| /* PasswordFile.java -- |
| Copyright (C) 2003, 2006 Free Software Foundation, Inc. |
| |
| This file is a part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or (at |
| your option) any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 |
| USA |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package gnu.javax.crypto.sasl.plain; |
| |
| import gnu.java.security.action.GetPropertyAction; |
| import gnu.javax.crypto.sasl.NoSuchUserException; |
| import gnu.javax.crypto.sasl.UserAlreadyExistsException; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.PrintWriter; |
| import java.security.AccessController; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.NoSuchElementException; |
| import java.util.StringTokenizer; |
| |
| /** |
| * A representation of a Plain password file. |
| */ |
| public class PasswordFile |
| { |
| private static String DEFAULT_FILE; |
| static |
| { |
| DEFAULT_FILE = (String) AccessController.doPrivileged |
| (new GetPropertyAction(PlainRegistry.PASSWORD_FILE, |
| PlainRegistry.DEFAULT_PASSWORD_FILE)); |
| } |
| private Hashtable entries; |
| private File passwdFile; |
| private long lastmod; |
| |
| public PasswordFile() throws IOException |
| { |
| this(DEFAULT_FILE); |
| } |
| |
| public PasswordFile(File pwFile) throws IOException |
| { |
| this(pwFile.getAbsolutePath()); |
| } |
| |
| public PasswordFile(String fileName) throws IOException |
| { |
| passwdFile = new File(fileName); |
| update(); |
| } |
| |
| public synchronized void add(String user, String passwd, String[] attributes) |
| throws IOException |
| { |
| checkCurrent(); |
| if (entries.containsKey(user)) |
| throw new UserAlreadyExistsException(user); |
| if (attributes.length != 5) |
| throw new IllegalArgumentException("Wrong number of attributes"); |
| // create the new entry |
| String[] fields = new String[7]; |
| fields[0] = user; |
| fields[1] = passwd; |
| System.arraycopy(attributes, 0, fields, 2, 5); |
| entries.put(user, fields); |
| savePasswd(); |
| } |
| |
| public synchronized void changePasswd(String user, String passwd) |
| throws IOException |
| { |
| checkCurrent(); |
| if (! entries.containsKey(user)) |
| throw new NoSuchUserException(user); |
| String[] fields = (String[]) entries.get(user); // get the existing entry |
| fields[1] = passwd; // modify the password field |
| entries.remove(user); // delete the existing entry |
| entries.put(user, fields); // add the new entry |
| savePasswd(); |
| } |
| |
| public synchronized String[] lookup(String user) throws IOException |
| { |
| checkCurrent(); |
| if (! entries.containsKey(user)) |
| throw new NoSuchUserException(user); |
| return (String[]) entries.get(user); |
| } |
| |
| public synchronized boolean contains(String s) throws IOException |
| { |
| checkCurrent(); |
| return entries.containsKey(s); |
| } |
| |
| private synchronized void update() throws IOException |
| { |
| lastmod = passwdFile.lastModified(); |
| readPasswd(new FileInputStream(passwdFile)); |
| } |
| |
| private void checkCurrent() throws IOException |
| { |
| if (passwdFile.lastModified() > lastmod) |
| update(); |
| } |
| |
| private synchronized void readPasswd(InputStream in) throws IOException |
| { |
| BufferedReader din = new BufferedReader(new InputStreamReader(in)); |
| String line; |
| entries = new Hashtable(); |
| String[] fields = new String[7]; |
| while ((line = din.readLine()) != null) |
| { |
| StringTokenizer st = new StringTokenizer(line, ":", true); |
| try |
| { |
| fields[0] = st.nextToken(); // username |
| st.nextToken(); |
| fields[1] = st.nextToken(); // passwd |
| if (fields[1].equals(":")) |
| fields[1] = ""; |
| else |
| st.nextToken(); |
| fields[2] = st.nextToken(); // uid |
| if (fields[2].equals(":")) |
| fields[2] = ""; |
| else |
| st.nextToken(); |
| fields[3] = st.nextToken(); // gid |
| if (fields[3].equals(":")) |
| fields[3] = ""; |
| else |
| st.nextToken(); |
| fields[4] = st.nextToken(); // gecos |
| if (fields[4].equals(":")) |
| fields[4] = ""; |
| else |
| st.nextToken(); |
| fields[5] = st.nextToken(); // dir |
| if (fields[5].equals(":")) |
| fields[5] = ""; |
| else |
| st.nextToken(); |
| fields[6] = st.nextToken(); // shell |
| if (fields[6].equals(":")) |
| fields[6] = ""; |
| } |
| catch (NoSuchElementException ignored) |
| { |
| continue; |
| } |
| entries.put(fields[0], fields); |
| } |
| } |
| |
| private synchronized void savePasswd() throws IOException |
| { |
| if (passwdFile != null) |
| { |
| FileOutputStream fos = new FileOutputStream(passwdFile); |
| PrintWriter pw = null; |
| try |
| { |
| pw = new PrintWriter(fos); |
| String key; |
| String[] fields; |
| StringBuffer sb; |
| Enumeration keys = entries.keys(); |
| while (keys.hasMoreElements()) |
| { |
| key = (String) keys.nextElement(); |
| fields = (String[]) entries.get(key); |
| sb = new StringBuffer(fields[0]); |
| for (int i = 1; i < fields.length; i++) |
| sb.append(":" + fields[i]); |
| pw.println(sb.toString()); |
| } |
| } |
| finally |
| { |
| if (pw != null) |
| try |
| { |
| pw.flush(); |
| } |
| finally |
| { |
| pw.close(); |
| } |
| if (fos != null) |
| try |
| { |
| fos.close(); |
| } |
| catch (IOException ignored) |
| { |
| } |
| lastmod = passwdFile.lastModified(); |
| } |
| } |
| } |
| } |