27 #if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5) 51 bool Curl_auth_is_gssapi_supported(
void)
53 PSecPkgInfo SecurityPackage;
54 SECURITY_STATUS status;
57 status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
58 TEXT(SP_NAME_KERBEROS),
61 return (status == SEC_E_OK ?
TRUE :
FALSE);
92 const bool mutual_auth,
94 struct kerberos5data *krb5,
95 char **outptr,
size_t *outlen)
99 unsigned char *chlg = NULL;
101 PSecPkgInfo SecurityPackage;
104 SecBufferDesc chlg_desc;
105 SecBufferDesc resp_desc;
106 SECURITY_STATUS status;
117 if(!krb5->output_token) {
119 status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *)
120 TEXT(SP_NAME_KERBEROS),
122 if(status != SEC_E_OK) {
126 krb5->token_max = SecurityPackage->cbMaxToken;
129 s_pSecFn->FreeContextBuffer(SecurityPackage);
132 krb5->output_token =
malloc(krb5->token_max);
133 if(!krb5->output_token)
137 if(!krb5->credentials) {
139 if(userp && *userp) {
141 result = Curl_create_sspi_identity(userp, passwdp, &krb5->identity);
146 krb5->p_identity = &krb5->identity;
150 krb5->p_identity = NULL;
153 krb5->credentials =
malloc(
sizeof(CredHandle));
154 if(!krb5->credentials)
157 memset(krb5->credentials, 0,
sizeof(CredHandle));
160 status = s_pSecFn->AcquireCredentialsHandle(NULL,
162 TEXT(SP_NAME_KERBEROS),
163 SECPKG_CRED_OUTBOUND, NULL,
164 krb5->p_identity, NULL, NULL,
165 krb5->credentials, &expiry);
166 if(status != SEC_E_OK)
170 krb5->context =
malloc(
sizeof(CtxtHandle));
174 memset(krb5->context, 0,
sizeof(CtxtHandle));
177 if(chlg64 && *chlg64) {
187 infof(data,
"GSSAPI handshake failure (empty challenge message)\n");
193 chlg_desc.ulVersion = SECBUFFER_VERSION;
194 chlg_desc.cBuffers = 1;
195 chlg_desc.pBuffers = &chlg_buf;
196 chlg_buf.BufferType = SECBUFFER_TOKEN;
197 chlg_buf.pvBuffer = chlg;
202 resp_desc.ulVersion = SECBUFFER_VERSION;
203 resp_desc.cBuffers = 1;
204 resp_desc.pBuffers = &resp_buf;
205 resp_buf.BufferType = SECBUFFER_TOKEN;
206 resp_buf.pvBuffer = krb5->output_token;
210 status = s_pSecFn->InitializeSecurityContext(krb5->credentials,
211 chlg ? krb5->context : NULL,
214 ISC_REQ_MUTUAL_AUTH : 0),
215 0, SECURITY_NATIVE_DREP,
216 chlg ? &chlg_desc : NULL, 0,
224 if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
228 if(memcmp(&context, krb5->context,
sizeof(context))) {
229 s_pSecFn->DeleteSecurityContext(krb5->context);
231 memcpy(krb5->context, &context,
sizeof(context));
234 if(resp_buf.cbBuffer) {
237 resp_buf.cbBuffer, outptr, outlen);
239 else if(mutual_auth) {
267 struct kerberos5data *krb5,
274 size_t messagelen = 0;
275 size_t appdatalen = 0;
276 unsigned char *chlg = NULL;
277 unsigned char *trailer = NULL;
278 unsigned char *message = NULL;
279 unsigned char *padding = NULL;
280 unsigned char *appdata = NULL;
281 SecBuffer input_buf[2];
282 SecBuffer wrap_buf[3];
283 SecBufferDesc input_desc;
284 SecBufferDesc wrap_desc;
286 unsigned long outdata = 0;
287 unsigned long qop = 0;
288 unsigned long sec_layer = 0;
289 unsigned long max_size = 0;
290 SecPkgContext_Sizes sizes;
291 SecPkgCredentials_Names names;
292 SECURITY_STATUS status;
296 if(strlen(chlg64) && *chlg64 !=
'=') {
304 infof(data,
"GSSAPI handshake failure (empty security message)\n");
310 status = s_pSecFn->QueryContextAttributes(krb5->context,
313 if(status != SEC_E_OK) {
320 status = s_pSecFn->QueryCredentialsAttributes(krb5->credentials,
321 SECPKG_CRED_ATTR_NAMES,
323 if(status != SEC_E_OK) {
330 input_desc.ulVersion = SECBUFFER_VERSION;
331 input_desc.cBuffers = 2;
332 input_desc.pBuffers = input_buf;
333 input_buf[0].BufferType = SECBUFFER_STREAM;
334 input_buf[0].pvBuffer = chlg;
336 input_buf[1].BufferType = SECBUFFER_DATA;
337 input_buf[1].pvBuffer = NULL;
338 input_buf[1].cbBuffer = 0;
341 status = s_pSecFn->DecryptMessage(krb5->context, &input_desc, 0, &qop);
342 if(status != SEC_E_OK) {
343 infof(data,
"GSSAPI handshake failure (empty security message)\n");
351 if(input_buf[1].cbBuffer != 4) {
352 infof(data,
"GSSAPI handshake failure (invalid security data)\n");
360 memcpy(&indata, input_buf[1].pvBuffer, 4);
361 s_pSecFn->FreeContextBuffer(input_buf[1].pvBuffer);
365 sec_layer = indata & 0x000000FF;
366 if(!(sec_layer & KERB_WRAP_NO_ENCRYPT)) {
367 infof(data,
"GSSAPI handshake failure (invalid security layer)\n");
373 max_size = ntohl(indata & 0xFFFFFF00);
382 trailer =
malloc(sizes.cbSecurityTrailer);
387 user_name = Curl_convert_tchar_to_UTF8(names.sUserName);
395 messagelen =
sizeof(outdata) + strlen(user_name) + 1;
396 message =
malloc(messagelen);
399 Curl_unicodefree(user_name);
409 outdata = htonl(max_size) | sec_layer;
410 memcpy(message, &outdata,
sizeof(outdata));
411 strcpy((
char *) message +
sizeof(outdata), user_name);
412 Curl_unicodefree(user_name);
415 padding =
malloc(sizes.cbBlockSize);
424 wrap_desc.ulVersion = SECBUFFER_VERSION;
425 wrap_desc.cBuffers = 3;
426 wrap_desc.pBuffers = wrap_buf;
427 wrap_buf[0].BufferType = SECBUFFER_TOKEN;
428 wrap_buf[0].pvBuffer = trailer;
429 wrap_buf[0].cbBuffer = sizes.cbSecurityTrailer;
430 wrap_buf[1].BufferType = SECBUFFER_DATA;
431 wrap_buf[1].pvBuffer = message;
433 wrap_buf[2].BufferType = SECBUFFER_PADDING;
434 wrap_buf[2].pvBuffer = padding;
435 wrap_buf[2].cbBuffer = sizes.cbBlockSize;
438 status = s_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT,
440 if(status != SEC_E_OK) {
449 appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer +
450 wrap_buf[2].cbBuffer;
451 appdata =
malloc(appdatalen);
461 memcpy(appdata, wrap_buf[0].pvBuffer, wrap_buf[0].cbBuffer);
462 offset += wrap_buf[0].cbBuffer;
463 memcpy(appdata + offset, wrap_buf[1].pvBuffer, wrap_buf[1].cbBuffer);
464 offset += wrap_buf[1].cbBuffer;
465 memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer);
490 void Curl_auth_gssapi_cleanup(
struct kerberos5data *krb5)
494 s_pSecFn->DeleteSecurityContext(krb5->context);
496 krb5->context = NULL;
500 if(krb5->credentials) {
501 s_pSecFn->FreeCredentialsHandle(krb5->credentials);
502 free(krb5->credentials);
503 krb5->credentials = NULL;
507 Curl_sspi_free_identity(krb5->p_identity);
508 krb5->p_identity = NULL;
CURLcode Curl_base64_decode(const char *src, unsigned char **outptr, size_t *outlen)
CURLcode Curl_base64_encode(struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
UNITTEST_START int result
memcpy(filename, filename1, strlen(filename1))
unsigned long curlx_uztoul(size_t uznum)
static struct input indata[NUM_HANDLES]
#define Curl_safefree(ptr)
char * Curl_auth_build_spn(const char *service, const char *host, const char *realm)