Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes
nsHttpDigestAuth Class Reference

#include <nsHttpDigestAuth.h>

Inheritance diagram for nsHttpDigestAuth:
Inheritance graph
[legend]
Collaboration diagram for nsHttpDigestAuth:
Collaboration graph
[legend]

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSIHTTPAUTHENTICATOR 
nsHttpDigestAuth ()
 ~nsHttpDigestAuth ()
void challengeReceived (in nsIHttpChannel aChannel, in string aChallenge, in boolean aProxyAuth, inout nsISupports aSessionState, inout nsISupports aContinuationState, out boolean aInvalidatesIdentity)
 Upon receipt of a server challenge, this function is called to determine whether or not the current user identity has been rejected.
string generateCredentials (in nsIHttpChannel aChannel, in string aChallenge, in boolean aProxyAuth, in wstring aDomain, in wstring aUser, in wstring aPassword, inout nsISupports aSessionState, inout nsISupports aContinuationState)
 Called to generate the authentication credentials for a particular server/proxy challenge.

Public Attributes

readonly attribute unsigned long authFlags
 Flags defining various properties of the authenticator.
const unsigned long REQUEST_BASED = (1<<0)
 A request based authentication scheme only authenticates an individual request (or a set of requests under the same authentication domain as defined by RFC 2617).
const unsigned long CONNECTION_BASED = (1<<1)
 A connection based authentication scheme authenticates an individual connection.
const unsigned long REUSABLE_CREDENTIALS = (1<<2)
 The credentials returned from generateCredentials may be reused with any other URLs within "the protection space" as defined by RFC 2617 section 1.2.
const unsigned long REUSABLE_CHALLENGE = (1<<3)
 A challenge may be reused to later generate credentials in anticipation of a duplicate server challenge for URLs within "the protection space" as defined by RFC 2617 section 1.2.
const unsigned long IDENTITY_IGNORED = (1<<10)
 This flag indicates that the identity of the user is not required by this authentication scheme.
const unsigned long IDENTITY_INCLUDES_DOMAIN = (1<<11)
 This flag indicates that the identity of the user includes a domain attribute that the user must supply.

Protected Member Functions

nsresult ExpandToHex (const char *digest, char *result)
nsresult CalculateResponse (const char *ha1_digest, const char *ha2_digest, const nsAFlatCString &nonce, PRUint16 qop, const char *nonce_count, const nsAFlatCString &cnonce, char *result)
nsresult CalculateHA1 (const nsAFlatCString &username, const nsAFlatCString &password, const nsAFlatCString &realm, PRUint16 algorithm, const nsAFlatCString &nonce, const nsAFlatCString &cnonce, char *result)
nsresult CalculateHA2 (const nsAFlatCString &http_method, const nsAFlatCString &http_uri_path, PRUint16 qop, const char *body_digest, char *result)
nsresult ParseChallenge (const char *challenge, nsACString &realm, nsACString &domain, nsACString &nonce, nsACString &opaque, PRBool *stale, PRUint16 *algorithm, PRUint16 *qop)
nsresult MD5Hash (const char *buf, PRUint32 len)
nsresult GetMethodAndPath (nsIHttpChannel *, PRBool, nsCString &, nsCString &)
nsresult AppendQuotedString (const nsACString &value, nsACString &aHeaderLine)

Protected Attributes

nsCOMPtr< nsICryptoHashmVerifier
char mHashBuf [DIGEST_LENGTH]
PRBool mGotVerifier

Detailed Description

Definition at line 64 of file nsHttpDigestAuth.h.


Constructor & Destructor Documentation

Definition at line 64 of file nsHttpDigestAuth.cpp.

{
  mVerifier = do_GetService("@mozilla.org/security/hash;1");
  mGotVerifier = (mVerifier != nsnull);

#if defined(PR_LOGGING)
  if (mGotVerifier) {
    LOG(("nsHttpDigestAuth: Got signature_verifier\n"));
  } else {
    LOG(("nsHttpDigestAuth: No signature_verifier available\n"));
  }
#endif
}

Here is the call graph for this function:

Definition at line 78 of file nsHttpDigestAuth.cpp.

{}

Member Function Documentation

nsresult nsHttpDigestAuth::AppendQuotedString ( const nsACString &  value,
nsACString &  aHeaderLine 
) [protected]

Definition at line 698 of file nsHttpDigestAuth.cpp.

