Example #1
0
  /**
   * Creates digest-response header as defined in RFC2617.
   *
   * @param credentials User credentials
   * @param digest The response tag's value as String.
   * @return The digest-response as String.
   */
  private Header createDigestHeader(final Credentials credentials, final String digest)
      throws AuthenticationException {

    CharArrayBuffer buffer = new CharArrayBuffer(128);
    if (isProxy()) {
      buffer.append(AUTH.PROXY_AUTH_RESP);
    } else {
      buffer.append(AUTH.WWW_AUTH_RESP);
    }
    buffer.append(": Digest ");

    String uri = getParameter("uri");
    String realm = getParameter("realm");
    String nonce = getParameter("nonce");
    String opaque = getParameter("opaque");
    String response = digest;
    String algorithm = getParameter("algorithm");

    String uname = credentials.getUserPrincipal().getName();

    List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>(20);
    params.add(new BasicNameValuePair("username", uname));
    params.add(new BasicNameValuePair("realm", realm));
    params.add(new BasicNameValuePair("nonce", nonce));
    params.add(new BasicNameValuePair("uri", uri));
    params.add(new BasicNameValuePair("response", response));

    if (qopVariant != QOP_MISSING) {
      params.add(new BasicNameValuePair("qop", getQopVariantString()));
      params.add(new BasicNameValuePair("nc", NC));
      params.add(new BasicNameValuePair("cnonce", getCnonce()));
    }
    if (algorithm != null) {
      params.add(new BasicNameValuePair("algorithm", algorithm));
    }
    if (opaque != null) {
      params.add(new BasicNameValuePair("opaque", opaque));
    }

    for (int i = 0; i < params.size(); i++) {
      BasicNameValuePair param = params.get(i);
      if (i > 0) {
        buffer.append(", ");
      }
      boolean noQuotes = "nc".equals(param.getName()) || "qop".equals(param.getName());
      BasicHeaderValueFormatter.DEFAULT.formatNameValuePair(buffer, param, !noQuotes);
    }
    return new BufferedHeader(buffer);
  }
