View Javadoc
1 /* 2 * $Header: /cvsroot/ebxmlrr/ebxmlrr/src/share/com/sun/ebxml/registry/security/authentication/AuthenticationServiceImpl.java,v 1.27 2003/06/20 14:35:05 farrukh_najmi Exp $ 3 * 4 * ==================================================================== 5 * 6 * This code is subject to the freebxml License, Version 1.1 7 * 8 * Copyright (c) 2003 freebxml.org. All rights reserved. 9 * 10 * ==================================================================== 11 */ 12 13 package com.sun.ebxml.registry.security.authentication; 14 15 import com.sun.ebxml.registry.RegistryException; 16 import com.sun.ebxml.registry.security.UserRegistrationException; 17 import com.sun.ebxml.registry.util.RegistryProperties; 18 import java.io.IOException; 19 import java.security.KeyStore; 20 import java.security.KeyStoreException; 21 import java.security.NoSuchAlgorithmException; 22 import java.security.cert.X509Certificate; 23 import org.oasis.ebxml.registry.bindings.rim.User; 24 25 /*** 26 * Manages authentication functionality for the registry. 27 * This includes managemnet of user public keys in the server key store. 28 * 29 * @author <a href="mailto:Farrukh.Najmi@Sun.COM">Farrukh S. Najmi</a> 30 */ 31 public class AuthenticationServiceImpl /*implements AuthenticationService*/ { 32 33 /* Aliases/ids for pre-defined Users.*/ 34 public static String ALIAS_REGISTRY_OPERATOR = "urn:uuid:921284f0-bbed-4a4c-9342-ecaf0625f9d7"; 35 public static String ALIAS_REGISTRY_GUEST = "urn:uuid:abfa78d5-605e-4dbc-b9ee-a42e99d5f7cf"; 36 37 /* Aliases/ids for test Users */ 38 public static String ALIAS_FARRUKH = "urn:uuid:977d9380-00e2-4ce8-9cdc-d8bf6a4157be"; 39 public static String ALIAS_NIKOLA = "urn:uuid:85428d8e-1bd5-473b-a8c8-b9d595f82728"; 40 public static String ALIAS_CY = "urn:uuid:b2691323-4aad-46da-9dc7-a842b7e4b1ae"; 41 public static String ALIAS_ADRIAN = "urn:uuid:bab82b84-7d63-44dd-b914-e72e0476c043"; 42 43 private org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(this.getClass()); 44 45 /*** 46 * @link 47 * @shapeType PatternLink 48 * @pattern Singleton 49 * @supplierRole Singleton factory 50 */ 51 /*# private AuthenticationServiceImpl _authenticationServiceImpl; */ 52 private static AuthenticationServiceImpl instance = null; 53 54 KeyStore keyStore = null; 55 /* A lock object to prevent another thread to access the keystore when 56 * there is a thread adding certificate to it and writing it to disk 57 */ 58 Object keyStoreWriteLock = new Object(); 59 KeyStore trustAnchorsKeyStore; 60 User registryGuest = null; 61 User registryOperator = null; 62 java.util.ArrayList userCache = new java.util.ArrayList(); 63 java.util.HashMap userMap = new java.util.HashMap(); 64 java.util.HashSet adminIdSet = new java.util.HashSet(); 65 66 final int cacheSize; 67 RegistryProperties propsReader = RegistryProperties.getInstance(); 68 69 protected AuthenticationServiceImpl() { 70 String userCacheSize = RegistryProperties.getInstance().getProperty("ebxmlrr.security.userCacheSize"); 71 loadRegistryAdministrators(); 72 cacheSize = Integer.parseInt(userCacheSize); 73 } 74 75 public KeyStore getTrustAnchorsKeyStore() throws RegistryException { 76 try { 77 if (trustAnchorsKeyStore==null) { 78 synchronized(AuthenticationServiceImpl.class) { 79 if (trustAnchorsKeyStore==null) { 80 String keyStoreFile = propsReader.getProperty("ebxmlrr.security.trustAnchors.keystoreFile"); 81 String keystorePassword = propsReader.getProperty("ebxmlrr.security.trustAnchors.keystorePassword"); 82 String keystoreType = propsReader.getProperty("ebxmlrr.security.trustAnchors.keystoreType"); 83 trustAnchorsKeyStore = KeyStore.getInstance(keystoreType); 84 trustAnchorsKeyStore.load(new java.io.FileInputStream(keyStoreFile), keystorePassword.toCharArray()); 85 } 86 } 87 } 88 return trustAnchorsKeyStore; 89 } 90 catch (NoSuchAlgorithmException e) { 91 throw new RegistryException("Cannot load the trust anchors keystore", e); 92 } 93 catch (KeyStoreException e) { 94 throw new RegistryException("Cannot load the trust anchors keystore", e); 95 } 96 catch (java.security.cert.CertificateException e) { 97 throw new RegistryException("Cannot load the trust anchors keystore", e); 98 } 99 catch (java.io.FileNotFoundException e) { 100 throw new RegistryException("Cannot load the trust anchors keystore", e); 101 } 102 catch (IOException e) { 103 throw new RegistryException("Cannot load the trust anchors keystore", e); 104 } 105 } 106 107 /*** 108 * Get the keystore whose path is specified by {@link #getKeyStoreFileName()}. 109 * Note that all the methods that access the keystore MUST access the keystore 110 * via this method. Do not access the keystore directly by accessing the keystore 111 * field. Otherwise the checking the write lock to keystore will be bypassed. 112 */ 113 public KeyStore getKeyStore() throws RegistryException { 114 synchronized(keyStoreWriteLock) { 115 if (keyStore == null) { 116 117 java.io.FileInputStream fis = null; 118 try { 119 keyStore = KeyStore.getInstance("JKS"); 120 121 String keystoreFile = getKeyStoreFileName(); 122 fis = new java.io.FileInputStream(keystoreFile); 123 124 String keystorePass = getKeyStorePassword(); 125 keyStore.load(fis, keystorePass.toCharArray()); 126 } 127 catch (java.security.cert.CertificateException e) { 128 throw new RegistryException(e); 129 } 130 catch (KeyStoreException e) { 131 throw new RegistryException(e); 132 } 133 catch (NoSuchAlgorithmException e) { 134 throw new RegistryException(e); 135 } 136 catch (java.io.FileNotFoundException e) { 137 throw new RegistryException(e); 138 } 139 catch (IOException e) { 140 throw new RegistryException(e); 141 } 142 finally { 143 if (fis != null) { 144 try { 145 fis.close(); 146 } 147 catch (IOException e) { 148 e.printStackTrace(); 149 } 150 } 151 152 } 153 } 154 return keyStore; 155 } 156 } 157 158 public java.security.PrivateKey getPrivateKey(String alias, String password) throws RegistryException { 159 java.security.PrivateKey privateKey =null; 160 161 try { 162 privateKey = (java.security.PrivateKey) getKeyStore().getKey(alias, password.toCharArray()); 163 } 164 catch (KeyStoreException e) { 165 throw new RegistryException("Error getting private key", e); 166 } 167 catch (NoSuchAlgorithmException e) { 168 throw new RegistryException("Error getting private key", e); 169 } 170 catch (java.security.UnrecoverableKeyException e) { 171 throw new RegistryException("Error getting private key", e); 172 } 173 return privateKey; 174 } 175 176 public X509Certificate getCertificate(String alias) throws RegistryException { 177 X509Certificate cert =null; 178 179 try { 180 cert = (X509Certificate) getKeyStore().getCertificate(alias); 181 if (cert == null) { 182 throw new RegistryException("Certificate not found for alias '" + alias + "'"); 183 } 184 } 185 catch (KeyStoreException e) { 186 throw new RegistryException("Error getting certificate", e); 187 } 188 return cert; 189 } 190 191 public java.security.cert.Certificate [] getCertificateChain(String alias) throws RegistryException { 192 try { 193 return getKeyStore().getCertificateChain(alias); 194 } 195 catch (KeyStoreException e) { 196 throw new RegistryException("Error getting certificate chain", e); 197 } 198 } 199 200 public static AuthenticationServiceImpl getInstance() { 201 if (instance == null) { 202 synchronized(com.sun.ebxml.registry.security.authentication.AuthenticationServiceImpl.class) { 203 if (instance == null) { 204 instance = new com.sun.ebxml.registry.security.authentication.AuthenticationServiceImpl(); 205 } 206 } 207 } 208 return instance; 209 } 210 211 public String getKeyStoreFileName() throws RegistryException { 212 String fileName = RegistryProperties.getInstance().getProperty("ebxmlrr.security.keystoreFile"); 213 return fileName; 214 } 215 216 public String getKeyStorePassword() throws RegistryException { 217 String pw = RegistryProperties.getInstance().getProperty("ebxmlrr.security.keystorePassword"); 218 return pw; 219 } 220 221 /*** 222 * Check if the signatures CA is trusted by the registry. 223 * 224 * @throws UserRegistrationException if the certificate issuing CA is not trusted. 225 * @throws RegistryException if the certificates cannot be verified for some other reasons, such as unable to load 226 * trust anchors keystore 227 */ 228 public void validateCertificate(org.apache.xml.security.signature.XMLSignature signature) throws UserRegistrationException, RegistryException { 229 try { 230 java.security.cert.CertPathBuilder certPathBuilder = java.security.cert.CertPathBuilder.getInstance("PKIX"); 231 java.security.cert.X509CertSelector targetConstraints = new java.security.cert.X509CertSelector(); 232 233 org.apache.xml.security.keys.KeyInfo keyInfo = signature.getKeyInfo(); 234 int lengthX509Data = keyInfo.lengthX509Data(); 235 for (int i=0; i < lengthX509Data; i++) { 236 org.apache.xml.security.keys.content.X509Data x509Data = keyInfo.itemX509Data(i); 237 X509Certificate x509Certificate = x509Data.itemCertificate(0).getX509Certificate(); 238 targetConstraints.setSubject(x509Certificate.getSubjectX500Principal().getEncoded()); 239 } 240 java.security.cert.PKIXBuilderParameters params = new java.security.cert.PKIXBuilderParameters(getTrustAnchorsKeyStore() 241 , targetConstraints); 242 java.security.cert.CollectionCertStoreParameters ccsp = new java.security.cert.CollectionCertStoreParameters(); 243 java.security.cert.CertStore store = java.security.cert.CertStore.getInstance("Collection", ccsp); 244 params.addCertStore(store); 245 certPathBuilder.build(params).getCertPath(); 246 } 247 catch (NoSuchAlgorithmException e) { 248 throw new RegistryException("Cannot verify the certificates", e); 249 } 250 catch (org.apache.xml.security.exceptions.XMLSecurityException e) { 251 throw new RegistryException("Cannot verify the certificates", e); 252 } 253 catch (IOException e) { 254 throw new RegistryException("Cannot verify the certificates", e); 255 } 256 catch (KeyStoreException e) { 257 throw new RegistryException("Cannot verify the certificates", e); 258 } 259 catch(java.security.InvalidAlgorithmParameterException e) { 260 throw new RegistryException("Cannot verify the certificates", e); 261 } 262 catch(java.security.cert.CertPathBuilderException e) { 263 throw new UserRegistrationException("User registration fails. The certificate is not " + 264 "issued by the trusted certificate authority", e); 265 } 266 } 267 268 /*** 269 * Gets the alias within the KeyStore for a User 270 */ 271 public String getAliasFromUser(User user) throws RegistryException { 272 return user.getId(); 273 } 274 275 /*** 276 * Gets the alias within the KeyStore for a User 277 */ 278 public X509Certificate getCertificateFromUser(User user) throws RegistryException { 279 X509Certificate cert = null; 280 try { 281 String alias = getAliasFromUser(user); 282 283 cert = (X509Certificate)(getKeyStore().getCertificate(alias)); 284 } 285 catch (KeyStoreException e) { 286 throw new RegistryException(e); 287 } 288 289 return cert; 290 } 291 292 /*** 293 * Gets the User that is associated with the KeyInfo provided within the XMLSignature signature. 294 * 295 * @throws RegistryException no matching User is found. May need more specific Exception?? 296 */ 297 public User getUserFromAlias(String alias) throws RegistryException { 298 User user = null; 299 300 String userId = alias; 301 302 /* 303 if (alias.equals(ALIAS_REGISTRY_GUEST) && registryGuest != null) { 304 return registryGuest; 305 } 306 else if (alias.equals(ALIAS_REGISTRY_OPERATOR) && registryOperator != null) { 307 return registryOperator; 308 } 309 else { 310 int index = userCache.indexOf(alias); 311 // cache hit 312 if (index != -1) { 313 userCache.add((String) userCache.remove(index)); 314 return (User) userMap.get(alias); 315 } 316 } 317 */ 318 319 com.sun.ebxml.registry.persistence.rdb.UserDAO userDAO = new com.sun.ebxml.registry.persistence.rdb.UserDAO(); 320 String sqlQuery = "SELECT id FROM " + 321 userDAO.getTableName() + " WHERE id='" + 322 userId + "'"; 323 324 org.oasis.ebxml.registry.bindings.query.ResponseOption responseOption = new org.oasis.ebxml.registry.bindings.query.ResponseOption(); 325 326 responseOption.setReturnType(org.oasis.ebxml.registry.bindings.query.types.ReturnTypeType.LEAFCLASS); 327 responseOption.setReturnComposedObjects(true); 328 329 330 org.oasis.ebxml.registry.bindings.query.SQLQueryResult sqlQueryResult = com.sun.ebxml.registry.query.sql.SQLQueryProcessor. 331 getInstance().executeQuery(null, sqlQuery, responseOption). 332 getSQLQueryResult(); 333 334 if (sqlQueryResult.getLeafRegistryObjectListTypeItemCount() > 0) { 335 user = sqlQueryResult.getLeafRegistryObjectListTypeItem(0).getUser(); 336 } 337 338 if (user == null) { 339 throw new com.sun.ebxml.registry.security.UserNotFoundException(userId); 340 } 341 342 //See if User need to be auto-classified as RegistryAdministrator 343 boolean isAdmin = isRegistryAdministrator(user); 344 345 if (isAdmin) { 346 //Make sure that the user is classified with the RegistryAdministrator role 347 makeRegistryAdministrator(user); 348 } 349 350 /* 351 if (alias.equals(ALIAS_REGISTRY_GUEST)) { 352 registryGuest = user; 353 } 354 else if (alias.equals(ALIAS_REGISTRY_OPERATOR)) { 355 registryOperator = user; 356 } 357 else { 358 if (userCache.size() == cacheSize) { 359 userMap.remove((String) userCache.get(0)); 360 userCache.remove(0); 361 } 362 userCache.add(alias); 363 userMap.put(alias, user); 364 } 365 */ 366 367 return user; 368 } 369 370 /*** 371 * See if User is declared as a RegistryAdministrator in prop file. 372 */ 373 private boolean isRegistryAdministrator(User user) throws RegistryException { 374 boolean isAdmin = false; 375 376 if (user != null) { 377 String id = user.getId(); 378 if (adminIdSet.contains(id)) { 379 isAdmin = true; 380 } 381 } 382 383 return isAdmin; 384 } 385 386 /*** 387 * Make sure user gets auto-classified as RegistryAdministrator if not so already. 388 */ 389 private void makeRegistryAdministrator(User user) throws RegistryException { 390 if (user != null) { 391 com.sun.ebxml.registry.security.authorization.AuthorizationServiceImpl az = 392 com.sun.ebxml.registry.security.authorization.AuthorizationServiceImpl.getInstance(); 393 394 boolean isAdmin = az.isRegistryAdministrator(user); 395 if (!isAdmin) { 396 org.oasis.ebxml.registry.bindings.rim.Classification classification = new org.oasis.ebxml.registry.bindings.rim.Classification(); 397 classification.setClassificationNode(az.CANONICAL_ID_NODE_REGISTRY_ADMINISTRATOR); 398 classification.setClassifiedObject(user); 399 user.addClassification(classification); 400 401 //Now persists updated User 402 com.sun.ebxml.registry.persistence.PersistenceManagerImpl pm = 403 com.sun.ebxml.registry.persistence.PersistenceManagerImpl.getInstance(); 404 405 java.util.ArrayList al = new java.util.ArrayList(); 406 al.add(user); 407 pm.update(user, al); 408 } 409 } 410 } 411 412 413 /* 414 * Loads the list of RegistryAdministrators from the property file during startup. 415 */ 416 private void loadRegistryAdministrators() { 417 String adminList = RegistryProperties.getInstance().getProperty("ebxmlrr.security.authorization.registryAdministrators"); 418 419 if (adminList != null) { 420 java.util.StringTokenizer tokenizer = 421 new java.util.StringTokenizer(adminList, "|" ); 422 423 while ( tokenizer.hasMoreTokens() ) { 424 try { 425 String adminId = tokenizer.nextToken(); 426 427 log.info("getRegistryAdministrators: adding admin '" + adminId + "'"); 428 adminIdSet.add(adminId); 429 } catch ( Exception e ) { 430 e.printStackTrace(); 431 } 432 } 433 } 434 else { 435 System.err.println("Registry has not defined RegistryAdministrators yet. This can be done by setting the ebxmlrr.security.authorization.registryAdministrators property in ebxmlrr.properties file."); 436 } 437 } 438 439 /*** 440 * Gets the User that is associated with the KeyInfo provided within the XMLSignature signature. 441 * 442 * @throws RegistryException no matching User is found. May need more specific Exception?? 443 */ 444 public User getUserFromXMLSignature(org.apache.xml.security.signature.XMLSignature signature) throws RegistryException { 445 User user = null; 446 447 //The registry expects the KeyInfo to either have the PublicKey or the DN from the public key 448 //In case of DN the registry can lookup the public key based on the DN 449 450 java.security.PublicKey publicKey = null; 451 X509Certificate cert = null; 452 String alias = null; 453 454 try { 455 org.apache.xml.security.keys.KeyInfo keyInfo = signature.getKeyInfo(); 456 for (int i=0 ; i<keyInfo.lengthKeyName() ; i++) { 457 String keyName = keyInfo.itemKeyName(i).getKeyName(); 458 log.info("getUserFromXMLSignature: KeyName=" + keyName); 459 if (keyName.startsWith("urn:uuid:")) { 460 alias = keyName; 461 break; 462 } 463 } 464 465 log.info("getUserFromXMLSignature: alias=" + alias); 466 467 if (alias == null) { 468 publicKey = keyInfo.getPublicKey(); 469 cert = keyInfo.getX509Certificate(); 470 471 alias = getKeyStore().getCertificateAlias(cert); 472 } 473 log.info("getUserFromXMLSignature: alias from publicKey=" + alias); 474 475 } 476 catch (KeyStoreException e) { 477 throw new RegistryException(e); 478 } 479 catch (org.apache.xml.security.keys.keyresolver.KeyResolverException e) { 480 throw new RegistryException(e); 481 } 482 catch (org.apache.xml.security.exceptions.XMLSecurityException e) { 483 throw new RegistryException(e); 484 } 485 486 487 user = getUserFromAlias(alias); 488 log.info("getUserFromXMLSignature: user=" + user); 489 return user; 490 } 491 492 /*** 493 * Compares two certificates. It will compare the issuerUniqueID and subjectUniqueID 494 * fields of the certificates. If either certificate does not contain either 495 * field, it will return false. 496 */ 497 private boolean certificatesAreSame(X509Certificate cert, X509Certificate oldCert) throws RegistryException { 498 499 boolean [] certIssuerID = cert.getIssuerUniqueID(); 500 boolean [] oldCertIssuerID = oldCert.getIssuerUniqueID(); 501 502 if (certIssuerID == null || oldCertIssuerID == null || 503 certIssuerID.length != oldCertIssuerID.length) { 504 return false; 505 } 506 507 for(int i=0; i < certIssuerID.length; i++) { 508 if (certIssuerID[i] != oldCertIssuerID[i]) { 509 return false; 510 } 511 } 512 513 boolean [] certSubjectID = cert.getSubjectUniqueID(); 514 boolean [] oldCertSubjectID = oldCert.getSubjectUniqueID(); 515 516 if (certSubjectID == null || oldCertSubjectID == null || certSubjectID.length != 517 oldCertSubjectID.length) { 518 return false; 519 } 520 521 for(int i=0; i < certSubjectID.length; i++) { 522 if (certSubjectID[i] != oldCertSubjectID[i]) { 523 return false; 524 } 525 } 526 527 return true; 528 } 529 530 /*** 531 * Add a certificate entry in the keystore. 532 * @param userId The alias of the certificate 533 * @param signature The XMLSignature containing the certificate 534 * @throws UserRegistration fails if the keystore already contrains the entry 535 * whose alias is equal to userId 536 */ 537 protected void registerUserCertificate(String userId, org.apache.xml.security.signature.XMLSignature signature) throws RegistryException { 538 539 java.io.FileOutputStream fos = null; 540 try { 541 org.apache.xml.security.keys.KeyInfo keyInfo = signature.getKeyInfo(); 542 java.security.PublicKey publicKey = keyInfo.getPublicKey(); 543 // The first certificate is assumed as target certificate 544 X509Certificate cert = keyInfo.getX509Certificate(); 545 546 KeyStore keyStore = getKeyStore(); 547 548 // Check if already in store 549 X509Certificate oldCert = null; 550 try { 551 oldCert = getCertificate(userId); 552 } 553 catch (Exception e) { 554 } 555 //System.err.println("Checking the certificates are the same..."); 556 557 if (oldCert != null && !certificatesAreSame(cert, oldCert)) { 558 throw new UserRegistrationException("User registration fails. " 559 + "The user with id '" + userId + "' already exists. " 560 + "If the certificate is recently updatd, replacement of the " 561 + "old certificate in last registration is not allowed"); 562 } 563 /* 564 Add the cert. to the keystore if the cert. does not exist yet 565 */ 566 if (oldCert == null) { 567 if (propsReader.getProperty("ebxmlrr.security.validateCertificates").trim().equals("true")) { 568 validateCertificate(signature); 569 } 570 synchronized (keyStoreWriteLock) { 571 keyStore.setCertificateEntry(userId, cert); 572 String keystoreFile = getKeyStoreFileName(); 573 fos = new java.io.FileOutputStream(keystoreFile); 574 575 String keystorePass = getKeyStorePassword(); 576 keyStore.store(fos, keystorePass.toCharArray()); 577 fos.flush(); 578 fos.close(); 579 this.keyStore = null; 580 } 581 } 582 } 583 catch (KeyStoreException e) { 584 throw new UserRegistrationException(e); 585 } 586 catch (org.apache.xml.security.keys.keyresolver.KeyResolverException e) { 587 throw new UserRegistrationException(e); 588 } 589 catch (org.apache.xml.security.exceptions.XMLSecurityException e) { 590 throw new UserRegistrationException(e); 591 } 592 catch (IOException e) { 593 throw new UserRegistrationException(e); 594 } 595 catch (NoSuchAlgorithmException e) { 596 throw new UserRegistrationException(e); 597 } 598 catch (java.security.cert.CertificateException e) { 599 throw new UserRegistrationException(e); 600 } 601 finally { 602 if (fos != null) { 603 try { 604 fos.close(); 605 } 606 catch (IOException e) { 607 e.printStackTrace(); 608 } 609 } 610 611 } 612 613 } 614 615 616 public static void main(String[] args) throws Exception { 617 618 com.sun.ebxml.registry.security.authorization.AuthorizationServiceImpl az = 619 com.sun.ebxml.registry.security.authorization.AuthorizationServiceImpl.getInstance(); 620 AuthenticationServiceImpl service = AuthenticationServiceImpl.getInstance(); 621 String alias = "urn:uuid:85428d8e-1bd5-473b-a8c8-b9d595f82728"; //service.ALIAS_REGISTRY_GUEST; 622 623 User user = service.getUserFromAlias(alias); 624 boolean isAdmin = az.isRegistryAdministrator(user); 625 626 System.err.println("isAdmin = " + isAdmin); 627 //java.security.PrivateKey key = service.getPrivateKey(alias, alias); 628 //X509Certificate cert = (X509Certificate)service.getKeyStore().getCertificate(alias); 629 //service.validateCertificate(cert); 630 631 //System.err.println(key); 632 } 633 634 }

This page was automatically generated by Maven