List of usage examples for org.apache.commons.httpclient URI isRelativeURI
public boolean isRelativeURI()
From source file:org.glite.slcs.shibclient.ShibbolethClient.java
/** * Parses and processes Pubcookie or CAS login form. * /*from ww w. j a v a2 s. co m*/ * @param idp * @param htmlForm * @throws IOException * @throws RemoteException * @throws ServiceException * @throws AuthException */ private URI processIdPLoginForm(IdentityProvider idp, URI ssoLoginURI, String ssoQuery, InputStream htmlForm) throws IOException, RemoteException, ServiceException, AuthException { LOG.info("Parse and process " + idp.getAuthTypeName() + " login form: " + ssoLoginURI); boolean formFound = false; URI idpLoginFormResponseURI = null; // Parse the FORM with Jericho HTML Parser Source source = new Source(htmlForm); List<Element> forms = source.findAllElements(Tag.FORM); for (Element form : forms) { String formName = form.getAttributeValue("NAME"); // BUG FIX: UniL use a CAS login form with NO NAME defined. // first try with the form ID as NAME, otherwise use an empty name. // the metadata should also define an empty name for this particular // form. LOG.debug("form name= " + formName); if (formName == null) { LOG.warn("form have no NAME, try form ID..."); String formId = form.getAttributeValue("ID"); if (formId == null) { LOG.warn("form have no NAME and no ID, using empty name..."); formName = ""; } else { formName = formId; } } if (formName.equals(idp.getAuthFormName())) { formFound = true; String formAction = form.getAttributeValue("ACTION"); LOG.debug("form action=" + formAction); if (formAction == null || formAction.equals("")) { // no form action to POST, use default from metadata formAction = ssoLoginURI.getEscapedURI(); LOG.info("default form action=" + formAction); } else { URI formActionURI = new URI(formAction, false); if (formActionURI.isRelativeURI()) { // action URL is not absolute like: // http://localhost/cas/login?... formActionURI = new URI(ssoLoginURI, formActionURI.getPathQuery(), true); } formAction = formActionURI.getEscapedURI(); LOG.info("corrected form action=" + formAction); } String formMethod = form.getAttributeValue("METHOD"); LOG.debug("form name=" + formName + " action=" + formAction + " method=" + formMethod); if (!formAction.equals("") && formMethod.equalsIgnoreCase("POST")) { PostMethod postLoginFormMethod = new PostMethod(formAction); // add all HIDDEN fields to POST List<FormControl> formControls = form.findFormControls(); for (FormControl control : formControls) { FormControlType type = control.getFormControlType(); if (type.equals(FormControlType.HIDDEN)) { String name = control.getName(); Collection<String> values = control.getValues(); for (String value : values) { LOG.debug("add hidden: " + name + "=" + value); // add all hidden fields postLoginFormMethod.addParameter(name, value); } } } // add username field postLoginFormMethod.addParameter(idp.getAuthFormUsername(), this.credentials_.getUserName()); // add the PASSWORD field postLoginFormMethod.addParameter(idp.getAuthFormPassword(), this.credentials_.getPassword()); // execute the login POST LOG.info("POST LoginFormMethod: " + postLoginFormMethod.getURI()); int formLoginResponseStatus = executeMethod(postLoginFormMethod); LOG.debug(postLoginFormMethod.getStatusLine()); // XXX dumpHttpClientCookies(); // CAS, or FORM can, send a 302 + Location header back if (formLoginResponseStatus == 302 && (idp.getAuthType() == IdentityProvider.SSO_AUTHTYPE_CAS || idp.getAuthType() == IdentityProvider.SSO_AUTHTYPE_FORM)) { LOG.debug("Process " + idp.getAuthTypeName() + " redirect response (302 + Location header)..."); Header location = postLoginFormMethod.getResponseHeader("Location"); if (location != null) { String locationURL = location.getValue(); LOG.debug("302 Location: " + locationURL); // CAS: if location path (/cas/login) is not the IdP // 1.3 // SSO path (/shibboleth-idp/SSO) or the IdP 2.X // /Authn/RemoteUser // handler, then it's a wrong login URI locationURI = new URI(locationURL, false); String locationPath = locationURI.getPath(); String idpSSOURL = idp.getUrl(); URI idpSSOURI = new URI(idpSSOURL, false); String idpSSOPath = idpSSOURI.getPath(); if (LOG.isDebugEnabled()) { LOG.debug("location path: " + locationPath); LOG.debug("location is the /Authn/RemoteUser hanlder? " + locationPath.endsWith("/Authn/RemoteUser")); LOG.debug("IdP SSO path: " + idpSSOPath); } if (!locationPath.equals(idpSSOPath) && !locationPath.endsWith("/Authn/RemoteUser")) { LOG.error("Redirect response is not the SSO (" + idpSSOURL + ") or the /Authn/RemoteUser handler: " + locationURL); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } idpLoginFormResponseURI = new URI(locationURL, false); LOG.debug("(" + idp.getAuthTypeName() + ": 302 + Location) idpLoginFormReponseURI= " + idpLoginFormResponseURI); } else { LOG.error(idp.getAuthTypeName() + ": Status 302 but no redirect Location header"); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } } // IdP 2.1 FORM authN send 200 and directly the SAMLResponse // form else if (formLoginResponseStatus == 200 && idp.getAuthType() == IdentityProvider.SSO_AUTHTYPE_FORM) { // BUG FIX: check for Browser/POST hidden form element // SAMLResponse for valid authentication LOG.debug("check for SAMLResponse hidden element"); boolean samlResponseFound = false; InputStream authnLoginResponse = postLoginFormMethod.getResponseBodyAsStream(); Source authnSource = new Source(authnLoginResponse); List<Element> browserPOSTForms = authnSource.findAllElements(Tag.FORM); for (Element browserPOSTForm : browserPOSTForms) { List<FormControl> browserPOSTFormControls = browserPOSTForm.findFormControls(); for (FormControl control : browserPOSTFormControls) { FormControlType type = control.getFormControlType(); if (type.equals(FormControlType.HIDDEN)) { String name = control.getName(); if (name.equals("SAMLResponse")) { LOG.debug("Hidden element found: " + control.getName()); samlResponseFound = true; } } } } if (!samlResponseFound) { LOG.error( idp.getAuthTypeName() + ": no Browser/POST SAMLResponse hidden element found"); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } LOG.debug("Process FORM (200 + full Browser/POST profile) response..."); idpLoginFormResponseURI = new URI(idp.getUrl(), false); // re-set the original SSO query params idpLoginFormResponseURI.setQuery(ssoQuery); LOG.debug("(FORM: 200 + Browser/POST) idpLoginFormReponseURI= " + idpLoginFormResponseURI); } // Pubcookie send 200 + fucking HTML form relay with hidden // fields!!! // <form method=post // action="https://aai-login.ethz.ch/PubCookie.reply" // name=relay> // then reply a redirect 302 + Location header else if (formLoginResponseStatus == 200 && idp.getAuthType() == IdentityProvider.SSO_AUTHTYPE_PUBCOOKIE) { LOG.debug("Process Pubcookie (200 + relay FORM) response..."); InputStream pubcookieLoginResponse = postLoginFormMethod.getResponseBodyAsStream(); Source pubcookieSource = new Source(pubcookieLoginResponse); PostMethod postPubcookieRelayMethod = null; List<Element> relayForms = pubcookieSource.findAllElements(Tag.FORM); for (Element relayForm : relayForms) { String relayFormAction = relayForm.getAttributeValue("ACTION"); LOG.debug("Pubcookie relay form action= " + relayFormAction); if (relayFormAction == null) { LOG.error("Pubcookie relay form action not found."); throw new RemoteException("Pubcookie relay form action not found"); } // create PubCookie relay POST postPubcookieRelayMethod = new PostMethod(relayFormAction); // add all HIDDEN fields to POST List<FormControl> relayFormControls = relayForm.findFormControls(); for (FormControl control : relayFormControls) { FormControlType type = control.getFormControlType(); if (type.equals(FormControlType.HIDDEN)) { String name = control.getName(); Collection<String> values = control.getValues(); for (String value : values) { LOG.debug("add hidden: " + name + "=" + value); // add all hidden fields postPubcookieRelayMethod.addParameter(name, value); } } } // add hidden fields } // for all relay forms if (postPubcookieRelayMethod != null) { LOG.debug("POST postPubcookieRelayMethod: " + postPubcookieRelayMethod.getURI()); int pubcookieRelayStatus = executeMethod(postPubcookieRelayMethod); LOG.debug(postPubcookieRelayMethod.getStatusLine()); Header location = postPubcookieRelayMethod.getResponseHeader("Location"); LOG.debug("postPubcookieRelayMethod.releaseConnection()"); postPubcookieRelayMethod.releaseConnection(); if (location != null) { String locationURL = location.getValue(); LOG.debug("302 Location: " + locationURL); // parse Location idpLoginFormResponseURI = new URI(locationURL, false); LOG.debug("(PubCookie: 302 + Location header) idpLoginFormReponseURI= " + idpLoginFormResponseURI); } else { LOG.error("Pubcookie relay response 302 + Location header not found"); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } } else { LOG.error("Pubcookie relay form not found"); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } // XXX dumpHttpClientCookies(); } else { LOG.error("Unexpected response status: " + formLoginResponseStatus + " AuthType:" + idp.getAuthTypeName()); throw new AuthException( idp.getAuthTypeName() + " Authentication failed: " + this.credentials_); } LOG.debug("POSTLoginFormMethod.releaseConnection()"); postLoginFormMethod.releaseConnection(); } // end if form action is set and method is POST } // end if form name match metadata } // end for all forms if (!formFound) { LOG.error("FORM name=" + idp.getAuthFormName() + " not found"); throw new ServiceException("FORM name=" + idp.getAuthFormName() + " not found"); } return idpLoginFormResponseURI; }
From source file:org.zaproxy.zap.extension.pscanrulesAlpha.StrictTransportSecurityScanner.java
@Override public void scanHttpResponseReceive(HttpMessage msg, int id, Source source) { long start = System.currentTimeMillis(); Vector<String> stsOption = msg.getResponseHeader().getHeaders(STS_HEADER); String metaHSTS = getMetaHSTSEvidence(source); if (msg.getRequestHeader().isSecure()) { // No point reporting missing for non-SSL resources // Content available via both HTTPS and HTTP is a separate though related issue if (stsOption == null) { // Header NOT found boolean report = true; if (!this.getAlertThreshold().equals(AlertThreshold.LOW) && HttpStatusCode.isRedirection(msg.getResponseHeader().getStatusCode())) { // Only report https redirects to the same domain at low threshold try { String redirStr = msg.getResponseHeader().getHeader(HttpHeader.LOCATION); URI srcUri = msg.getRequestHeader().getURI(); URI redirUri = new URI(redirStr, false); if (redirUri.isRelativeURI() || (redirUri.getScheme().equalsIgnoreCase("https") && redirUri.getHost().equals(srcUri.getHost()) && redirUri.getPort() == srcUri.getPort())) { report = false;/* ww w .j a v a 2 s.com*/ } } catch (Exception e) { // Ignore, so report the missing header } } if (report) { raiseAlert(VulnType.HSTS_MISSING, null, msg, id); } } else if (stsOption.size() > 1) { // More than one header found raiseAlert(VulnType.HSTS_MULTIPLE_HEADERS, null, msg, id); } else { // Single HSTS header entry String stsOptionString = stsOption.get(0); Matcher badAgeMatcher = BAD_MAX_AGE_PATT.matcher(stsOptionString); Matcher maxAgeMatcher = MAX_AGE_PATT.matcher(stsOptionString); Matcher malformedMaxAgeMatcher = MALFORMED_MAX_AGE.matcher(stsOptionString); Matcher wellformedMatcher = WELL_FORMED_PATT.matcher(stsOptionString); if (!wellformedMatcher.matches()) { // Well formed pattern didn't match (perhaps curly quotes or some other unwanted // character(s)) raiseAlert(VulnType.HSTS_MALFORMED_CONTENT, STS_HEADER, msg, id); } else if (badAgeMatcher.find()) { // Matched BAD_MAX_AGE_PATT, max-age is zero raiseAlert(VulnType.HSTS_MAX_AGE_DISABLED, badAgeMatcher.group(), msg, id); } else if (!maxAgeMatcher.find()) { // Didn't find a digit value associated with max-age raiseAlert(VulnType.HSTS_MAX_AGE_MISSING, stsOption.get(0), msg, id); } else if (malformedMaxAgeMatcher.find()) { // Found max-age but it was malformed raiseAlert(VulnType.HSTS_MALFORMED_MAX_AGE, stsOption.get(0), msg, id); } } } else if (AlertThreshold.LOW.equals(this.getAlertThreshold()) && stsOption != null && !stsOption.isEmpty()) { // isSecure is false at this point // HSTS Header found on non-HTTPS response (technically there could be more than one // but we only care that there is one or more) raiseAlert(VulnType.HSTS_ON_PLAIN_RESP, stsOption.get(0), msg, id); } if (metaHSTS != null) { // HSTS found defined by META tag raiseAlert(VulnType.HSTS_META, metaHSTS, msg, id); } if (logger.isDebugEnabled()) { logger.debug("\tScan of record " + id + " took " + (System.currentTimeMillis() - start) + " ms"); } }