1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_auth_gssapi_posix.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <limits>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/format_macros.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread_restrictions.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These are defined for the GSSAPI library:
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Paraphrasing the comments from gssapi.h:
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// "The implementation must reserve static storage for a
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// gss_OID_desc object for each constant.  That constant
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// should be initialized to point to that gss_OID_desc."
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_USER_NAME_VAL = {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  10,
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01")
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_MACHINE_UID_NAME_VAL = {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  10,
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02")
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_STRING_UID_NAME_VAL = {
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  10,
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03")
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_X_VAL = {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  6,
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2b\x06\x01\x05\x06\x02")
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_HOSTBASED_SERVICE_VAL = {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  10,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_ANONYMOUS_VAL = {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  6,
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2b\x06\01\x05\x06\x03")
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic gss_OID_desc GSS_C_NT_EXPORT_NAME_VAL = {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  6,
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2b\x06\x01\x05\x06\x04")
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_USER_NAME = &GSS_C_NT_USER_NAME_VAL;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_MACHINE_UID_NAME = &GSS_C_NT_MACHINE_UID_NAME_VAL;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_STRING_UID_NAME = &GSS_C_NT_STRING_UID_NAME_VAL;
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_HOSTBASED_SERVICE_X = &GSS_C_NT_HOSTBASED_SERVICE_X_VAL;
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_HOSTBASED_SERVICE = &GSS_C_NT_HOSTBASED_SERVICE_VAL;
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_ANONYMOUS = &GSS_C_NT_ANONYMOUS_VAL;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID GSS_C_NT_EXPORT_NAME = &GSS_C_NT_EXPORT_NAME_VAL;
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These are encoded using ASN.1 BER encoding.
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This one is used by Firefox's nsAuthGSSAPI class.
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID_desc CHROME_GSS_KRB5_MECH_OID_DESC_VAL = {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  9,
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02")
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID_desc CHROME_GSS_C_NT_HOSTBASED_SERVICE_X_VAL = {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  6,
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2b\x06\x01\x05\x06\x02")
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID_desc CHROME_GSS_C_NT_HOSTBASED_SERVICE_VAL = {
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  10,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const_cast<char*>("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE_X =
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CHROME_GSS_C_NT_HOSTBASED_SERVICE_X_VAL;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE =
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CHROME_GSS_C_NT_HOSTBASED_SERVICE_VAL;
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgss_OID CHROME_GSS_KRB5_MECH_OID_DESC =
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CHROME_GSS_KRB5_MECH_OID_DESC_VAL;
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Debugging helpers.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DisplayStatus(OM_uint32 major_status,
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          OM_uint32 minor_status) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (major_status == GSS_S_COMPLETE)
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return "OK";
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return base::StringPrintf("0x%08X 0x%08X", major_status, minor_status);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DisplayCode(GSSAPILibrary* gssapi_lib,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        OM_uint32 status,
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        OM_uint32 status_code_type) {
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const int kMaxDisplayIterations = 8;
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t kMaxMsgLength = 4096;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // msg_ctx needs to be outside the loop because it is invoked multiple times.
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 msg_ctx = 0;
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string rv = base::StringPrintf("(0x%08X)", status);
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This loop should continue iterating until msg_ctx is 0 after the first
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // iteration. To be cautious and prevent an infinite loop, it stops after
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a finite number of iterations as well. As an added sanity check, no
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // individual message may exceed |kMaxMsgLength|, and the final result
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // will not exceed |kMaxMsgLength|*2-1.
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < kMaxDisplayIterations && rv.size() < kMaxMsgLength;
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       ++i) {
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 min_stat;
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_desc_struct msg = GSS_C_EMPTY_BUFFER;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 maj_stat =
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gssapi_lib->display_status(&min_stat, status, status_code_type,
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   GSS_C_NULL_OID, &msg_ctx, &msg);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (maj_stat == GSS_S_COMPLETE) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int msg_len = (msg.length > kMaxMsgLength) ?
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          static_cast<int>(kMaxMsgLength) :
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          static_cast<int>(msg.length);
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (msg_len > 0 && msg.value != NULL) {
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        rv += base::StringPrintf(" %.*s", msg_len,
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 static_cast<char*>(msg.value));
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gssapi_lib->release_buffer(&min_stat, &msg);
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!msg_ctx)
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DisplayExtendedStatus(GSSAPILibrary* gssapi_lib,
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  OM_uint32 major_status,
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  OM_uint32 minor_status) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (major_status == GSS_S_COMPLETE)
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return "OK";
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string major = DisplayCode(gssapi_lib, major_status, GSS_C_GSS_CODE);
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string minor = DisplayCode(gssapi_lib, minor_status, GSS_C_MECH_CODE);
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return base::StringPrintf("Major: %s | Minor: %s", major.c_str(),
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            minor.c_str());
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScopedName releases a gss_name_t when it goes out of scope.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedName {
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedName(gss_name_t name,
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             GSSAPILibrary* gssapi_lib)
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : name_(name),
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gssapi_lib_(gssapi_lib) {
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(gssapi_lib_);
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~ScopedName() {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (name_ != GSS_C_NO_NAME) {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OM_uint32 minor_status = 0;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OM_uint32 major_status =
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          gssapi_lib_->release_name(&minor_status, &name_);
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (major_status != GSS_S_COMPLETE) {
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(WARNING) << "Problem releasing name. "
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     << DisplayStatus(major_status, minor_status);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      name_ = GSS_C_NO_NAME;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_name_t name_;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GSSAPILibrary* gssapi_lib_;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedName);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ScopedBuffer releases a gss_buffer_t when it goes out of scope.
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ScopedBuffer {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedBuffer(gss_buffer_t buffer,
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               GSSAPILibrary* gssapi_lib)
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : buffer_(buffer),
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        gssapi_lib_(gssapi_lib) {
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(gssapi_lib_);
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~ScopedBuffer() {
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (buffer_ != GSS_C_NO_BUFFER) {
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OM_uint32 minor_status = 0;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      OM_uint32 major_status =
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          gssapi_lib_->release_buffer(&minor_status, buffer_);
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (major_status != GSS_S_COMPLETE) {
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(WARNING) << "Problem releasing buffer. "
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     << DisplayStatus(major_status, minor_status);
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      buffer_ = GSS_C_NO_BUFFER;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_buffer_t buffer_;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GSSAPILibrary* gssapi_lib_;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedBuffer);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string AppendIfPredefinedValue(gss_OID oid,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    gss_OID predefined_oid,
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    const char* predefined_oid_name) {
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(oid);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(predefined_oid);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(predefined_oid_name);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string output;
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (oid->length != predefined_oid->length)
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return output;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (0 != memcmp(oid->elements,
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  predefined_oid->elements,
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  predefined_oid->length))
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return output;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += " (";
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += predefined_oid_name;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += ")";
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return output;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DescribeOid(GSSAPILibrary* gssapi_lib, const gss_OID oid) {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!oid)
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return "<NULL>";
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string output;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const size_t kMaxCharsToPrint = 1024;
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 byte_length = oid->length;
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t char_length = byte_length / sizeof(char);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (char_length > kMaxCharsToPrint) {
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This might be a plain ASCII string.
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check if the first |kMaxCharsToPrint| characters
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // contain only printable characters and are NULL terminated.
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* str = reinterpret_cast<const char*>(oid);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool is_printable = true;
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    size_t str_length = 0;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for ( ; str_length < kMaxCharsToPrint; ++str_length) {
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!str[str_length])
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!isprint(str[str_length])) {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        is_printable = false;
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!str[str_length]) {
2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      output += base::StringPrintf("\"%s\"", str);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return output;
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  output = base::StringPrintf("(%u) \"", byte_length);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!oid->elements) {
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    output += "<NULL>";
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return output;
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const unsigned char* elements =
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      reinterpret_cast<const unsigned char*>(oid->elements);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't print more than |kMaxCharsToPrint| characters.
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t i = 0;
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for ( ; (i < byte_length) && (i < kMaxCharsToPrint); ++i) {
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    output += base::StringPrintf("\\x%02X", elements[i]);
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (i >= kMaxCharsToPrint)
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    output += "...";
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += "\"";
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Check if the OID is one of the predefined values.
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_USER_NAME,
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_USER_NAME");
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_MACHINE_UID_NAME,
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_MACHINE_UID_NAME");
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_STRING_UID_NAME,
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_STRING_UID_NAME");
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_HOSTBASED_SERVICE_X,
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_HOSTBASED_SERVICE_X");
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_HOSTBASED_SERVICE,
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_HOSTBASED_SERVICE");
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_ANONYMOUS,
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_ANONYMOUS");
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  output += AppendIfPredefinedValue(oid,
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GSS_C_NT_EXPORT_NAME,
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    "GSS_C_NT_EXPORT_NAME");
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return output;
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DescribeName(GSSAPILibrary* gssapi_lib, const gss_name_t name) {
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 major_status = 0;
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 minor_status = 0;
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_buffer_desc_struct output_name_buffer = GSS_C_EMPTY_BUFFER;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_OID_desc output_name_type_desc = GSS_C_EMPTY_BUFFER;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_OID output_name_type = &output_name_type_desc;
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  major_status = gssapi_lib->display_name(&minor_status,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          name,
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          &output_name_buffer,
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          &output_name_type);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedBuffer scoped_output_name(&output_name_buffer, gssapi_lib);
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (major_status != GSS_S_COMPLETE) {
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string error =
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        base::StringPrintf("Unable to describe name 0x%p, %s",
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           name,
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           DisplayExtendedStatus(gssapi_lib,
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 major_status,
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 minor_status).c_str());
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return error;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int len = output_name_buffer.length;
3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string description = base::StringPrintf(
3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      "%*s (Type %s)",
3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      len,
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      reinterpret_cast<const char*>(output_name_buffer.value),
3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DescribeOid(gssapi_lib, output_name_type).c_str());
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return description;
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string DescribeContext(GSSAPILibrary* gssapi_lib,
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const gss_ctx_id_t context_handle) {
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 major_status = 0;
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 minor_status = 0;
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_name_t src_name = GSS_C_NO_NAME;
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_name_t targ_name = GSS_C_NO_NAME;
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 lifetime_rec = 0;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_OID mech_type = GSS_C_NO_OID;
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 ctx_flags = 0;
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int locally_initiated = 0;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int open = 0;
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  major_status = gssapi_lib->inquire_context(&minor_status,
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             context_handle,
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &src_name,
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &targ_name,
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &lifetime_rec,
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &mech_type,
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &ctx_flags,
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &locally_initiated,
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                             &open);
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedName(src_name, gssapi_lib);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedName(targ_name, gssapi_lib);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (major_status != GSS_S_COMPLETE) {
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string error =
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        base::StringPrintf("Unable to describe context 0x%p, %s",
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           context_handle,
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           DisplayExtendedStatus(gssapi_lib,
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 major_status,
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                 minor_status).c_str());
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return error;
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string source(DescribeName(gssapi_lib, src_name));
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string target(DescribeName(gssapi_lib, targ_name));
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string description = base::StringPrintf("Context 0x%p: "
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                               "Source \"%s\", "
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                               "Target \"%s\", "
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                "lifetime %d, "
3703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                "mechanism %s, "
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                "flags 0x%08X, "
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                "local %d, "
3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                "open %d",
3743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                context_handle,
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                source.c_str(),
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                target.c_str(),
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                lifetime_rec,
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                DescribeOid(gssapi_lib,
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                            mech_type).c_str(),
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                ctx_flags,
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                locally_initiated,
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                open);
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return description;
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochGSSAPISharedLibrary::GSSAPISharedLibrary(const std::string& gssapi_library_name)
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : initialized_(false),
3904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      gssapi_library_name_(gssapi_library_name),
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gssapi_library_(NULL),
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      import_name_(NULL),
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      release_name_(NULL),
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      release_buffer_(NULL),
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      display_name_(NULL),
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      display_status_(NULL),
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      init_sec_context_(NULL),
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      wrap_size_limit_(NULL),
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete_sec_context_(NULL),
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      inquire_context_(NULL) {
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGSSAPISharedLibrary::~GSSAPISharedLibrary() {
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (gssapi_library_) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    base::UnloadNativeLibrary(gssapi_library_);
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gssapi_library_ = NULL;
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GSSAPISharedLibrary::Init() {
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!initialized_)
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InitImpl();
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return initialized_;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GSSAPISharedLibrary::InitImpl() {
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!initialized_);
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gssapi_library_ = LoadSharedLibrary();
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (gssapi_library_ == NULL)
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  initialized_ = true;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbase::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary() {
4264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const char** library_names;
4274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  size_t num_lib_names;
4284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const char* user_specified_library[1];
4294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!gssapi_library_name_.empty()) {
4304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    user_specified_library[0] = gssapi_library_name_.c_str();
4314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    library_names = user_specified_library;
4324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    num_lib_names = 1;
4334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  } else {
4344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    static const char* kDefaultLibraryNames[] = {
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX)
4364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      "libgssapi_krb5.dylib"  // MIT Kerberos
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else
4384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      "libgssapi_krb5.so.2",  // MIT Kerberos - FC, Suse10, Debian
4394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      "libgssapi.so.4",       // Heimdal - Suse10, MDK
440ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      "libgssapi.so.2",       // Heimdal - Gentoo
4414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      "libgssapi.so.1"        // Heimdal - Suse9, CITI - FC, MDK, Suse10
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
4434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    };
4444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    library_names = kDefaultLibraryNames;
4454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    num_lib_names = arraysize(kDefaultLibraryNames);
4464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < num_lib_names; ++i) {
4494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const char* library_name = library_names[i];
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    FilePath file_path(library_name);
45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // TODO(asanka): Move library loading to a separate thread.
45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    //               http://crbug.com/66702
45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    base::ThreadRestrictions::ScopedAllowIO allow_io_temporarily;
455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::NativeLibrary lib = base::LoadNativeLibrary(file_path, NULL);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (lib) {
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Only return this library if we can bind the functions we need.
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (BindMethods(lib))
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return lib;
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::UnloadNativeLibrary(lib);
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG(WARNING) << "Unable to find a compatible GSSAPI library";
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#define BIND(lib, x)                                                    \
4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  gss_##x##_type x = reinterpret_cast<gss_##x##_type>(                  \
4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::GetFunctionPointerFromNativeLibrary(lib, "gss_" #x));       \
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (x == NULL) {                                                      \
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(WARNING) << "Unable to bind function \"" << "gss_" #x << "\"";  \
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return false;                                                       \
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib) {
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(lib != NULL);
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, import_name);
4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, release_name);
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, release_buffer);
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, display_name);
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, display_status);
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, init_sec_context);
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, wrap_size_limit);
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, delete_sec_context);
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  BIND(lib, inquire_context);
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  import_name_ = import_name;
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  release_name_ = release_name;
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  release_buffer_ = release_buffer;
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  display_name_ = display_name;
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  display_status_ = display_status;
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  init_sec_context_ = init_sec_context;
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  wrap_size_limit_ = wrap_size_limit;
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delete_sec_context_ = delete_sec_context;
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  inquire_context_ = inquire_context;
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#undef BIND
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::import_name(
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_buffer_t input_name_buffer,
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_OID input_name_type,
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_name_t* output_name) {
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return import_name_(minor_status, input_name_buffer, input_name_type,
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      output_name);
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::release_name(
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_name_t* input_name) {
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return release_name_(minor_status, input_name);
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::release_buffer(
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_t buffer) {
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return release_buffer_(minor_status, buffer);
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::display_name(
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_name_t input_name,
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_t output_name_buffer,
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_OID* output_name_type) {
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return display_name_(minor_status,
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       input_name,
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       output_name_buffer,
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       output_name_type);
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::display_status(
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 status_value,
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int status_type,
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_OID mech_type,
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* message_context,
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_t status_string) {
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return display_status_(minor_status, status_value, status_type, mech_type,
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         message_context, status_string);
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::init_sec_context(
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_cred_id_t initiator_cred_handle,
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_ctx_id_t* context_handle,
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_name_t target_name,
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_OID mech_type,
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 req_flags,
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 time_req,
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_channel_bindings_t input_chan_bindings,
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_buffer_t input_token,
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_OID* actual_mech_type,
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_t output_token,
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* ret_flags,
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* time_rec) {
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return init_sec_context_(minor_status,
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           initiator_cred_handle,
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           context_handle,
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           target_name,
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           mech_type,
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           req_flags,
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           time_req,
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           input_chan_bindings,
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           input_token,
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           actual_mech_type,
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           output_token,
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           ret_flags,
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           time_rec);
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::wrap_size_limit(
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_ctx_id_t context_handle,
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int conf_req_flag,
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_qop_t qop_req,
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 req_output_size,
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* max_input_size) {
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return wrap_size_limit_(minor_status,
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          context_handle,
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          conf_req_flag,
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          qop_req,
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          req_output_size,
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          max_input_size);
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::delete_sec_context(
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_ctx_id_t* context_handle,
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_t output_token) {
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is called from the owner class' destructor, even if
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Init() is not called, so we can't assume |initialized_|
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // is set.
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!initialized_)
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return delete_sec_context_(minor_status,
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             context_handle,
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             output_token);
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochOM_uint32 GSSAPISharedLibrary::inquire_context(
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* minor_status,
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const gss_ctx_id_t context_handle,
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_name_t* src_name,
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_name_t* targ_name,
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* lifetime_rec,
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_OID* mech_type,
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32* ctx_flags,
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* locally_initiated,
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* open) {
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(initialized_);
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return inquire_context_(minor_status,
6233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          context_handle,
6243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          src_name,
6253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          targ_name,
6263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          lifetime_rec,
6273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          mech_type,
6283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          ctx_flags,
6293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          locally_initiated,
6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          open);
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochScopedSecurityContext::ScopedSecurityContext(GSSAPILibrary* gssapi_lib)
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : security_context_(GSS_C_NO_CONTEXT),
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gssapi_lib_(gssapi_lib) {
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(gssapi_lib_);
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochScopedSecurityContext::~ScopedSecurityContext() {
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (security_context_ != GSS_C_NO_CONTEXT) {
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 minor_status = 0;
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    OM_uint32 major_status = gssapi_lib_->delete_sec_context(
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        &minor_status, &security_context_, &output_token);
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (major_status != GSS_S_COMPLETE) {
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(WARNING) << "Problem releasing security_context. "
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   << DisplayStatus(major_status, minor_status);
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    security_context_ = GSS_C_NO_CONTEXT;
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpAuthGSSAPI::HttpAuthGSSAPI(GSSAPILibrary* library,
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const std::string& scheme,
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               gss_OID gss_oid)
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : scheme_(scheme),
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gss_oid_(gss_oid),
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      library_(library),
6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      scoped_sec_context_(library),
6603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      can_delegate_(false) {
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(library_);
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpAuthGSSAPI::~HttpAuthGSSAPI() {
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpAuthGSSAPI::Init() {
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!library_)
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return library_->Init();
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpAuthGSSAPI::NeedsIdentity() const {
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return decoded_server_auth_token_.empty();
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpAuthGSSAPI::Delegate() {
6783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  can_delegate_ = true;
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6813345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge(
6823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpAuth::ChallengeTokenizer* tok) {
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Verify the challenge's auth-scheme.
684731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str()))
6853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
687731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  std::string encoded_auth_token = tok->base64_param();
688731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (encoded_auth_token.empty()) {
6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // If a context has already been established, an empty Negotiate challenge
6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // should be treated as a rejection of the current attempt.
6923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (scoped_sec_context_.get() != GSS_C_NO_CONTEXT)
6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return HttpAuth::AUTHORIZATION_RESULT_REJECT;
6943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    DCHECK(decoded_server_auth_token_.empty());
6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // If a context has not already been established, additional tokens should
6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // not be present in the auth challenge.
6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (scoped_sec_context_.get() == GSS_C_NO_CONTEXT)
7003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return HttpAuth::AUTHORIZATION_RESULT_INVALID;
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Make sure the additional token is base64 encoded.
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string decoded_auth_token;
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool base64_rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token);
7063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!base64_rv)
7073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return HttpAuth::AUTHORIZATION_RESULT_INVALID;
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  decoded_server_auth_token_ = decoded_auth_token;
7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return HttpAuth::AUTHORIZATION_RESULT_ACCEPT;
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpAuthGSSAPI::GenerateAuthToken(const string16* username,
7133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                      const string16* password,
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      const std::wstring& spn,
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                      std::string* auth_token) {
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(auth_token);
7173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(username == NULL && password == NULL);
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  input_token.length = decoded_server_auth_token_.length();
7213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  input_token.value = (input_token.length > 0) ?
7223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const_cast<char*>(decoded_server_auth_token_.data()) :
7233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL;
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedBuffer scoped_output_token(&output_token, library_);
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = GetNextSecurityToken(spn, &input_token, &output_token);
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv != OK)
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return rv;
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Base64 encode data in output buffer and prepend the scheme.
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string encode_input(static_cast<char*>(output_token.value),
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           output_token.length);
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string encode_output;
7343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool base64_rv = base::Base64Encode(encode_input, &encode_output);
7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!base64_rv) {
7363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    LOG(ERROR) << "Base64 encoding of auth token failed.";
7373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_ENCODING_CONVERSION_FAILED;
7383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *auth_token = scheme_ + " " + encode_output;
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace {
7453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// GSSAPI status codes consist of a calling error (essentially, a programmer
7473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// bug), a routine error (defined by the RFC), and supplementary information,
7483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// all bitwise-or'ed together in different regions of the 32 bit return value.
7493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// This means a simple switch on the return codes is not sufficient.
7503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint MapImportNameStatusToError(OM_uint32 major_status) {
752731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "import_name returned 0x" << std::hex << major_status;
7533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (major_status == GSS_S_COMPLETE)
7543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return OK;
7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (GSS_CALLING_ERROR(major_status) != 0)
7563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_UNEXPECTED;
7573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OM_uint32 routine_error = GSS_ROUTINE_ERROR(major_status);
7583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch (routine_error) {
7593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_FAILURE:
7603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Looking at the MIT Kerberos implementation, this typically is returned
7613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // when memory allocation fails. However, the API does not guarantee
7623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // that this is the case, so using ERR_UNEXPECTED rather than
7633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // ERR_OUT_OF_MEMORY.
7643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
7653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_NAME:
7663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_NAMETYPE:
7673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_MALFORMED_IDENTITY;
7683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_DEFECTIVE_TOKEN:
7693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Not mentioned in the API, but part of code.
7703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
7713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_MECH:
7723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNSUPPORTED_AUTH_SCHEME;
7733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
7743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS;
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
7763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint MapInitSecContextStatusToError(OM_uint32 major_status) {
779731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  VLOG(1) << "init_sec_context returned 0x" << std::hex << major_status;
7803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Although GSS_S_CONTINUE_NEEDED is an additional bit, it seems like
7813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // other code just checks if major_status is equivalent to it to indicate
7823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // that there are no other errors included.
7833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (major_status == GSS_S_COMPLETE || major_status == GSS_S_CONTINUE_NEEDED)
7843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return OK;
7853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (GSS_CALLING_ERROR(major_status) != 0)
7863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_UNEXPECTED;
7873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OM_uint32 routine_status = GSS_ROUTINE_ERROR(major_status);
7883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch (routine_status) {
7893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_DEFECTIVE_TOKEN:
7903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_INVALID_RESPONSE;
7913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_DEFECTIVE_CREDENTIAL:
7923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Not expected since this implementation uses the default credential.
7933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
7943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_SIG:
7953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Probably won't happen, but it's a bad response.
7963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_INVALID_RESPONSE;
7973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_NO_CRED:
7983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_INVALID_AUTH_CREDENTIALS;
7993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_CREDENTIALS_EXPIRED:
8003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_INVALID_AUTH_CREDENTIALS;
8013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_BINDINGS:
8023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This only happens with mutual authentication.
8033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
8043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_NO_CONTEXT:
8053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
8063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_NAMETYPE:
8073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNSUPPORTED_AUTH_SCHEME;
8083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_NAME:
8093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNSUPPORTED_AUTH_SCHEME;
8103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_BAD_MECH:
8113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS;
8123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case GSS_S_FAILURE:
8133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // This should be an "Unexpected Security Status" according to the
8143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // GSSAPI documentation, but it's typically used to indicate that
8153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // credentials are not correctly set up on a user machine, such
8163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // as a missing credential cache or hitting this after calling
8173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // kdestroy.
8183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // TODO(cbentzel): Use minor code for even better mapping?
8193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return ERR_MISSING_AUTH_CREDENTIALS;
8203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
8213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (routine_status != 0)
8223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS;
8233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
8243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
8253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  OM_uint32 supplemental_status = GSS_SUPPLEMENTARY_INFO(major_status);
8263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Replays could indicate an attack.
8273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (supplemental_status & (GSS_S_DUPLICATE_TOKEN | GSS_S_OLD_TOKEN |
8283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             GSS_S_UNSEQ_TOKEN | GSS_S_GAP_TOKEN))
8293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return ERR_INVALID_RESPONSE;
8303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
8313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // At this point, every documented status has been checked.
8323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS;
8333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
8343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpAuthGSSAPI::GetNextSecurityToken(const std::wstring& spn,
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         gss_buffer_t in_token,
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         gss_buffer_t out_token) {
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a name for the principal
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(cbentzel): Just do this on the first pass?
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string spn_principal = WideToASCII(spn);
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_buffer_desc spn_buffer = GSS_C_EMPTY_BUFFER;
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spn_buffer.value = const_cast<char*>(spn_principal.c_str());
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spn_buffer.length = spn_principal.size() + 1;
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 minor_status = 0;
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gss_name_t principal_name = GSS_C_NO_NAME;
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 major_status = library_->import_name(
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &minor_status,
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &spn_buffer,
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CHROME_GSS_C_NT_HOSTBASED_SERVICE,
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &principal_name);
8533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int rv = MapImportNameStatusToError(major_status);
8543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (rv != OK) {
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "Problem importing name from "
856731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               << "spn \"" << spn_principal << "\"\n"
857731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               << DisplayExtendedStatus(library_, major_status, minor_status);
8583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return rv;
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ScopedName scoped_name(principal_name, library_);
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Continue creating a security context.
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OM_uint32 req_flags = 0;
8643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (can_delegate_)
8653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req_flags |= GSS_C_DELEG_FLAG;
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  major_status = library_->init_sec_context(
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &minor_status,
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GSS_C_NO_CREDENTIAL,
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      scoped_sec_context_.receive(),
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      principal_name,
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gss_oid_,
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      req_flags,
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GSS_C_INDEFINITE,
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GSS_C_NO_CHANNEL_BINDINGS,
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      in_token,
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,  // actual_mech_type
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      out_token,
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL,  // ret flags
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL);
8803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  rv = MapInitSecContextStatusToError(major_status);
8813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (rv != OK) {
882731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(ERROR) << "Problem initializing context. \n"
883731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               << DisplayExtendedStatus(library_, major_status, minor_status)
884731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick               << '\n'
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               << DescribeContext(library_, scoped_sec_context_.get());
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
887731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return rv;
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
891