{
  nsCAutoString quoted;
  nsACString::const_iterator s, e;
  value.BeginReading(s);
  value.EndReading(e);

  //
  // Encode string according to RFC 2616 quoted-string production
  //
  quoted.Append('"');
  for ( ; s != e; ++s) {
    //
    // CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>
    //
    if (*s <= 31 || *s == 127) {
      return NS_ERROR_FAILURE;
    }

    // Escape two syntactically significant characters
    if (*s == '"' || *s == '\\') {
      quoted.Append('\\');
    }

    quoted.Append(*s);
  }
  // FIXME: bug 41489
  // We should RFC2047-encode non-Latin-1 values according to spec
  quoted.Append('"');
  aHeaderLine.Append(quoted);
  return NS_OK;
}
nsresult nsHttpDigestAuth::CalculateHA1 ( const nsAFlatCString username,
const nsAFlatCString password,
const nsAFlatCString realm,
PRUint16  algorithm,
const nsAFlatCString nonce,
const nsAFlatCString cnonce,
char *  result 
) [protected]

Definition at line 493 of file nsHttpDigestAuth.cpp.

{
  PRInt16 len = username.Length() + password.Length() + realm.Length() + 2;
  if (algorithm & ALGO_MD5_SESS) {
    PRInt16 exlen = EXPANDED_DIGEST_LENGTH + nonce.Length() + cnonce.Length() + 2;
    if (exlen > len)
        len = exlen;
  }

  nsCAutoString contents;
  contents.SetCapacity(len + 1);

  contents.Assign(username);
  contents.Append(':');
  contents.Append(realm);
  contents.Append(':');
  contents.Append(password);

  nsresult rv;
  rv = MD5Hash(contents.get(), contents.Length());
  if (NS_FAILED(rv))
    return rv;

  if (algorithm & ALGO_MD5_SESS) {
    char part1[EXPANDED_DIGEST_LENGTH+1];
    ExpandToHex(mHashBuf, part1);

    contents.Assign(part1, EXPANDED_DIGEST_LENGTH);
    contents.Append(':');
    contents.Append(nonce);
    contents.Append(':');
    contents.Append(cnonce);

    rv = MD5Hash(contents.get(), contents.Length());
    if (NS_FAILED(rv))
      return rv;
  }

  return ExpandToHex(mHashBuf, result);
}

Here is the call graph for this function:

nsresult nsHttpDigestAuth::CalculateHA2 ( const nsAFlatCString http_method,
const nsAFlatCString http_uri_path,
PRUint16  qop,
const char *  body_digest,
char *  result 
) [protected]

Definition at line 541 of file nsHttpDigestAuth.cpp.

{
  PRInt16 methodLen = method.Length();
  PRInt16 pathLen = path.Length();
  PRInt16 len = methodLen + pathLen + 1;

  if (qop & QOP_AUTH_INT) {
    len += EXPANDED_DIGEST_LENGTH + 1;
  }

  nsCAutoString contents;
  contents.SetCapacity(len);

  contents.Assign(method);
  contents.Append(':');
  contents.Append(path);

  if (qop & QOP_AUTH_INT) {
    contents.Append(':');
    contents.Append(bodyDigest, EXPANDED_DIGEST_LENGTH);
  }

  nsresult rv = MD5Hash(contents.get(), contents.Length());
  if (NS_SUCCEEDED(rv))
    rv = ExpandToHex(mHashBuf, result);
  return rv;
}

Here is the call graph for this function:

nsresult nsHttpDigestAuth::CalculateResponse ( const char *  ha1_digest,
const char *  ha2_digest,
const nsAFlatCString nonce,
PRUint16  qop,
const char *  nonce_count,
const nsAFlatCString cnonce,
char *  result 
) [protected]

Definition at line 424 of file nsHttpDigestAuth.cpp.

{
  PRUint32 len = 2*EXPANDED_DIGEST_LENGTH + nonce.Length() + 2;

  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
    len += cnonce.Length() + NONCE_COUNT_LENGTH + 3;
    if (qop & QOP_AUTH_INT)
      len += 8; // length of "auth-int"
    else
      len += 4; // length of "auth"
  }

  nsCAutoString contents;
  contents.SetCapacity(len);

  contents.Assign(ha1_digest, EXPANDED_DIGEST_LENGTH);
  contents.Append(':');
  contents.Append(nonce);
  contents.Append(':');

  if (qop & QOP_AUTH || qop & QOP_AUTH_INT) {
    contents.Append(nonce_count, NONCE_COUNT_LENGTH);
    contents.Append(':');
    contents.Append(cnonce);
    contents.Append(':');
    if (qop & QOP_AUTH_INT)
      contents.AppendLiteral("auth-int:");
    else
      contents.AppendLiteral("auth:");
  }

  contents.Append(ha2_digest, EXPANDED_DIGEST_LENGTH);

  nsresult rv = MD5Hash(contents.get(), contents.Length());
  if (NS_SUCCEEDED(rv))
    rv = ExpandToHex(mHashBuf, result);
  return rv;
}

