Source code: org/mortbay/util/Password.java
1 // ========================================================================
2 // Copyright (c) 1998 Mort Bay Consulting (Australia) Pty. Ltd.
3 // $Id: Password.java,v 1.10 2003/09/18 13:29:27 gregwilkins Exp $
4 // ========================================================================
5
6 package org.mortbay.util;
7 import java.io.IOException;
8
9 import org.apache.commons.logging.Log;
10 import org.apache.commons.logging.LogFactory;
11
12 /* ------------------------------------------------------------ */
13 /** Password utility class.
14 *
15 * This utility class gets a password or pass phrase either by:<PRE>
16 * + Password is set as a system property.
17 * + The password is prompted for and read from standard input
18 * + A program is run to get the password.
19 * </pre>
20 * Passwords that begin with OBF: are de obfuscated.
21 * Passwords can be obfuscated by run org.mortbay.util.Password as a
22 * main class. Obfuscated password are required if a system needs
23 * to recover the full password (eg. so that it may be passed to another
24 * system). They are not secure, but prevent casual observation.
25 * <p>
26 * Passwords that begin with CRYPT: are oneway encrypted with
27 * UnixCrypt. The real password cannot be retrieved, but comparisons
28 * can be made to other passwords. A Crype can be generated by running
29 * org.mortbay.util.UnixCrypt as a main class, passing password and
30 * then the username. Checksum passwords are a secure(ish) way to
31 * store passwords that only need to be checked rather
32 * than recovered. Note that it is not strong security - specially if
33 * simple passwords are used.
34 *
35 * @version $Id: Password.java,v 1.10 2003/09/18 13:29:27 gregwilkins Exp $
36 * @author Greg Wilkins (gregw)
37 */
38 public class Password extends Credential
39 {
40 private static Log log = LogFactory.getLog(Password.class);
41
42 private String _pw;
43
44 /* ------------------------------------------------------------ */
45 /** Constructor.
46 * @param password The String password.
47 */
48 public Password(String password)
49 {
50 _pw=password;
51
52 // expand password
53 while (_pw!=null && _pw.startsWith("OBF:"))
54 _pw=deobfuscate(_pw);
55 }
56
57 /* ------------------------------------------------------------ */
58 public String toString()
59 {
60 return _pw;
61 }
62
63 /* ------------------------------------------------------------ */
64 public String toStarString()
65 {
66 return "*****************************************************"
67 .substring(0,_pw.length());
68 }
69
70 /* ------------------------------------------------------------ */
71 public boolean check(Object credentials)
72 {
73 if (this == credentials)
74 return true;
75
76 if (credentials instanceof Password)
77 return credentials.equals(_pw);
78
79 if (credentials instanceof String)
80 return credentials.equals(_pw);
81
82 if (credentials instanceof Credential)
83 return ((Credential)credentials).check(_pw);
84
85 return false;
86 }
87
88 /* ------------------------------------------------------------ */
89 public boolean equals(Object o)
90 {
91 if (this == o)
92 return true;
93
94 if (null == o)
95 return false;
96
97 if (o instanceof Password)
98 {
99 Password p=(Password)o;
100 return p._pw == _pw || (null != _pw && _pw.equals(p._pw));
101 }
102
103 if (o instanceof String)
104 return o.equals(_pw);
105
106 return false;
107 }
108
109 /* ------------------------------------------------------------ */
110 public int hashCode() {
111 return null == _pw ? super.hashCode() : _pw.hashCode();
112 }
113
114 /* ------------------------------------------------------------ */
115 public static String obfuscate(String s)
116 {
117 StringBuffer buf = new StringBuffer();
118 byte[] b = s.getBytes();
119
120 synchronized(buf)
121 {
122 buf.append("OBF:");
123 for (int i=0;i<b.length;i++)
124 {
125 byte b1 = b[i];
126 byte b2 = b[s.length()-(i+1)];
127 int i1= (int)b1+(int)b2+127;
128 int i2= (int)b1-(int)b2+127;
129 int i0=i1*256+i2;
130 String x=Integer.toString(i0,36);
131
132 switch(x.length())
133 {
134 case 1:buf.append('0');
135 case 2:buf.append('0');
136 case 3:buf.append('0');
137 default:buf.append(x);
138 }
139 }
140 return buf.toString();
141 }
142 }
143
144 /* ------------------------------------------------------------ */
145 public static String deobfuscate(String s)
146 {
147 if (s.startsWith("OBF:"))
148 s=s.substring(4);
149
150 byte[] b=new byte[s.length()/2];
151 int l=0;
152 for (int i=0;i<s.length();i+=4)
153 {
154 String x=s.substring(i,i+4);
155 int i0 = Integer.parseInt(x,36);
156 int i1=(i0/256);
157 int i2=(i0%256);
158 b[l++]=(byte)((i1+i2-254)/2);
159 }
160
161 return new String(b,0,l);
162 }
163
164 /* ------------------------------------------------------------ */
165 /** Get a password.
166 * A password is obtained by trying <UL>
167 * <LI>Calling <Code>System.getProperty(realm,dft)</Code>
168 * <LI>Prompting for a password
169 * <LI>Using promptDft if nothing was entered.
170 * </UL>
171 * @param realm The realm name for the password, used as a SystemProperty name.
172 * @param dft The default password.
173 * @param promptDft The default to use if prompting for the password.
174 * @return Password
175 */
176 public static Password getPassword(String realm,String dft, String promptDft)
177 {
178 String passwd=System.getProperty(realm,dft);
179 if (passwd==null || passwd.length()==0)
180 {
181 try
182 {
183 System.out.print(realm+
184 ((promptDft!=null && promptDft.length()>0)
185 ?" [dft]":"")+" : ");
186 System.out.flush();
187 byte[] buf = new byte[512];
188 int len=System.in.read(buf);
189 if (len>0)
190 passwd=new String(buf,0,len).trim();
191 }
192 catch(IOException e)
193 {
194 log.warn(LogSupport.EXCEPTION,e);
195 }
196 if (passwd==null || passwd.length()==0)
197 passwd=promptDft;
198 }
199 return new Password(passwd);
200 }
201
202
203 /* ------------------------------------------------------------ */
204 /**
205 * @param arg
206 */
207 public static void main(String[] arg)
208 {
209 if (arg.length!=1 && arg.length!=2 )
210 {
211 System.err.println("Usage - java org.mortbay.util.Password [<user>] <password>");
212 System.err.println("If the password is ?, the user will be prompted for the password");
213 System.exit(1);
214 }
215 String p=arg[arg.length==1?0:1];
216 Password pw = "?".equals(p)?new Password(p):new Password(p);
217 System.err.println(pw.toString());
218 System.err.println(obfuscate(pw.toString()));
219 System.err.println(Credential.MD5.digest(p));
220 if (arg.length==2)
221 System.err.println(Credential.Crypt.crypt(arg[0],pw.toString()));
222 }
223 }
224
225