http_auth_sspi_win.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See "SSPI Sample Application" at 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/aa918273.aspx 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth_sspi_win.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_auth.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapAcquireCredentialsStatusToError(SECURITY_STATUS status, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SEC_WCHAR* package) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "AcquireCredentialsHandle returned 0x" << std::hex << status; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_OK: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INSUFFICIENT_MEMORY: 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_OUT_OF_MEMORY; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INTERNAL_ERROR: 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "AcquireCredentialsHandle returned unexpected status 0x" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_NO_CREDENTIALS: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_NOT_OWNER: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_UNKNOWN_CREDENTIALS: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_AUTH_CREDENTIALS; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_SECPKG_NOT_FOUND: 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This indicates that the SSPI configuration does not match expectations 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNSUPPORTED_AUTH_SCHEME; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "AcquireCredentialsHandle returned undocumented status 0x" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AcquireExplicitCredentials(SSPILibrary* library, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SEC_WCHAR* package, 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& domain, 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& user, 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::string16& password, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CredHandle* cred) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_WINNT_AUTH_IDENTITY identity; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.User = 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(user.c_str())); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.UserLength = user.size(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.Domain = 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(domain.c_str())); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.DomainLength = domain.size(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.Password = 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned short*>(const_cast<wchar_t*>(password.c_str())); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) identity.PasswordLength = password.size(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeStamp expiry; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass the username/password to get the credentials handle. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_STATUS status = library->AcquireCredentialsHandle( 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pszPrincipal 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<SEC_WCHAR*>(package), // pszPackage 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECPKG_CRED_OUTBOUND, // fCredentialUse 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pvLogonID 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &identity, // pAuthData 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pGetKeyFn (not used) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pvGetKeyArgument (not used) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cred, // phCredential 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &expiry); // ptsExpiry 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapAcquireCredentialsStatusToError(status, package); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AcquireDefaultCredentials(SSPILibrary* library, const SEC_WCHAR* package, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CredHandle* cred) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeStamp expiry; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass the username/password to get the credentials handle. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: Since the 5th argument is NULL, it uses the default 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cached credentials for the logged in user, which can be used 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for a single sign-on. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_STATUS status = library->AcquireCredentialsHandle( 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pszPrincipal 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<SEC_WCHAR*>(package), // pszPackage 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECPKG_CRED_OUTBOUND, // fCredentialUse 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pvLogonID 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pAuthData 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pGetKeyFn (not used) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // pvGetKeyArgument (not used) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cred, // phCredential 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &expiry); // ptsExpiry 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapAcquireCredentialsStatusToError(status, package); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapInitializeSecurityContextStatusToError(SECURITY_STATUS status) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "InitializeSecurityContext returned 0x" << std::hex << status; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_OK: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_I_CONTINUE_NEEDED: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_I_COMPLETE_AND_CONTINUE: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_I_COMPLETE_NEEDED: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_I_INCOMPLETE_CREDENTIALS: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INCOMPLETE_MESSAGE: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INTERNAL_ERROR: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These are return codes reported by InitializeSecurityContext 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but not expected by Chrome (for example, INCOMPLETE_CREDENTIALS 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and INCOMPLETE_MESSAGE are intended for schannel). 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "InitializeSecurityContext returned unexpected status 0x" 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INSUFFICIENT_MEMORY: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_OUT_OF_MEMORY; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_UNSUPPORTED_FUNCTION: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INVALID_HANDLE: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_HANDLE; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_INVALID_TOKEN: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_RESPONSE; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_LOGON_DENIED: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_ACCESS_DENIED; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_NO_CREDENTIALS: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_WRONG_PRINCIPAL: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_AUTH_CREDENTIALS; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_NO_AUTHENTICATING_AUTHORITY: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_TARGET_UNKNOWN: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_MISCONFIGURED_AUTH_ENVIRONMENT; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "InitializeSecurityContext returned undocumented status 0x" 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapQuerySecurityPackageInfoStatusToError(SECURITY_STATUS status) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "QuerySecurityPackageInfo returned 0x" << std::hex << status; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_OK: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_SECPKG_NOT_FOUND: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This isn't a documented return code, but has been encountered 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // during testing. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNSUPPORTED_AUTH_SCHEME; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "QuerySecurityPackageInfo returned undocumented status 0x" 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapFreeContextBufferStatusToError(SECURITY_STATUS status) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "FreeContextBuffer returned 0x" << std::hex << status; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_E_OK: 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The documentation at 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://msdn.microsoft.com/en-us/library/aa375416(VS.85).aspx 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only mentions that a non-zero (or non-SEC_E_OK) value is returned 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if the function fails, and does not indicate what the failure 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // conditions are. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "FreeContextBuffer returned undocumented status 0x" 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << std::hex << status; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // anonymous namespace 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthSSPI::HttpAuthSSPI(SSPILibrary* library, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& scheme, 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const SEC_WCHAR* security_package, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG max_token_length) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : library_(library), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scheme_(scheme), 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) security_package_(security_package), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_token_length_(max_token_length), 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_delegate_(false) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(library_); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecInvalidateHandle(&cred_); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecInvalidateHandle(&ctxt_); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuthSSPI::~HttpAuthSSPI() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetSecurityContext(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SecIsValidHandle(&cred_)) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) library_->FreeCredentialsHandle(&cred_); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecInvalidateHandle(&cred_); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpAuthSSPI::NeedsIdentity() const { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return decoded_server_auth_token_.empty(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpAuthSSPI::AllowsExplicitCredentials() const { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpAuthSSPI::Delegate() { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) can_delegate_ = true; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpAuthSSPI::ResetSecurityContext() { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SecIsValidHandle(&ctxt_)) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) library_->DeleteSecurityContext(&ctxt_); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecInvalidateHandle(&ctxt_); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge( 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HttpAuth::ChallengeTokenizer* tok) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify the challenge's auth-scheme. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str())) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_INVALID; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_auth_token = tok->base64_param(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoded_auth_token.empty()) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a context has already been established, an empty challenge 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be treated as a rejection of the current attempt. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SecIsValidHandle(&ctxt_)) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_REJECT; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(decoded_server_auth_token_.empty()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_ACCEPT; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a context has not already been established, additional tokens should 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not be present in the auth challenge. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SecIsValidHandle(&ctxt_)) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_INVALID; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string decoded_auth_token; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool base64_rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base64_rv) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_INVALID; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded_server_auth_token_ = decoded_auth_token; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return HttpAuth::AUTHORIZATION_RESULT_ACCEPT; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& spn, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* auth_token) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initial challenge. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SecIsValidHandle(&cred_)) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = OnFirstRound(credentials); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(SecIsValidHandle(&cred_)); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* out_buf; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int out_buf_len; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = GetNextSecurityToken( 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spn, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<void *>(const_cast<char *>( 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded_server_auth_token_.c_str())), 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded_server_auth_token_.length(), 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &out_buf, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &out_buf_len); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Base64 encode data in output buffer and prepend the scheme. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encode_input(static_cast<char*>(out_buf), out_buf_len); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encode_output; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool base64_rv = base::Base64Encode(encode_input, &encode_output); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OK, we are done with |out_buf| 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(out_buf); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base64_rv) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Base64 encoding of auth token failed."; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_ENCODING_CONVERSION_FAILED; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *auth_token = scheme_ + " " + encode_output; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthSSPI::OnFirstRound(const AuthCredentials* credentials) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!SecIsValidHandle(&cred_)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = OK; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (credentials) { 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::string16 domain; 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::string16 user; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SplitDomainAndUser(credentials->username(), &domain, &user); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = AcquireExplicitCredentials(library_, security_package_, domain, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user, credentials->password(), &cred_); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = AcquireDefaultCredentials(library_, security_package_, &cred_); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpAuthSSPI::GetNextSecurityToken( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& spn, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* in_token, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int in_token_len, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void** out_token, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* out_token_len) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CtxtHandle* ctxt_ptr; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecBufferDesc in_buffer_desc, out_buffer_desc; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecBufferDesc* in_buffer_desc_ptr; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SecBuffer in_buffer, out_buffer; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_token_len > 0) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare input buffer. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc.ulVersion = SECBUFFER_VERSION; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc.cBuffers = 1; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc.pBuffers = &in_buffer; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer.BufferType = SECBUFFER_TOKEN; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer.cbBuffer = in_token_len; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer.pvBuffer = const_cast<void*>(in_token); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctxt_ptr = &ctxt_; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc_ptr = &in_buffer_desc; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no input token, then we are starting a new authentication 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // sequence. If we have already initialized our security context, then 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we're incorrectly reusing the auth handler for a new sequence. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SecIsValidHandle(&ctxt_)) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_UNEXPECTED; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctxt_ptr = NULL; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc_ptr = NULL; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prepare output buffer. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer_desc.ulVersion = SECBUFFER_VERSION; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer_desc.cBuffers = 1; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer_desc.pBuffers = &out_buffer; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer.BufferType = SECBUFFER_TOKEN; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer.cbBuffer = max_token_length_; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer.pvBuffer = malloc(out_buffer.cbBuffer); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!out_buffer.pvBuffer) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_OUT_OF_MEMORY; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD context_flags = 0; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Firefox only sets ISC_REQ_DELEGATE, but MSDN documentation indicates that 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ISC_REQ_MUTUAL_AUTH must also be set. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_delegate_) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_flags |= (ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This returns a token that is passed to the remote server. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD context_attribute; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_STATUS status = library_->InitializeSecurityContext( 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cred_, // phCredential 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ctxt_ptr, // phContext 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<wchar_t *>(spn.c_str()), // pszTargetName 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_flags, // fContextReq 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // Reserved1 (must be 0) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_NATIVE_DREP, // TargetDataRep 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_buffer_desc_ptr, // pInput 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, // Reserved2 (must be 0) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ctxt_, // phNewContext 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &out_buffer_desc, // pOutput 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &context_attribute, // pfContextAttr 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); // ptsExpiry 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = MapInitializeSecurityContextStatusToError(status); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetSecurityContext(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(out_buffer.pvBuffer); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!out_buffer.cbBuffer) { 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(out_buffer.pvBuffer); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_buffer.pvBuffer = NULL; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_token = out_buffer.pvBuffer; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out_token_len = out_buffer.cbBuffer; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SplitDomainAndUser(const base::string16& combined, 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::string16* domain, 395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::string16* user) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |combined| may be in the form "user" or "DOMAIN\user". 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Separate the two parts if they exist. 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(cbentzel): I believe user@domain is also a valid form. 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t backslash_idx = combined.find(L'\\'); 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (backslash_idx == base::string16::npos) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) domain->clear(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *user = combined; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *domain = combined.substr(0, backslash_idx); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *user = combined.substr(backslash_idx + 1); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int DetermineMaxTokenLength(SSPILibrary* library, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& package, 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG* max_token_length) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(library); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(max_token_length); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PSecPkgInfo pkg_info = NULL; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECURITY_STATUS status = library->QuerySecurityPackageInfo( 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<wchar_t *>(package.c_str()), &pkg_info); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = MapQuerySecurityPackageInfoStatusToError(status); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int token_length = pkg_info->cbMaxToken; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = library->FreeContextBuffer(pkg_info); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = MapFreeContextBufferStatusToError(status); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *max_token_length = token_length; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 430