1 28 package net.sf.jguard.jee.authentication.callbacks; 29 30 import java.io.IOException ; 31 import java.io.UnsupportedEncodingException ; 32 import java.security.cert.X509Certificate ; 33 import java.util.Arrays ; 34 import java.util.Iterator ; 35 import java.util.List ; 36 37 import javax.security.auth.Subject ; 38 import javax.security.auth.callback.Callback ; 39 import javax.security.auth.callback.CallbackHandler ; 40 import javax.security.auth.callback.NameCallback ; 41 import javax.security.auth.callback.PasswordCallback ; 42 import javax.security.auth.callback.UnsupportedCallbackException ; 43 import javax.servlet.FilterChain ; 44 import javax.servlet.ServletException ; 45 import javax.servlet.ServletRequest ; 46 import javax.servlet.ServletResponse ; 47 import javax.servlet.http.HttpServletRequest ; 48 import javax.servlet.http.HttpServletResponse ; 49 import javax.servlet.http.HttpSession ; 50 51 import net.sf.jguard.ext.SecurityConstants; 52 import net.sf.jguard.ext.authentication.callbacks.CertificatesCallback; 53 import net.sf.jguard.ext.authentication.callbacks.JCaptchaCallback; 54 import net.sf.jguard.ext.authentication.certificates.CertificateConverter; 55 import net.sf.jguard.jee.authentication.http.HttpAuthenticationUtils; 56 import net.sf.jguard.jee.authentication.http.HttpConstants; 57 58 import org.apache.commons.logging.Log; 59 import org.apache.commons.logging.LogFactory; 60 import org.bouncycastle.util.encoders.Base64; 61 62 import com.octo.captcha.service.CaptchaService; 63 64 68 public class HttpCallbackHandler implements CallbackHandler { 69 70 private static final String JAVAX_SERVLET_REQUEST_X509CERTIFICATE = "javax.servlet.request.X509Certificate"; 71 private static final String DIGEST_REALM = "Digest realm=\""; 72 public static final String AUTHORIZATION = "Authorization"; 73 private static final String BASIC_REALM = "Basic realm=\""; 74 private static final String NO_CACHE_AUTHORIZATION = "no-cache=\"Authorization\""; 75 private static final String CACHE_CONTROL = "Cache-Control"; 76 private static final String WWW_AUTHENTICATE = "WWW-Authenticate"; 77 private static final String BASIC = "Basic "; 78 private static final String ISO_8859_1 = "ISO-8859-1"; 79 80 private static final Log logger = LogFactory.getLog(HttpCallbackHandler.class); 81 private HttpServletRequest httpRequest; 82 private HttpServletResponse httpResponse; 83 private String authScheme=HttpConstants.FORM_AUTH; 84 private static String loginField="login"; 85 private static String passwordField="password"; 86 private boolean afterRegistration; 87 88 89 92 public HttpCallbackHandler(){ 93 94 } 95 96 102 public HttpCallbackHandler(HttpServletRequest request,HttpServletResponse response,String authScheme){ 103 this.httpRequest = request; 104 this.httpResponse = response; 105 this.authScheme = authScheme; 106 107 108 } 109 110 111 116 public void handle(Callback [] callbacks) throws IOException , UnsupportedCallbackException { 117 boolean httpRelatedAuthScheme = false; 118 logger.debug("authSchemeItem="+authScheme); 119 String [] schemes = authScheme.split(","); 120 List authSchemes = Arrays.asList(schemes); 121 Iterator itAutSchemes = authSchemes.iterator(); 122 while(itAutSchemes.hasNext()){ 123 String scheme = (String )itAutSchemes.next(); 124 if(!httpRelatedAuthScheme && HttpConstants.FORM_AUTH.equalsIgnoreCase(scheme)){ 126 grabFormCredentials(this.httpRequest,callbacks); 127 httpRelatedAuthScheme = true; 128 }else if(!httpRelatedAuthScheme && HttpConstants.BASIC_AUTH.equalsIgnoreCase(scheme)){ 129 grabBasicCredentials(this.httpRequest,callbacks); 130 httpRelatedAuthScheme = true; 131 }else if(!httpRelatedAuthScheme && HttpConstants.DIGEST_AUTH.equalsIgnoreCase(scheme)){ 132 grabDigestCredentials(this.httpRequest,callbacks); 133 httpRelatedAuthScheme = true; 134 } 135 if(HttpConstants.CLIENT_CERT_AUTH.equalsIgnoreCase(scheme)){ 138 boolean certificatesFound = grabClientCertCredentials(this.httpRequest,callbacks); 139 if(!certificatesFound){ 140 logger.info(" X509 certificates are not found "); 141 } 142 } 143 } 144 145 } 146 147 public HttpServletRequest getHttpRequest() { 148 return httpRequest; 149 } 150 151 152 public void setHttpRequest(HttpServletRequest httpRequest) { 153 this.httpRequest = httpRequest; 154 } 155 156 public HttpServletResponse getHttpResponse() { 157 return httpResponse; 158 } 159 160 public void setHttpResponse(HttpServletResponse httpResponse) { 161 this.httpResponse = httpResponse; 162 } 163 164 171 public static String buildBasicAuthHeader(String login,String password,String encoding){ 172 if(encoding==null){ 173 encoding=HttpCallbackHandler.ISO_8859_1; 174 } 175 StringBuffer decodedString = new StringBuffer (); 176 decodedString.append(login); 177 decodedString.append(" : "); 178 decodedString.append(password); 179 String encodedString; 180 try { 181 encodedString = new String (Base64.encode(decodedString.toString().getBytes(encoding))); 182 } catch (UnsupportedEncodingException e) { 183 encodedString = new String (Base64.encode(decodedString.toString().getBytes())); 184 } 185 StringBuffer header = new StringBuffer (); 186 header.append(HttpCallbackHandler.BASIC); 187 header.append(encodedString); 188 header.append("=="); 189 return header.toString(); 190 } 191 192 197 public static void buildBasicChallenge(HttpServletResponse response,String realmName){ 198 StringBuffer responseValue= new StringBuffer (); 199 responseValue.append(HttpCallbackHandler.BASIC_REALM); 200 responseValue.append(realmName); 201 responseValue.append("\""); 202 response.setHeader(HttpCallbackHandler.WWW_AUTHENTICATE,responseValue.toString()); 203 response.setHeader(HttpCallbackHandler.CACHE_CONTROL, HttpCallbackHandler.NO_CACHE_AUTHORIZATION); 204 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 205 } 206 207 208 215 private boolean grabBasicCredentials(HttpServletRequest request,Callback [] callbacks){ 216 boolean result = false; 217 String login=""; 218 String password=""; 219 String encodedLoginAndPwd = request.getHeader(HttpCallbackHandler.AUTHORIZATION); 221 222 if(encodedLoginAndPwd==null ||encodedLoginAndPwd.equals("")){ 223 login =SecurityConstants.GUEST; 224 password =SecurityConstants.GUEST; 225 226 }else{ 227 encodedLoginAndPwd = encodedLoginAndPwd.substring(6).trim(); 228 String decodedLoginAndPassword = null; 229 230 String encoding = request.getCharacterEncoding(); 231 if(encoding==null){ 232 encoding=HttpCallbackHandler.ISO_8859_1; 233 } 234 logger.debug(encoding); 235 236 try { 237 decodedLoginAndPassword = new String (Base64.decode(encodedLoginAndPwd.getBytes()),encoding); 238 } catch (UnsupportedEncodingException e) { 239 e.printStackTrace(); 240 logger.error(" encoding "+encoding+" is not supported by the platform "); 241 } 242 243 String [] parts = decodedLoginAndPassword.split(":"); 244 if(parts.length == 2 ){ 245 login = parts[0].trim(); 246 password = parts[1].trim(); 247 248 result = true; 249 } 250 if((login=="" && password=="")||(parts.length==0)){ 251 login =SecurityConstants.GUEST; 252 password =SecurityConstants.GUEST; 253 } 254 255 } 256 257 fillBasicCredentials(callbacks,login,password); 258 return result; 259 } 260 261 267 private boolean grabFormCredentials(HttpServletRequest request,Callback [] callbacks){ 268 boolean result = false; 269 HttpSession session = request.getSession(); 270 271 for(int i=0;i<callbacks.length;i++){ 272 if(callbacks[i] instanceof NameCallback ){ 273 NameCallback nc = (NameCallback )callbacks[i]; 274 String login =httpRequest.getParameter(loginField); 275 nc.setName(login); 276 }else if(callbacks[i] instanceof PasswordCallback ){ 277 PasswordCallback pc = (PasswordCallback )callbacks[i]; 278 String strPwd = httpRequest.getParameter(passwordField); 279 if(strPwd!= null &&strPwd!=""){ 280 pc.setPassword(strPwd.toCharArray()); 281 }else{ 282 pc.setPassword(null); 283 } 284 }else if(callbacks[i] instanceof JCaptchaCallback){ 285 JCaptchaCallback pc = (JCaptchaCallback)callbacks[i]; 286 pc.setCaptchaAnswer(httpRequest.getParameter(SecurityConstants.CAPTCHA_ANSWER)); 287 pc.setCaptchaService((CaptchaService)session.getServletContext().getAttribute(SecurityConstants.CAPTCHA_SERVICE)); 288 Subject subject = ((HttpAuthenticationUtils)session.getAttribute(HttpConstants.AUTHN_UTILS)).getSubject(); 289 if(subject==null ||this.isAfterRegistration()){ 290 pc.setSkipJCaptchaChallenge(true); 291 } 292 293 pc.setSessionID(session.getId()); 294 } 295 } 296 result = true; 297 298 299 return result; 300 } 301 302 308 private boolean grabDigestCredentials(HttpServletRequest request,Callback [] callbacks){ 309 boolean result = false; 310 String login = ""; 311 String password = ""; 312 if(login==null || password == null ){ 316 login =SecurityConstants.GUEST; 317 password =SecurityConstants.GUEST; 318 }else{ 319 result = true; 321 } 322 return result; 323 } 324 325 331 private boolean grabClientCertCredentials(HttpServletRequest request,Callback [] callbacks) { 332 if(!request.isSecure()){ 333 logger.warn(" certificate-based authentication MUST be do in secure mode "); 334 logger.warn(" but connection is do with the non secured protocol "+request.getScheme()); 335 return false; 336 } 337 338 X509Certificate [] certificates = null; 339 javax.security.cert.X509Certificate[] oldCerts = null; 340 Object [] objects = (Object []) request.getAttribute(HttpCallbackHandler.JAVAX_SERVLET_REQUEST_X509CERTIFICATE); 341 342 if(objects == null || objects.length==0){ 343 return false; 344 } 345 346 if(objects instanceof X509Certificate []) { 347 certificates= (X509Certificate []) objects; 348 }else if(objects instanceof javax.security.cert.X509Certificate[]) { 350 oldCerts = (javax.security.cert.X509Certificate[])objects; 351 List newCerts = null; 352 for(int i =0;i<oldCerts.length;i++){ 353 newCerts = Arrays.asList(certificates); 354 newCerts.add(CertificateConverter.convertOldToNew(oldCerts[i])); 355 } 356 certificates = (X509Certificate []) newCerts.toArray(); 357 }else{ 358 logger.warn(" X509certificates are needed but not provided by the client "); 359 return false; 360 } 361 fillCertCredentials(callbacks,certificates); 362 363 return true; 364 } 365 366 private void fillBasicCredentials(Callback [] callbacks, String login, String password) { 367 for(int i=0;i<callbacks.length;i++){ 368 if(callbacks[i] instanceof NameCallback ){ 369 NameCallback nc = (NameCallback )callbacks[i]; 370 nc.setName(login); 371 372 }else if(callbacks[i] instanceof PasswordCallback ){ 373 PasswordCallback pc = (PasswordCallback )callbacks[i]; 374 pc.setPassword(password.toCharArray()); 375 }else if (callbacks[i] instanceof JCaptchaCallback){ 376 JCaptchaCallback jc = (JCaptchaCallback)callbacks[i]; 377 jc.setSkipJCaptchaChallenge(true); 380 } 381 } 382 } 383 384 385 private void fillCertCredentials(Callback [] callbacks,X509Certificate [] certificates) { 386 for(int i=0;i<callbacks.length;i++){ 387 if(callbacks[i] instanceof CertificatesCallback){ 388 CertificatesCallback cc = (CertificatesCallback)callbacks[i]; 389 cc.setCertificates(certificates); 390 break; 391 } 392 } 393 } 394 395 public static void buildFormChallenge(FilterChain chain,ServletRequest req,ServletResponse res) throws IOException , ServletException { 396 chain.doFilter(req,res); 397 } 398 399 404 public static void buildDigestChallenge(HttpServletRequest request,HttpServletResponse response, String realm) { 405 StringBuffer responseValue= new StringBuffer (); 407 409 responseValue.append(HttpCallbackHandler.DIGEST_REALM); 411 responseValue.append(realm); 412 responseValue.append("\""); 413 responseValue.append(","); 414 responseValue.append("qop=\""); 416 responseValue.append(getQop()); 417 responseValue.append("\""); 418 responseValue.append(","); 419 420 responseValue.append("nonce=\""); 421 responseValue.append(getNonce(request)); 422 responseValue.append("\""); 423 responseValue.append(","); 424 responseValue.append("opaque="); 426 responseValue.append("\""); 427 responseValue.append(getOpaque()); 428 responseValue.append("\""); 429 responseValue.append("algorithm="); 431 responseValue.append("\""); 432 responseValue.append(getAlgorithm()); 433 responseValue.append("\""); 434 responseValue.append("stale="); 436 responseValue.append("\""); 437 responseValue.append(getStale()); 438 responseValue.append("\""); 439 response.setHeader(HttpCallbackHandler.WWW_AUTHENTICATE,responseValue.toString()); 440 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 441 } 442 443 456 private static String getStale() { 457 return "false"; 458 } 459 460 473 private static String getQop() { 474 return "auth,auth-int"; 475 } 476 477 484 private static String getOpaque() { 485 return "5ccc069c403ebaf9f0171e9517f40e41"; 486 } 487 488 516 private static String getAlgorithm() { 517 return "MD5"; 518 } 519 520 560 private static String getNonce(HttpServletRequest request){ 561 return "dcd98b7102dd2f0e8b11d0f600bfb0c093"; 562 } 563 564 565 569 public static String getPasswordField() { 570 return passwordField; 571 } 572 573 public static void setPasswordField(String passwordField) { 574 if(passwordField!=null){ 575 HttpCallbackHandler.passwordField = passwordField; 576 } 577 } 578 579 583 public static String getLoginField() { 584 return loginField; 585 } 586 587 public static void setLoginField(String loginField) { 588 if(loginField!=null){ 589 HttpCallbackHandler.loginField = loginField; 590 } 591 } 592 593 public void setAfterRegistration(boolean afterRegistration) { 594 this.afterRegistration = afterRegistration; 595 } 596 597 public boolean isAfterRegistration() { 598 return afterRegistration; 599 } 600 } 601 | Popular Tags |