Here is the call graph for this function:

void nsIHttpAuthenticator::challengeReceived ( in nsIHttpChannel  aChannel,
in string  aChallenge,
in boolean  aProxyAuth,
inout nsISupports  aSessionState,
inout nsISupports  aContinuationState,
out boolean  aInvalidatesIdentity 
) [inherited]

Upon receipt of a server challenge, this function is called to determine whether or not the current user identity has been rejected.

If true, then the user will be prompted by the channel to enter (or revise) their identity. Following this, generateCredentials will be called.

If the IDENTITY_IGNORED auth flag is set, then the aInvalidateIdentity return value will be ignored, and user prompting will be suppressed.

Parameters:
aChannelthe http channel that received the challenge.
aChallengethe challenge from the WWW-Authenticate/Proxy-Authenticate server response header. (possibly from the auth cache.)
aProxyAuthflag indicating whether or not aChallenge is from a proxy.
aSessionStatesee description below for generateCredentials.
aContinuationStatesee description below for generateCredentials.
aInvalidateIdentityreturn value indicating whether or not to prompt the user for a revised identity.
nsresult nsHttpDigestAuth::ExpandToHex ( const char *  digest,
char *  result 
) [protected]

Definition at line 470 of file nsHttpDigestAuth.cpp.

{
  PRInt16 index, value;

  for (index = 0; index < DIGEST_LENGTH; index++) {
    value = (digest[index] >> 4) & 0xf;
    if (value < 10)
      result[index*2] = value + '0';
    else
      result[index*2] = value - 10 + 'a';

    value = digest[index] & 0xf;
    if (value < 10)
      result[(index*2)+1] = value + '0';
    else
      result[(index*2)+1] = value - 10 + 'a';
  }

  result[EXPANDED_DIGEST_LENGTH] = 0;
  return NS_OK;
}

Here is the caller graph for this function:

string nsIHttpAuthenticator::generateCredentials ( in nsIHttpChannel  aChannel,
in string  aChallenge,
in boolean  aProxyAuth,
in wstring  aDomain,
in wstring  aUser,
in wstring  aPassword,
inout nsISupports  aSessionState,
inout nsISupports  aContinuationState 
) [inherited]

Called to generate the authentication credentials for a particular server/proxy challenge.

This is the value that will be sent back to the server via an Authorization/Proxy-Authorization header.

This function may be called using a cached challenge provided the authenticator sets the REUSABLE_CHALLENGE flag.

Parameters:
aChannelthe http channel requesting credentials
aChallengethe challenge from the WWW-Authenticate/Proxy-Authenticate server response header. (possibly from the auth cache.)
aProxyAuthflag indicating whether or not aChallenge is from a proxy.
aDomainstring containing the domain name (if appropriate)
aUserstring containing the user name
aPasswordstring containing the password
aSessionStatestate stored along side the user's identity in the auth cache for the lifetime of the browser session. if a new auth cache entry is created for this challenge, then this parameter will be null. on return, the result will be stored in the new auth cache entry. this parameter is non-null when an auth cache entry is being reused.
aContinuationStatestate held by the channel between consecutive calls to generateCredentials, assuming multiple calls are required to authenticate. this state is held for at most the lifetime of the channel.
nsresult nsHttpDigestAuth::GetMethodAndPath ( nsIHttpChannel httpChannel,
PRBool  isProxyAuth,
nsCString httpMethod,
nsCString path 
) [protected]

Definition at line 116 of file nsHttpDigestAuth.cpp.