Example #2
0
  /**
   * Creates digest-response header as defined in RFC2617.
   *
   * @param credentials User credentials
   * @return The digest-response as String.
   */
  private Header createDigestHeader(final Credentials credentials) throws AuthenticationException {
    String uri = getParameter("uri");
    String realm = getParameter("realm");
    String nonce = getParameter("nonce");
    String opaque = getParameter("opaque");
    String method = getParameter("methodname");
    String algorithm = getParameter("algorithm");
    if (uri == null) {
      throw new IllegalStateException("URI may not be null");
    }
    if (realm == null) {
      throw new IllegalStateException("Realm may not be null");
    }
    if (nonce == null) {
      throw new IllegalStateException("Nonce may not be null");
    }

    // TODO: add support for QOP_INT
    int qop = QOP_UNKNOWN;
    String qoplist = getParameter("qop");
    if (qoplist != null) {
      StringTokenizer tok = new StringTokenizer(qoplist, ",");
      while (tok.hasMoreTokens()) {
        String variant = tok.nextToken().trim();
        if (variant.equals("auth")) {
          qop = QOP_AUTH;
          break;
        }
      }
    } else {
      qop = QOP_MISSING;
    }

    if (qop == QOP_UNKNOWN) {
      throw new AuthenticationException("None of the qop methods is supported: " + qoplist);
    }

    // If an algorithm is not specified, default to MD5.
    if (algorithm == null) {
      algorithm = "MD5";
    }
    // If an charset is not specified, default to ISO-8859-1.
    String charset = getParameter("charset");
    if (charset == null) {
      charset = "ISO-8859-1";
    }

    String digAlg = algorithm;
    if (digAlg.equalsIgnoreCase("MD5-sess")) {
      digAlg = "MD5";
    }

    MessageDigest digester;
    try {
      digester = createMessageDigest(digAlg);
    } catch (UnsupportedDigestAlgorithmException ex) {
      throw new AuthenticationException("Unsuppported digest algorithm: " + digAlg);
    }

    String uname = credentials.getUserPrincipal().getName();
    String pwd = credentials.getPassword();

    if (nonce.equals(this.lastNonce)) {
      nounceCount++;
    } else {
      nounceCount = 1;
      cnonce = null;
      lastNonce = nonce;
    }
    StringBuilder sb = new StringBuilder(256);
    Formatter formatter = new Formatter(sb, Locale.US);
    formatter.format("%08x", nounceCount);
    String nc = sb.toString();

    if (cnonce == null) {
      cnonce = createCnonce();
    }

    a1 = null;
    a2 = null;
    // 3.2.2.2: Calculating digest
    if (algorithm.equalsIgnoreCase("MD5-sess")) {
      // H( unq(username-value) ":" unq(realm-value) ":" passwd )
      //      ":" unq(nonce-value)
      //      ":" unq(cnonce-value)

      // calculated one per session
      sb.setLength(0);
      sb.append(uname).append(':').append(realm).append(':').append(pwd);
      String checksum = encode(digester.digest(EncodingUtils.getBytes(sb.toString(), charset)));
      sb.setLength(0);
      sb.append(checksum).append(':').append(nonce).append(':').append(cnonce);
      a1 = sb.toString();
    } else {
      // unq(username-value) ":" unq(realm-value) ":" passwd
      sb.setLength(0);
      sb.append(uname).append(':').append(realm).append(':').append(pwd);
      a1 = sb.toString();
    }

    String hasha1 = encode(digester.digest(EncodingUtils.getBytes(a1, charset)));

    if (qop == QOP_AUTH) {
      // Method ":" digest-uri-value
      a2 = method + ':' + uri;
    } else if (qop == QOP_AUTH_INT) {
      // Method ":" digest-uri-value ":" H(entity-body)
      // TODO: calculate entity hash if entity is repeatable
      throw new AuthenticationException("qop-int method is not suppported");
    } else {
      a2 = method + ':' + uri;
    }

    String hasha2 = encode(digester.digest(EncodingUtils.getBytes(a2, charset)));

    // 3.2.2.1

    String digestValue;
    if (qop == QOP_MISSING) {
      sb.setLength(0);
      sb.append(hasha1).append(':').append(nonce).append(':').append(hasha2);
      digestValue = sb.toString();
    } else {
      sb.setLength(0);
      sb.append(hasha1)
          .append(':')
          .append(nonce)
          .append(':')
          .append(nc)
          .append(':')
          .append(cnonce)
          .append(':')
          .append(qop == QOP_AUTH_INT ? "auth-int" : "auth")
          .append(':')
          .append(hasha2);
      digestValue = sb.toString();
    }

    String digest = encode(digester.digest(EncodingUtils.getAsciiBytes(digestValue)));

    CharArrayBuffer buffer = new CharArrayBuffer(128);
    if (isProxy()) {
      buffer.append(AUTH.PROXY_AUTH_RESP);
    } else {
      buffer.append(AUTH.WWW_AUTH_RESP);
    }
    buffer.append(": Digest ");

    List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>(20);
    params.add(new BasicNameValuePair("username", uname));
    params.add(new BasicNameValuePair("realm", realm));
    params.add(new BasicNameValuePair("nonce", nonce));
    params.add(new BasicNameValuePair("uri", uri));
    params.add(new BasicNameValuePair("response", digest));

    if (qop != QOP_MISSING) {
      params.add(new BasicNameValuePair("qop", qop == QOP_AUTH_INT ? "auth-int" : "auth"));
      params.add(new BasicNameValuePair("nc", nc));
      params.add(new BasicNameValuePair("cnonce", cnonce));
    }
    if (algorithm != null) {
      params.add(new BasicNameValuePair("algorithm", algorithm));
    }
    if (opaque != null) {
      params.add(new BasicNameValuePair("opaque", opaque));
    }

    for (int i = 0; i < params.size(); i++) {
      BasicNameValuePair param = params.get(i);
      if (i > 0) {
        buffer.append(", ");
      }
      boolean noQuotes = "nc".equals(param.getName()) || "qop".equals(param.getName());
      BasicHeaderValueFormatter.DEFAULT.formatNameValuePair(buffer, param, !noQuotes);
    }
    return new BufferedHeader(buffer);
  }