// // $Id$ // package org.dcache.srm.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.net.MalformedURLException; import java.net.UnknownHostException; /** * * @author Vladimir Podstavkov */ public class Pgpass { private static final Logger _logger = LoggerFactory.getLogger(Pgpass.class); private final String _pwdfile; private String _hostname; private String _port; private String _database; public Pgpass(String pwdfile) { _pwdfile = pwdfile; } private String process( String line, String hostname, String port, String database, String username) { if (line.charAt(0) != '#') { // System.out.println("process: "+line); String[] sa = line.split(":"); // for (int i = 0; i < sa.length; i++) { // System.out.print(sa[i]+","); // } // System.out.println(); boolean hostMatched =sa[0].equals("*") ; if(!hostMatched) { try { hostMatched = Tools.sameHost(sa[0],hostname); } catch(UnknownHostException uhe) { _logger.warn(uhe.toString()); } } if ( hostMatched && (sa[1].equals("*") || sa[1].equals(port)) && (sa[2].equals("*") || sa[2].equals(database)) && (sa[3].equals("*") || sa[3].equals(username)) ) { return sa[4]; } } return null; } private static final String legalFormats = "\n supported jdbc url formats:\n"+ " jdbc:postgresql:database\n"+ " jdbc:postgresql://host/database\n"+ " jdbc:postgresql://host:port/database\n"; private void parseUrl(String url) throws MalformedURLException { // -jdbcUrl=jdbc:postgresql:database // -jdbcUrl=jdbc:postgresql://host/database // -jdbcUrl=jdbc:postgresql://host:port/database String[] r = url.split("/"); _hostname = "localhost"; _port = "5432"; if (r.length==1) { String[] r1 = r[0].split(":"); _database = r1[r1.length-1]; } else if (r.length==4) { _database = r[r.length-1]; String[] r1 = r[2].split(":"); _hostname = r1[0]; if (r1.length==2) { _port = r1[1]; } else if (r1.length > 2) { String error = "illegal jdbc url format: "+url+legalFormats; _logger.error(error); throw new MalformedURLException(error); } } else { String error = "illegal jdbc url format: "+url+legalFormats; _logger.error(error); throw new MalformedURLException(error); } } public String getPgpass( String hostname, String port, String database, String username) throws IOException { // try{ Process p1 = Runtime.getRuntime().exec("stat -c '%a' "+_pwdfile); String reply; try (BufferedReader stdInput = new BufferedReader( new InputStreamReader(p1.getInputStream()))) { reply = stdInput.readLine(); try { p1.waitFor(); } catch (InterruptedException x) { _logger.error("stat for '" + _pwdfile + "' was interrupted", x); throw new InterruptedIOException("Cannot stat '" + _pwdfile + "'"); } } // System.out.println("mode: '"+reply+"'"); if (reply==null) { _logger.error("Cannot stat '"+_pwdfile+"'"); throw new IOException("Cannot stat '"+_pwdfile+"'"); } else if (!reply.equals("'600'")) { _logger.error("Protection for '"+_pwdfile+"' must be '600'"); throw new IOException("Protection for '"+_pwdfile+"' must be '600'"); } /* * Here we can read and parse the password file */ String r = null; try (BufferedReader in = new BufferedReader(new FileReader(_pwdfile))) { String line; while ((line = in.readLine()) != null && r == null) { r = process(line, hostname, port, database, username); // System.out.println("->"+r); } } if(r == null) { String error = String.format("could not get password from '%s' "+ "for hostname: '%s' ,port: %s ,database: '%s' " + "and username: '%s' ",_pwdfile,hostname,port,database,username); _logger.error(error); throw new IOException(error); } return r; } catch (IOException ioe) { _logger.error("processing '"+_pwdfile+"' failed: I/O error",ioe); throw new IOException("processing '"+_pwdfile+"' failed: I/O error",ioe); } } public String getPgpass(String url, String username) throws IOException { parseUrl(url); return getPgpass(_hostname, _port, _database, username); } public String getHostname() { return _hostname; } public String getPort() { return _port; } public String getDatabase() { return _database; } }