// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_HTTP_HTTP_AUTH_H_
#define NET_HTTP_HTTP_AUTH_H_
#pragma once
#include <set>
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "net/http/http_util.h"
template <class T> class scoped_refptr;
namespace net {
class BoundNetLog;
class HttpAuthHandler;
class HttpAuthHandlerFactory;
class HttpResponseHeaders;
// Utility class for http authentication.
class HttpAuth {
public:
// Http authentication can be done the the proxy server, origin server,
// or both. This enum tracks who the target is.
enum Target {
AUTH_NONE = -1,
// We depend on the valid targets (!= AUTH_NONE) being usable as indexes
// in an array, so start from 0.
AUTH_PROXY = 0,
AUTH_SERVER = 1,
AUTH_NUM_TARGETS = 2,
};
// What the HTTP WWW-Authenticate/Proxy-Authenticate headers indicate about
// the previous authorization attempt.
enum AuthorizationResult {
AUTHORIZATION_RESULT_ACCEPT, // The authorization attempt was accepted,
// although there still may be additional
// rounds of challenges.
AUTHORIZATION_RESULT_REJECT, // The authorization attempt was rejected.
AUTHORIZATION_RESULT_STALE, // (Digest) The nonce used in the
// authorization attempt is stale, but
// otherwise the attempt was valid.
AUTHORIZATION_RESULT_INVALID, // The authentication challenge headers are
// poorly formed (the authorization attempt
// itself may have been fine).
AUTHORIZATION_RESULT_DIFFERENT_REALM, // The authorization
// attempt was rejected,
// but the realm associated
// with the new challenge
// is different from the
// previous attempt.
};
// Describes where the identity used for authentication came from.
enum IdentitySource {
// Came from nowhere -- the identity is not initialized.
IDENT_SRC_NONE,
// The identity came from the auth cache, by doing a path-based
// lookup (premptive authorization).
IDENT_SRC_PATH_LOOKUP,
// The identity was extracted from a URL of the form:
// http://<username>:<password>@host:port
IDENT_SRC_URL,
// The identity was retrieved from the auth cache, by doing a
// realm lookup.
IDENT_SRC_REALM_LOOKUP,
// The identity was provided by RestartWithAuth -- it likely
// came from a prompt (or maybe the password manager).
IDENT_SRC_EXTERNAL,
// The identity used the default credentials for the computer,
// on schemes that support single sign-on.
IDENT_SRC_DEFAULT_CREDENTIALS,
};
enum Scheme {
AUTH_SCHEME_BASIC = 0,
AUTH_SCHEME_DIGEST,
AUTH_SCHEME_NTLM,
AUTH_SCHEME_NEGOTIATE,
AUTH_SCHEME_MOCK,
AUTH_SCHEME_MAX,
};
// Helper structure used by HttpNetworkTransaction to track
// the current identity being used for authorization.
struct Identity {
Identity();
IdentitySource source;
bool invalid;
string16 username;
string16 password;
};
// Get the name of the header containing the auth challenge
// (either WWW-Authenticate or Proxy-Authenticate).
static std::string GetChallengeHeaderName(Target target);
// Get the name of the header where the credentials go
// (either Authorization or Proxy-Authorization).
static std::string GetAuthorizationHeaderName(Target target);
// Returns a string representation of a Target value that can be used in log
// messages.
static std::string GetAuthTargetString(Target target);
// Returns a string representation of an authentication Scheme.
static const char* SchemeToString(Scheme scheme);
// Iterate through the challenge headers, and pick the best one that
// we support. Obtains the implementation class for handling the challenge,
// and passes it back in |*handler|. If no supported challenge was found,
// |*handler| is set to NULL.
//
// |disabled_schemes| is the set of schemes that we should not use.
//
// |origin| is used by the NTLM and Negotiation authentication scheme to
// construct the service principal name. It is ignored by other schemes.
static void ChooseBestChallenge(
HttpAuthHandlerFactory* http_auth_handler_factory,
const HttpResponseHeaders* headers,
Target target,
const GURL& origin,
const std::set<Scheme>& disabled_schemes,
const BoundNetLog& net_log,
scoped_ptr<HttpAuthHandler>* handler);
// Handle a 401/407 response from a server/proxy after a previous
// authentication attempt. For connection-based authentication schemes, the
// new response may be another round in a multi-round authentication sequence.
// For request-based schemes, a 401/407 response is typically treated like a
// rejection of the previous challenge, except in the Digest case when a
// "stale" attribute is present.
//
// |handler| must be non-NULL, and is the HttpAuthHandler from the previous
// authentication round.
//
// |headers| must be non-NULL and contain the new HTTP response.
//
// |target| specifies whether the authentication challenge response came
// from a server or a proxy.
//
// |disabled_schemes| are the authentication schemes to ignore.
//
// |challenge_used| is the text of the authentication challenge used in
// support of the returned AuthorizationResult. If no headers were used for
// the result (for example, all headers have unknown authentication schemes),
// the value is cleared.
static AuthorizationResult HandleChallengeResponse(
HttpAuthHandler* handler,
const HttpResponseHeaders* headers,
Target target,
const std::set<Scheme>& disabled_schemes,
std::string* challenge_used);
// Breaks up a challenge string into the the auth scheme and parameter list,
// according to RFC 2617 Sec 1.2:
// challenge = auth-scheme 1*SP 1#auth-param
//
// Depending on the challenge scheme, it may be appropriate to interpret the
// parameters as either a base-64 encoded string or a comma-delimited list
// of name-value pairs. param_pairs() and base64_param() methods are provided
// to support either usage.
class ChallengeTokenizer {
public:
ChallengeTokenizer(std::string::const_iterator begin,
std::string::const_iterator end)
: begin_(begin),
end_(end),
scheme_begin_(begin),
scheme_end_(begin),
params_begin_(end),
params_end_(end) {
Init(begin, end);
}
// Get the original text.
std::string challenge_text() const {
return std::string(begin_, end_);
}
// Get the auth scheme of the challenge.
std::string::const_iterator scheme_begin() const { return scheme_begin_; }
std::string::const_iterator scheme_end() const { return scheme_end_; }
std::string scheme() const {
return std::string(scheme_begin_, scheme_end_);
}
HttpUtil::NameValuePairsIterator param_pairs() const;
std::string base64_param() const;
private:
void Init(std::string::const_iterator begin,
std::string::const_iterator end);
std::string::const_iterator begin_;
std::string::const_iterator end_;
std::string::const_iterator scheme_begin_;
std::string::const_iterator scheme_end_;
std::string::const_iterator params_begin_;
std::string::const_iterator params_end_;
};
};
} // namespace net
#endif // NET_HTTP_HTTP_AUTH_H_