{
  nsresult rv;
  nsCOMPtr<nsIURI> uri;
  rv = httpChannel->GetURI(getter_AddRefs(uri));
  if (NS_SUCCEEDED(rv)) {
    PRBool isSecure;
    rv = uri->SchemeIs("https", &isSecure);
    if (NS_SUCCEEDED(rv)) {
      //
      // if we are being called in response to a 407, and if the protocol
      // is HTTPS, then we are really using a CONNECT method.
      //
      if (isSecure && isProxyAuth) {
        httpMethod.AssignLiteral("CONNECT");
        //
        // generate hostname:port string. (unfortunately uri->GetHostPort
        // leaves out the port if it matches the default value, so we can't
        // just call it.)
        //
        PRInt32 port;
        rv  = uri->GetAsciiHost(path);
        rv |= uri->GetPort(&port);
        if (NS_SUCCEEDED(rv)) {
          path.Append(':');
          path.AppendInt(port < 0 ? NS_HTTPS_DEFAULT_PORT : port);
        }
      }
      else { 
        rv  = httpChannel->GetRequestMethod(httpMethod);
        rv |= uri->GetPath(path);
        if (NS_SUCCEEDED(rv)) {
          //
          // strip any fragment identifier from the URL path.
          //
          PRInt32 ref = path.RFindChar('#');
          if (ref != kNotFound)
            path.Truncate(ref);
          //
          // make sure we escape any UTF-8 characters in the URI path.  the
          // digest auth uri attribute needs to match the request-URI.
          //
          // XXX we should really ask the HTTP channel for this string
          // instead of regenerating it here.
          //
          nsCAutoString buf;
          path = NS_EscapeURL(path, esc_OnlyNonASCII, buf);
        }
      }
    }
  }
  return rv;
}

Here is the call graph for this function:

nsresult nsHttpDigestAuth::MD5Hash ( const char *  buf,
PRUint32  len 
) [protected]

Definition at line 92 of file nsHttpDigestAuth.cpp.

