1 18 package sync4j.server.security; 19 20 import java.util.HashMap ; 21 import java.util.logging.Logger ; 22 import java.util.logging.Level ; 23 24 import java.security.Principal ; 25 import javax.security.auth.*; 26 import javax.security.auth.login.*; 27 import javax.security.*; 28 29 import sync4j.framework.security.Officer; 30 import sync4j.framework.security.Sync4jPrincipal; 31 import sync4j.framework.logging.Sync4jLogger; 32 import sync4j.framework.core.Cred; 33 import sync4j.framework.core.Authentication; 34 import sync4j.framework.server.Sync4jDevice; 35 import sync4j.framework.config.ConfigurationConstants; 36 import sync4j.framework.tools.MD5; 37 import sync4j.framework.tools.Base64; 38 import sync4j.framework.server.Sync4jUser; 39 import sync4j.framework.server.store.PersistentStore; 40 import sync4j.framework.server.store.PersistentStoreException; 41 import sync4j.framework.server.store.WhereClause; 42 import sync4j.framework.server.store.LogicalClause; 43 import sync4j.framework.config.ConfigurationConstants; 44 import sync4j.server.config.Configuration; 45 import sync4j.server.admin.UserManager; 46 47 54 public class DBOfficer implements Officer, java.io.Serializable { 55 56 58 protected transient Logger log = Sync4jLogger.getLogger(); 59 protected PersistentStore ps = null; 60 protected UserManager userManager = null; 61 62 65 68 private boolean loginFailed = false; 69 70 public boolean isLoginFailed() { 71 return loginFailed; 72 } 73 74 77 private boolean loginExpired = false; 78 79 82 private String clientAuth = Cred.AUTH_TYPE_BASIC; 83 84 public String getClientAuth() { 85 return this.clientAuth; 86 } 87 public void setClientAuth(String clientAuth) { 88 this.clientAuth = clientAuth; 89 } 90 91 94 private String serverAuth = Cred.AUTH_NONE; 95 public String getServerAuth() { 96 return this.serverAuth; 97 } 98 99 public void setServerAuth(String serverAuth) { 100 this.serverAuth = serverAuth; 101 } 102 103 105 112 public boolean authenticate(Cred credential) { 113 Configuration config = Configuration.getConfiguration(); 114 ps = config.getStore(); 115 116 userManager = (UserManager)config.getUserManager(); 117 118 String type = credential.getType(); 119 120 if ((Cred.AUTH_TYPE_BASIC).equals(type)) { 121 return authenticateBasicCredential(credential); 122 } else if ( (Cred.AUTH_TYPE_MD5).equals(type) ) { 123 String syncMLVerProto = 124 credential.getAuthentication().getSyncMLVerProto(); 125 if (syncMLVerProto.indexOf("1.0") != -1) { 130 return authenticateMD5Credential10(credential); 131 } else if (syncMLVerProto.indexOf("1.1") != -1) { 132 return authenticateMD5Credential11(credential); 133 } 134 } else if ( (Cred.AUTH_TYPE_HMAC).equals(type) ) { 135 return false; 136 } 137 return false; 138 } 139 140 private boolean authenticateBasicCredential(Cred credential) { 141 Sync4jUser[] users = null; 142 String username = null, password = null; 143 Sync4jPrincipal principal = null; 144 145 Authentication auth = credential.getAuthentication(); 146 String deviceId = auth.getDeviceId(); 147 String userpwd = new String (Base64.decode(auth.getData())); 148 149 int p = userpwd.indexOf(':'); 150 151 if (p == -1) { 152 username = userpwd; 153 password = ""; 154 } else { 155 username = (p>0) ? userpwd.substring(0, p) : ""; 156 password = (p == (userpwd.length()-1)) ? "" : userpwd.substring(p+1); 157 } 158 159 if (log.isLoggable(Level.FINEST)) { 160 log.finest("Username: " + username); 161 } 162 163 try { 167 principal = new Sync4jPrincipal(username, deviceId); 168 ps.read(principal); 169 credential.getAuthentication().setPrincipalId(principal.getId()); 170 } catch(PersistentStoreException e) { 171 log.severe("Error reading principal: " + e); 172 log.throwing(getClass().getName(), "authenticateBasicCredential", e); 173 return false; 174 } 175 176 try { 177 WhereClause[] wc = new WhereClause[2]; 178 String value[] = new String [1]; 179 value[0] = username; 180 wc[0] = new WhereClause("username",value, WhereClause.OPT_EQ, true); 181 182 value = new String [1]; 183 value[0] = password; 184 wc[1] = new WhereClause("password",value, WhereClause.OPT_EQ, true); 185 LogicalClause lc = new LogicalClause(LogicalClause.OPT_AND, wc); 186 187 users = userManager.getUsers(lc); 188 if (users.length == 1) { 189 return true; 190 } 191 192 } catch(PersistentStoreException e) { 193 log.severe("Error reading user: " + e); 194 log.throwing(getClass().getName(), "authenticateBasicCredential", e); 195 return false; 196 } 197 198 199 return false; 200 } 201 private boolean authenticateMD5Credential10(Cred credential) { 202 Sync4jPrincipal principals[] = null ; 203 boolean isFindDigest = false; 204 String password = null ; 205 String username = null ; 206 String usernamepwd = null ; 207 208 Authentication auth = credential.getAuthentication(); 209 String deviceId = auth.getDeviceId(); 210 211 WhereClause whereClause = new WhereClause("device", 215 new String [] {deviceId}, 216 WhereClause.OPT_EQ, 217 true); 218 try { 219 principals = (Sync4jPrincipal[])ps.read( 220 new Sync4jPrincipal(null, deviceId), 221 whereClause 222 ); 223 } catch(PersistentStoreException e) { 224 log.severe("Error reading principals: " + e); 225 log.throwing(getClass().getName(), "authenticateMD5Credential11", e); 226 return false; 227 } 228 int size = principals.length; 232 for (int i=0; i<size; i++) { 233 Sync4jUser user = new Sync4jUser(principals[i].getUsername(), null, null, null, null, null); 234 235 try { 236 userManager.getUser(user); 237 } catch(PersistentStoreException e) { 238 log.severe("Error reading user: " + e); 239 log.throwing(getClass().getName(), "authenticateMD5Credential11", e); 240 } 241 242 username = user.getUsername(); 246 password = user.getPassword(); 247 usernamepwd = username + ':' + password; 248 byte[] usernamepwdBytes = usernamepwd.getBytes(); 249 250 byte[] clientNonce = auth.getNextNonce().getValue(); 251 252 if (log.isLoggable(Level.FINEST)) { 253 log.finest("username: " + username); 254 log.finest("password: " + password); 255 log.finest("clientNonce : " + new String (Base64.encode(clientNonce))); 256 } 257 258 byte[] buf = new byte[usernamepwdBytes.length + 1 + clientNonce.length]; 264 265 System.arraycopy(usernamepwdBytes, 0, buf, 0, usernamepwdBytes.length); 266 buf[usernamepwdBytes.length] = (byte)':'; 267 System.arraycopy(clientNonce, 0, buf, usernamepwdBytes.length+1, clientNonce.length); 268 269 byte[] digest = MD5.digest(buf); 270 271 String serverDigestNonceB64 = new String (Base64.encode(digest)); 275 276 String msgDigestNonceB64 = auth.getData(); 280 281 if (log.isLoggable(Level.FINEST)) { 282 log.finest("serverDigestNonceB64: " + serverDigestNonceB64); 283 log.finest("msgDigestNonceB64: " + msgDigestNonceB64 ); 284 } 285 286 if (msgDigestNonceB64.equals(serverDigestNonceB64)) { 287 credential.getAuthentication().setPrincipalId(principals[i].getId()); 288 isFindDigest = true; 289 break; 290 } 291 } 292 293 if (!isFindDigest) { 294 return false; 295 } 296 297 auth.setUsername(usernamepwd); 298 credential.setAuthentication(auth); 299 return true; 300 } 301 302 private boolean authenticateMD5Credential11(Cred credential) { 303 Sync4jPrincipal principals[] = null ; 304 boolean isFindDigest = false; 305 String password = null ; 306 String username = null ; 307 byte[] userDigestB64 = null ; 308 309 Authentication auth = credential.getAuthentication(); 310 String deviceId = auth.getDeviceId(); 311 312 WhereClause whereClause = new WhereClause("device", 316 new String [] {deviceId}, 317 WhereClause.OPT_EQ, 318 true); 319 try { 320 principals = (Sync4jPrincipal[])ps.read( 321 new Sync4jPrincipal(null, deviceId), 322 whereClause 323 ); 324 } catch(PersistentStoreException e) { 325 log.severe("Error reading principals: " + e); 326 log.throwing(getClass().getName(), "authenticateMD5Credential11", e); 327 return false; 328 } 329 int size = principals.length; 333 for (int i=0; i<size; i++) { 334 Sync4jUser user = new Sync4jUser(principals[i].getUsername(), null, null, null, null, null); 335 336 try { 337 userManager.getUser(user); 338 } catch(PersistentStoreException e) { 339 log.severe("Error reading user: " + e); 340 log.throwing(getClass().getName(), "authenticateMD5Credential11", e); 341 } 342 343 username = user.getUsername(); 347 password = user.getPassword(); 348 349 byte[] userDigest = MD5.digest((new String (username + ':' + password)).getBytes()); 350 userDigestB64 = Base64.encode(userDigest); 351 352 byte[] clientNonce = auth.getNextNonce().getValue(); 353 354 if (log.isLoggable(Level.FINEST)) { 355 log.finest("userDigestB64: " + new String (userDigestB64)); 356 log.finest("clientNonce : " + new String (Base64.encode(clientNonce))); 357 } 358 359 byte[] buf = new byte[userDigestB64.length + 1 + clientNonce.length]; 365 366 System.arraycopy(userDigestB64, 0, buf, 0, userDigestB64.length); 367 buf[userDigestB64.length] = (byte)':'; 368 System.arraycopy(clientNonce, 0, buf, userDigestB64.length+1, clientNonce.length); 369 370 byte[] digest = MD5.digest(buf); 371 372 String serverDigestNonceB64 = new String (Base64.encode(digest)); 376 377 String msgDigestNonceB64 = auth.getData(); 381 382 if (log.isLoggable(Level.FINEST)) { 383 log.finest("serverDigestNonceB64: " + serverDigestNonceB64); 384 log.finest("msgDigestNonceB64: " + msgDigestNonceB64 ); 385 } 386 387 if (msgDigestNonceB64.equals(serverDigestNonceB64)) { 388 credential.getAuthentication().setPrincipalId(principals[i].getId()); 389 isFindDigest = true; 390 break; 391 } 392 } 393 394 if (!isFindDigest) { 395 return false; 396 } 397 auth.setUsername(new String (userDigestB64)); 398 credential.setAuthentication(auth); 399 return true; 400 } 401 402 411 public boolean authorize(Principal principal, String resource) { 412 return true; 413 } 414 415 419 public void unAuthenticate(Cred credential) { 420 } 425 426 429 public boolean isAccountExpired() { 430 return loginExpired; 431 } 432 433 434 private void readObject(java.io.ObjectInputStream in) 435 throws java.io.IOException , ClassNotFoundException { 436 in.defaultReadObject(); 437 log = Sync4jLogger.getLogger(); 438 } 439 } | Popular Tags |