1 7 8 package org.jboss.security.plugins; 9 10 import java.io.BufferedReader ; 11 import java.io.File ; 12 import java.io.IOException ; 13 import java.io.InputStream ; 14 import java.io.InputStreamReader ; 15 import java.lang.reflect.Constructor ; 16 import java.lang.reflect.Method ; 17 import java.net.MalformedURLException ; 18 import java.net.URL ; 19 import java.security.KeyStore ; 20 import java.util.Arrays ; 21 import java.util.StringTokenizer ; 22 import javax.crypto.Cipher; 23 import javax.crypto.SecretKey; 24 import javax.crypto.SecretKeyFactory; 25 import javax.crypto.spec.PBEKeySpec; 26 import javax.crypto.spec.PBEParameterSpec; 27 import javax.management.MBeanServer ; 28 import javax.management.ObjectName ; 29 import javax.net.ssl.KeyManagerFactory; 30 import javax.net.ssl.TrustManagerFactory; 31 import javax.security.auth.callback.CallbackHandler ; 32 33 import org.jboss.mx.util.MBeanServerLocator; 34 import org.jboss.security.SecurityDomain; 35 import org.jboss.security.Util; 36 import org.jboss.security.auth.callback.SecurityAssociationHandler; 37 38 99 public class JaasSecurityDomain 100 extends JaasSecurityManager 101 implements SecurityDomain, JaasSecurityDomainMBean 102 { 103 104 private static final RuntimePermission encodePermission = 105 new RuntimePermission ("org.jboss.security.plugins.JaasSecurityDomain.encode"); 106 107 private static final RuntimePermission decodePermission = 108 new RuntimePermission ("org.jboss.security.plugins.JaasSecurityDomain.decode"); 109 110 111 private KeyStore keyStore; 112 private KeyManagerFactory keyMgr; 113 114 private String keyStoreType = "JKS"; 115 116 private URL keyStoreURL; 117 118 private char[] keyStorePassword; 119 120 private String keyStorePasswordCmd; 121 122 private String keyStorePasswordCmdType; 123 124 private SecretKey cipherKey; 125 126 private String cipherAlgorithm = "PBEwithMD5andDES"; 127 private byte[] salt = {1, 2, 3, 4, 5, 6, 7, 8}; 128 private int iterationCount = 103; 129 private PBEParameterSpec cipherSpec; 130 131 private ObjectName managerServiceName = JaasSecurityManagerServiceMBean.OBJECT_NAME; 132 133 private KeyStore trustStore; 134 private String trustStoreType = "JKS"; 135 private char[] trustStorePassword; 136 private URL trustStoreURL; 137 private TrustManagerFactory trustMgr; 138 139 142 public JaasSecurityDomain() 143 { 144 super(); 145 } 146 147 151 public JaasSecurityDomain(String securityDomain) 152 { 153 this(securityDomain, new SecurityAssociationHandler()); 154 } 155 156 161 public JaasSecurityDomain(String securityDomain, CallbackHandler handler) 162 { 163 super(securityDomain, handler); 164 } 165 166 public KeyStore getKeyStore() throws SecurityException 167 { 168 return keyStore; 169 } 170 171 public KeyManagerFactory getKeyManagerFactory() throws SecurityException 172 { 173 return keyMgr; 174 } 175 176 public KeyStore getTrustStore() throws SecurityException 177 { 178 return trustStore; 179 } 180 181 public TrustManagerFactory getTrustManagerFactory() throws SecurityException 182 { 183 return trustMgr; 184 } 185 186 189 public ObjectName getManagerServiceName() 190 { 191 return this.managerServiceName; 192 } 193 194 196 public void setManagerServiceName(ObjectName managerServiceName) 197 { 198 this.managerServiceName = managerServiceName; 199 } 200 201 public String getKeyStoreType() 202 { 203 return this.keyStoreType; 204 } 205 206 public void setKeyStoreType(String type) 207 { 208 this.keyStoreType = type; 209 } 210 211 public String getKeyStoreURL() 212 { 213 String url = null; 214 if( keyStoreURL != null ) 215 url = keyStoreURL.toExternalForm(); 216 return url; 217 } 218 219 public void setKeyStoreURL(String storeURL) throws IOException 220 { 221 this.keyStoreURL = this.validateStoreURL(storeURL); 222 log.debug("Using KeyStore=" + keyStoreURL.toExternalForm()); 223 } 224 225 public void setKeyStorePass(String password) 226 { 227 this.keyStorePassword = null; 228 if( password.charAt(0) == '{' ) 230 { 231 StringTokenizer tokenizer = new StringTokenizer (password, "{}"); 232 this.keyStorePasswordCmdType = tokenizer.nextToken(); 233 this.keyStorePasswordCmd = tokenizer.nextToken(); 234 } 235 else 236 { 237 this.keyStorePassword = password.toCharArray(); 239 } 240 } 241 242 public String getTrustStoreType() 243 { 244 return this.trustStoreType; 245 } 246 247 public void setTrustStoreType(String type) 248 { 249 this.trustStoreType = type; 250 } 251 252 public void setTrustStorePass(String password) 253 { 254 this.trustStorePassword = password.toCharArray(); 255 } 256 257 public String getTrustStoreURL() 258 { 259 String url = null; 260 if( trustStoreURL != null ) 261 url = trustStoreURL.toExternalForm(); 262 return url; 263 } 264 265 public void setTrustStoreURL(String storeURL) throws IOException 266 { 267 this.trustStoreURL = validateStoreURL(storeURL); 268 } 269 270 public void setSalt(String salt) 271 { 272 this.salt = salt.getBytes(); 273 } 274 275 public void setIterationCount(int iterationCount) 276 { 277 this.iterationCount = iterationCount; 278 } 279 280 public String getCipherAlgorithm() 281 { 282 return cipherAlgorithm; 283 } 284 285 public void setCipherAlgorithm(String cipherAlgorithm) 286 { 287 this.cipherAlgorithm = cipherAlgorithm; 288 } 289 290 public String getName() 291 { 292 return "JaasSecurityDomain(" + getSecurityDomain() + ")"; 293 } 294 295 300 public byte[] encode(byte[] secret) 301 throws Exception 302 { 303 SecurityManager sm = System.getSecurityManager(); 304 if( sm != null ) 305 { 306 System.out.println("Checking: "+encodePermission); 307 sm.checkPermission(encodePermission); 308 } 309 310 Cipher cipher = Cipher.getInstance(cipherAlgorithm); 311 cipher.init(Cipher.ENCRYPT_MODE, cipherKey, cipherSpec); 312 byte[] encoding = cipher.doFinal(secret); 313 return encoding; 314 } 315 321 public byte[] decode(byte[] secret) 322 throws Exception 323 { 324 SecurityManager sm = System.getSecurityManager(); 325 if( sm != null ) 326 sm.checkPermission(decodePermission); 327 328 Cipher cipher = Cipher.getInstance(cipherAlgorithm); 329 cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherSpec); 330 byte[] decode = cipher.doFinal(secret); 331 return decode; 332 } 333 338 public String encode64(byte[] secret) 339 throws Exception 340 { 341 byte[] encoding = encode(secret); 342 String b64 = Util.tob64(encoding); 343 return b64; 344 } 345 351 public byte[] decode64(String secret) 352 throws Exception 353 { 354 byte[] encoding = Util.fromb64(secret); 355 byte[] decode = decode(encoding); 356 return decode; 357 } 358 359 362 public void reloadKeyAndTrustStore() 363 throws Exception 364 { 365 loadKeyAndTrustStore(); 366 } 367 368 protected void startService() 369 throws Exception 370 { 371 loadKeystorePassword(); 373 374 loadKeyAndTrustStore(); 376 377 381 MBeanServer server = MBeanServerLocator.locateJBoss(); 382 Object [] params = {getSecurityDomain(), this}; 383 String [] signature = new String []{"java.lang.String", "org.jboss.security.SecurityDomain"}; 384 server.invoke(managerServiceName, "registerSecurityDomain", params, signature); 385 } 386 387 protected void stopService() 388 { 389 if( keyStorePassword != null ) 390 { 391 Arrays.fill(keyStorePassword, '\0'); 392 keyStorePassword = null; 393 } 394 cipherKey = null; 395 } 396 397 400 private void loadKeystorePassword() 401 throws Exception 402 { 403 if( keyStorePassword == null ) 404 { 405 if( keyStorePasswordCmdType.equals("EXT") ) 406 execPasswordCmd(); 407 else if( keyStorePasswordCmdType.equals("CLASS") ) 408 invokePasswordClass(); 409 else 410 throw new IllegalArgumentException ("Unknown keyStorePasswordCmdType: "+keyStorePasswordCmdType); 411 } 412 413 cipherSpec = new PBEParameterSpec(salt, iterationCount); 415 PBEKeySpec keySpec = new PBEKeySpec(keyStorePassword); 416 SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithMD5andDES"); 417 cipherKey = factory.generateSecret(keySpec); 418 } 419 420 private void loadKeyAndTrustStore() 421 throws Exception 422 { 423 if( keyStoreURL != null ) 424 { 425 keyStore = KeyStore.getInstance(keyStoreType); 426 InputStream is = keyStoreURL.openStream(); 427 keyStore.load(is, keyStorePassword); 428 String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 429 keyMgr = KeyManagerFactory.getInstance(algorithm); 430 keyMgr.init(keyStore, keyStorePassword); 431 } 432 if( trustStoreURL != null ) 433 { 434 trustStore = KeyStore.getInstance(trustStoreType); 435 InputStream is = trustStoreURL.openStream(); 436 trustStore.load(is, trustStorePassword); 437 String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 438 trustMgr = TrustManagerFactory.getInstance(algorithm); 439 trustMgr.init(trustStore); 440 } 441 else if( keyStore != null ) 442 { 443 trustStore = keyStore; 444 String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 445 trustMgr = TrustManagerFactory.getInstance(algorithm); 446 trustMgr.init(trustStore); 447 } 448 } 449 450 private void execPasswordCmd() 451 throws Exception 452 { 453 log.debug("Executing command: "+keyStorePasswordCmd); 454 Runtime rt = Runtime.getRuntime(); 455 Process p = rt.exec(keyStorePasswordCmd); 456 InputStream stdin = p.getInputStream(); 457 BufferedReader reader = new BufferedReader (new InputStreamReader (stdin)); 458 String password = reader.readLine(); 459 stdin.close(); 460 int exitCode = p.waitFor(); 461 log.debug("Command exited with: "+exitCode); 462 keyStorePassword = password.toCharArray(); 463 } 464 468 private void invokePasswordClass() 469 throws Exception 470 { 471 keyStorePassword = null; 472 473 String classname = keyStorePasswordCmd; 475 String ctorArg = null; 476 int colon = keyStorePasswordCmd.indexOf(':'); 477 if( colon > 0 ) 478 { 479 classname = keyStorePasswordCmd.substring(0, colon); 480 ctorArg = keyStorePasswordCmd.substring(colon+1); 481 } 482 log.debug("Loading class: "+classname+", ctorArg="+ctorArg); 483 ClassLoader loader = SubjectActions.getContextClassLoader(); 484 Class c = loader.loadClass(classname); 485 Object instance = null; 486 if( ctorArg != null ) 488 { 489 Class [] sig = {String .class}; 490 Constructor ctor = c.getConstructor(sig); 491 Object [] args = {ctorArg}; 492 instance = ctor.newInstance(args); 493 } 494 else 495 { 496 instance = c.newInstance(); 498 } 499 500 try 502 { 503 log.debug("Checking for toCharArray"); 504 Class [] sig = {}; 505 Method toCharArray = c.getMethod("toCharArray", sig); 506 Object [] args = {}; 507 log.debug("Invoking toCharArray"); 508 keyStorePassword = (char[]) toCharArray.invoke(instance, args); 509 } 510 catch(NoSuchMethodException e) 511 { 512 log.debug("No toCharArray found, invoking toString"); 513 String tmp = instance.toString(); 514 if( tmp != null ) 515 keyStorePassword = tmp.toCharArray(); 516 } 517 } 518 519 private URL validateStoreURL(String storeURL) throws IOException 520 { 521 URL url = null; 522 try 524 { 525 url = new URL (storeURL); 526 } 527 catch(MalformedURLException e) 528 { 529 } 531 532 if( url == null ) 534 { 535 File tst = new File (storeURL); 536 if( tst.exists() == true ) 537 url = tst.toURL(); 538 } 539 540 if( url == null ) 542 { 543 ClassLoader loader = SubjectActions.getContextClassLoader(); 544 url = loader.getResource(storeURL); 545 } 546 547 if( url == null ) 549 { 550 String msg = "Failed to find url=" + storeURL + " as a URL, file or resource"; 551 throw new MalformedURLException (msg); 552 } 553 return url; 554 } 555 } 556 | Popular Tags |