{
  if (!mGotVerifier)
    return NS_ERROR_NOT_INITIALIZED;

  nsresult rv;


  rv = mVerifier->Init(nsICryptoHash::MD5);
  if (NS_FAILED(rv)) return rv;

  rv = mVerifier->Update((unsigned char*)buf, len);
  if (NS_FAILED(rv)) return rv;

  nsCAutoString hashString;
  rv = mVerifier->Finish(PR_FALSE, hashString);
  if (NS_FAILED(rv)) return rv;
  
  if (NS_SUCCEEDED(rv))
    memcpy(mHashBuf, hashString.get(), hashString.Length());
  return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsHttpDigestAuth::ParseChallenge ( const char *  challenge,
nsACString &  realm,
nsACString &  domain,
nsACString &  nonce,
nsACString &  opaque,
PRBool stale,
PRUint16 algorithm,
PRUint16 qop 
) [protected]

Definition at line 574 of file nsHttpDigestAuth.cpp.

{
  const char *p = challenge + 7; // first 7 characters are "Digest "

  *stale = PR_FALSE;
  *algorithm = ALGO_MD5; // default is MD5
  *qop = 0;

  for (;;) {
    while (*p && (*p == ',' || nsCRT::IsAsciiSpace(*p)))
      ++p;
    if (!*p)
      break;

    // name
    PRInt16 nameStart = (p - challenge);
    while (*p && !nsCRT::IsAsciiSpace(*p) && *p != '=') 
      ++p;
    if (!*p)
      return NS_ERROR_INVALID_ARG;
    PRInt16 nameLength = (p - challenge) - nameStart;

    while (*p && (nsCRT::IsAsciiSpace(*p) || *p == '=')) 
      ++p;
    if (!*p) 
      return NS_ERROR_INVALID_ARG;

    PRBool quoted = PR_FALSE;
    if (*p == '"') {
      ++p;
      quoted = PR_TRUE;
    }

    // value
    PRInt16 valueStart = (p - challenge);
    PRInt16 valueLength = 0;
    if (quoted) {
      while (*p && *p != '"') 
        ++p;
      if (*p != '"') 
        return NS_ERROR_INVALID_ARG;
      valueLength = (p - challenge) - valueStart;
      ++p;
    } else {
      while (*p && !nsCRT::IsAsciiSpace(*p) && *p != ',') 
        ++p; 
      valueLength = (p - challenge) - valueStart;
    }

    // extract information
    if (nameLength == 5 &&
        nsCRT::strncasecmp(challenge+nameStart, "realm", 5) == 0)
    {
      realm.Assign(challenge+valueStart, valueLength);
    }
    else if (nameLength == 6 &&
        nsCRT::strncasecmp(challenge+nameStart, "domain", 6) == 0)
    {
      domain.Assign(challenge+valueStart, valueLength);
    }
    else if (nameLength == 5 &&
        nsCRT::strncasecmp(challenge+nameStart, "nonce", 5) == 0)
    {
      nonce.Assign(challenge+valueStart, valueLength);
    }
    else if (nameLength == 6 &&
        nsCRT::strncasecmp(challenge+nameStart, "opaque", 6) == 0)
    {
      opaque.Assign(challenge+valueStart, valueLength);
    }
    else if (nameLength == 5 &&
        nsCRT::strncasecmp(challenge+nameStart, "stale", 5) == 0)
    {
      if (nsCRT::strncasecmp(challenge+valueStart, "true", 4) == 0)
        *stale = PR_TRUE;
      else
        *stale = PR_FALSE;
    }
    else if (nameLength == 9 &&
        nsCRT::strncasecmp(challenge+nameStart, "algorithm", 9) == 0)
    {
      // we want to clear the default, so we use = not |= here
      *algorithm = ALGO_SPECIFIED;
      if (valueLength == 3 &&
          nsCRT::strncasecmp(challenge+valueStart, "MD5", 3) == 0)
        *algorithm |= ALGO_MD5;
      else if (valueLength == 8 &&
          nsCRT::strncasecmp(challenge+valueStart, "MD5-sess", 8) == 0)
        *algorithm |= ALGO_MD5_SESS;
    }
    else if (nameLength == 3 &&
        nsCRT::strncasecmp(challenge+nameStart, "qop", 3) == 0)
    {
      PRInt16 ipos = valueStart;
      while (ipos < valueStart+valueLength) {
        while (ipos < valueStart+valueLength &&
               (nsCRT::IsAsciiSpace(challenge[ipos]) ||
                challenge[ipos] == ',')) 
          ipos++;
        PRInt16 algostart = ipos;
        while (ipos < valueStart+valueLength &&
               !nsCRT::IsAsciiSpace(challenge[ipos]) &&
               challenge[ipos] != ',') 
          ipos++;
        if ((ipos - algostart) == 4 &&
            nsCRT::strncasecmp(challenge+algostart, "auth", 4) == 0)
          *qop |= QOP_AUTH;
        else if ((ipos - algostart) == 8 &&
            nsCRT::strncasecmp(challenge+algostart, "auth-int", 8) == 0)
          *qop |= QOP_AUTH_INT;
      }
    }
  }
  return NS_OK;
}

Here is the call graph for this function:


Member Data Documentation

readonly attribute unsigned long nsIHttpAuthenticator::authFlags [inherited]

Flags defining various properties of the authenticator.

Definition at line 134 of file nsIHttpAuthenticator.idl.

const unsigned long nsIHttpAuthenticator::CONNECTION_BASED = (1<<1) [inherited]

A connection based authentication scheme authenticates an individual connection.

Multiple requests may be issued over the connection without repeating the authentication steps. Connection based authentication schemes can associate state with the connection being authenticated via the aContinuationState parameter (see generateCredentials).

Definition at line 151 of file nsIHttpAuthenticator.idl.

const unsigned long nsIHttpAuthenticator::IDENTITY_IGNORED = (1<<10) [inherited]

This flag indicates that the identity of the user is not required by this authentication scheme.

Definition at line 173 of file nsIHttpAuthenticator.idl.

This flag indicates that the identity of the user includes a domain attribute that the user must supply.

Definition at line 179 of file nsIHttpAuthenticator.idl.

Definition at line 119 of file nsHttpDigestAuth.h.

Definition at line 118 of file nsHttpDigestAuth.h.

Definition at line 117 of file nsHttpDigestAuth.h.

const unsigned long nsIHttpAuthenticator::REQUEST_BASED = (1<<0) [inherited]

A request based authentication scheme only authenticates an individual request (or a set of requests under the same authentication domain as defined by RFC 2617).

BASIC and DIGEST are request based authentication schemes.

Definition at line 142 of file nsIHttpAuthenticator.idl.

const unsigned long nsIHttpAuthenticator::REUSABLE_CHALLENGE = (1<<3) [inherited]

A challenge may be reused to later generate credentials in anticipation of a duplicate server challenge for URLs within "the protection space" as defined by RFC 2617 section 1.2.

Definition at line 167 of file nsIHttpAuthenticator.idl.

const unsigned long nsIHttpAuthenticator::REUSABLE_CREDENTIALS = (1<<2) [inherited]

The credentials returned from generateCredentials may be reused with any other URLs within "the protection space" as defined by RFC 2617 section 1.2.

If this flag is not set, then generateCredentials must be called for each request within the protection space. REUSABLE_CREDENTIALS implies REUSABLE_CHALLENGE.

Definition at line 160 of file nsIHttpAuthenticator.idl.


The documentation for this class was generated from the following files: