diff --git a/lib/curl_ntlm_msgs.c b/lib/curl_ntlm_msgs.c index 050ffe25d..e222b73b7 100644 --- a/lib/curl_ntlm_msgs.c +++ b/lib/curl_ntlm_msgs.c @@ -346,17 +346,15 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm) { Curl_safefree(ntlm->type_2); + if(ntlm->has_handles) { s_pSecFn->DeleteSecurityContext(&ntlm->c_handle); s_pSecFn->FreeCredentialsHandle(&ntlm->handle); ntlm->has_handles = 0; } - if(ntlm->p_identity) { - Curl_safefree(ntlm->identity.User); - Curl_safefree(ntlm->identity.Password); - Curl_safefree(ntlm->identity.Domain); - ntlm->p_identity = NULL; - } + + Curl_sspi_free_identity(ntlm->p_identity); + ntlm->p_identity = NULL; } #endif @@ -420,84 +418,20 @@ CURLcode Curl_ntlm_create_type1_message(const char *userp, SecBufferDesc desc; SECURITY_STATUS status; unsigned long attrs; - xcharp_u useranddomain; - xcharp_u user, dup_user; - xcharp_u domain, dup_domain; - xcharp_u passwd, dup_passwd; - size_t domlen = 0; TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */ - domain.const_tchar_ptr = TEXT(""); - Curl_ntlm_sspi_cleanup(ntlm); if(userp && *userp) { + CURLcode result; - /* null initialize ntlm identity's data to allow proper cleanup */ + /* Populate our identity structure */ + result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity); + if(result) + return result; + + /* Allow proper cleanup of the identity structure */ ntlm->p_identity = &ntlm->identity; - memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity)); - - useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); - if(!useranddomain.tchar_ptr) - return CURLE_OUT_OF_MEMORY; - - user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); - if(!user.const_tchar_ptr) - user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); - - if(user.tchar_ptr) { - domain.tchar_ptr = useranddomain.tchar_ptr; - domlen = user.tchar_ptr - useranddomain.tchar_ptr; - user.tchar_ptr++; - } - else { - user.tchar_ptr = useranddomain.tchar_ptr; - domain.const_tchar_ptr = TEXT(""); - domlen = 0; - } - - /* setup ntlm identity's user and length */ - dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); - if(!dup_user.tchar_ptr) { - Curl_unicodefree(useranddomain.tchar_ptr); - return CURLE_OUT_OF_MEMORY; - } - ntlm->identity.User = dup_user.tbyte_ptr; - ntlm->identity.UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); - dup_user.tchar_ptr = NULL; - - /* setup ntlm identity's domain and length */ - dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); - if(!dup_domain.tchar_ptr) { - Curl_unicodefree(useranddomain.tchar_ptr); - return CURLE_OUT_OF_MEMORY; - } - _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); - *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); - ntlm->identity.Domain = dup_domain.tbyte_ptr; - ntlm->identity.DomainLength = curlx_uztoul(domlen); - dup_domain.tchar_ptr = NULL; - - Curl_unicodefree(useranddomain.tchar_ptr); - - /* setup ntlm identity's password and length */ - passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); - if(!passwd.tchar_ptr) - return CURLE_OUT_OF_MEMORY; - dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); - if(!dup_passwd.tchar_ptr) { - Curl_unicodefree(passwd.tchar_ptr); - return CURLE_OUT_OF_MEMORY; - } - ntlm->identity.Password = dup_passwd.tbyte_ptr; - ntlm->identity.PasswordLength = - curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); - dup_passwd.tchar_ptr = NULL; - - Curl_unicodefree(passwd.tchar_ptr); - - /* setup ntlm identity's flags */ - ntlm->identity.Flags = SECFLAG_WINNT_AUTH_IDENTITY; } else ntlm->p_identity = NULL; diff --git a/lib/curl_ntlm_msgs.h b/lib/curl_ntlm_msgs.h index d8000b5fe..80413c885 100644 --- a/lib/curl_ntlm_msgs.h +++ b/lib/curl_ntlm_msgs.h @@ -170,14 +170,6 @@ void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm); #define NTLMFLAG_NEGOTIATE_56 (1<<31) /* Indicates that 56-bit encryption is supported. */ -#ifdef UNICODE -# define SECFLAG_WINNT_AUTH_IDENTITY \ - (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE -#else -# define SECFLAG_WINNT_AUTH_IDENTITY \ - (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI -#endif - #endif /* BUILDING_CURL_NTLM_MSGS_C */ #endif /* USE_NTLM */ diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c index bb41a879c..f09d28827 100644 --- a/lib/curl_sspi.c +++ b/lib/curl_sspi.c @@ -32,6 +32,9 @@ #include #include "curl_memory.h" +#include "curl_multibyte.h" +#include "warnless.h" + /* The last #include file should be: */ #include "memdebug.h" @@ -150,4 +153,105 @@ void Curl_sspi_global_cleanup(void) } } +/* + * Curl_create_sspi_identity() + * + * This is used to populate a SSPI identity structure based on the supplied + * username and password. + * + * Parameters: + * + * userp [in] - The user name in the format User or Domain\User. + * passdwp [in] - The user's password. + * identity [in/out] - The identity structure. + * + * Returns CURLE_OK on success. + */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity) +{ + xcharp_u useranddomain; + xcharp_u user, dup_user; + xcharp_u domain, dup_domain; + xcharp_u passwd, dup_passwd; + size_t domlen = 0; + + domain.const_tchar_ptr = TEXT(""); + + /* Initialize the identity */ + memset(identity, 0, sizeof(*identity)); + + useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); + if(!useranddomain.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\')); + if(!user.const_tchar_ptr) + user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/')); + + if(user.tchar_ptr) { + domain.tchar_ptr = useranddomain.tchar_ptr; + domlen = user.tchar_ptr - useranddomain.tchar_ptr; + user.tchar_ptr++; + } + else { + user.tchar_ptr = useranddomain.tchar_ptr; + domain.const_tchar_ptr = TEXT(""); + domlen = 0; + } + + /* Setup the identity's user and length */ + dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); + if(!dup_user.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->User = dup_user.tbyte_ptr; + identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); + dup_user.tchar_ptr = NULL; + + /* Setup the identity's domain and length */ + dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); + if(!dup_domain.tchar_ptr) { + Curl_unicodefree(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); + *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(domlen); + dup_domain.tchar_ptr = NULL; + + Curl_unicodefree(useranddomain.tchar_ptr); + + /* Setup ntlm identity's password and length */ + passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); + if(!passwd.tchar_ptr) + return CURLE_OUT_OF_MEMORY; + dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); + if(!dup_passwd.tchar_ptr) { + Curl_unicodefree(passwd.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + identity->Password = dup_passwd.tbyte_ptr; + identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); + dup_passwd.tchar_ptr = NULL; + + Curl_unicodefree(passwd.tchar_ptr); + + /* Setup the identity's flags */ + identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; + + return CURLE_OK; +} + +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity) +{ + if(identity) { + Curl_safefree(identity->User); + Curl_safefree(identity->Password); + Curl_safefree(identity->Domain); + } +} + #endif /* USE_WINDOWS_SSPI */ diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h index d52582856..812d7a849 100644 --- a/lib/curl_sspi.h +++ b/lib/curl_sspi.h @@ -43,6 +43,13 @@ CURLcode Curl_sspi_global_init(void); void Curl_sspi_global_cleanup(void); +/* This is used to generate an SSPI identity structure */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to free an SSPI identity structure */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity); + /* Forward-declaration of global variables defined in curl_sspi.c */ extern HMODULE s_hSecDll; @@ -289,5 +296,13 @@ extern PSecurityFunctionTable s_pSecFn; # define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) #endif +#ifdef UNICODE +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE +#else +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI +#endif + #endif /* USE_WINDOWS_SSPI */ #endif /* HEADER_CURL_SSPI_H */