1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 2009, Markus Moeller, <markus_moeller@compuserve.com>
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
26 #ifdef USE_WINDOWS_SSPI
39 #include "curl_sspi.h"
41 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
42 #include <curl/mprintf.h>
44 #include "curl_memory.h"
45 /* The last #include file should be: */
49 * Definitions required from ntsecapi.h are directly provided below this point
50 * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h
52 #define KERB_WRAP_NO_ENCRYPT 0x80000001
55 * Helper sspi error functions.
57 static int check_sspi_err(struct SessionHandle *data,
58 SECURITY_STATUS major_status,
59 SECURITY_STATUS minor_status,
65 if(major_status != SEC_E_OK &&
66 major_status != SEC_I_COMPLETE_AND_CONTINUE &&
67 major_status != SEC_I_COMPLETE_NEEDED &&
68 major_status != SEC_I_CONTINUE_NEEDED) {
69 failf(data, "SSPI error: %s failed: %d\n", function, major_status);
70 switch (major_status) {
71 case SEC_I_COMPLETE_AND_CONTINUE:
72 txt="SEC_I_COMPLETE_AND_CONTINUE";
74 case SEC_I_COMPLETE_NEEDED:
75 txt="SEC_I_COMPLETE_NEEDED";
77 case SEC_I_CONTINUE_NEEDED:
78 txt="SEC_I_CONTINUE_NEEDED";
80 case SEC_I_CONTEXT_EXPIRED:
81 txt="SEC_I_CONTEXT_EXPIRED";
83 case SEC_I_INCOMPLETE_CREDENTIALS:
84 txt="SEC_I_INCOMPLETE_CREDENTIALS";
86 case SEC_I_RENEGOTIATE:
87 txt="SEC_I_RENEGOTIATE";
89 case SEC_E_BUFFER_TOO_SMALL:
90 txt="SEC_E_BUFFER_TOO_SMALL";
92 case SEC_E_CONTEXT_EXPIRED:
93 txt="SEC_E_CONTEXT_EXPIRED";
95 case SEC_E_CRYPTO_SYSTEM_INVALID:
96 txt="SEC_E_CRYPTO_SYSTEM_INVALID";
98 case SEC_E_INCOMPLETE_MESSAGE:
99 txt="SEC_E_INCOMPLETE_MESSAGE";
101 case SEC_E_INSUFFICIENT_MEMORY:
102 txt="SEC_E_INSUFFICIENT_MEMORY";
104 case SEC_E_INTERNAL_ERROR:
105 txt="SEC_E_INTERNAL_ERROR";
107 case SEC_E_INVALID_HANDLE:
108 txt="SEC_E_INVALID_HANDLE";
110 case SEC_E_INVALID_TOKEN:
111 txt="SEC_E_INVALID_TOKEN";
113 case SEC_E_LOGON_DENIED:
114 txt="SEC_E_LOGON_DENIED";
116 case SEC_E_MESSAGE_ALTERED:
117 txt="SEC_E_MESSAGE_ALTERED";
119 case SEC_E_NO_AUTHENTICATING_AUTHORITY:
120 txt="SEC_E_NO_AUTHENTICATING_AUTHORITY";
122 case SEC_E_NO_CREDENTIALS:
123 txt="SEC_E_NO_CREDENTIALS";
125 case SEC_E_NOT_OWNER:
126 txt="SEC_E_NOT_OWNER";
128 case SEC_E_OUT_OF_SEQUENCE:
129 txt="SEC_E_OUT_OF_SEQUENCE";
131 case SEC_E_QOP_NOT_SUPPORTED:
132 txt="SEC_E_QOP_NOT_SUPPORTED";
134 case SEC_E_SECPKG_NOT_FOUND:
135 txt="SEC_E_SECPKG_NOT_FOUND";
137 case SEC_E_TARGET_UNKNOWN:
138 txt="SEC_E_TARGET_UNKNOWN";
140 case SEC_E_UNKNOWN_CREDENTIALS:
141 txt="SEC_E_UNKNOWN_CREDENTIALS";
143 case SEC_E_UNSUPPORTED_FUNCTION:
144 txt="SEC_E_UNSUPPORTED_FUNCTION";
146 case SEC_E_WRONG_PRINCIPAL:
147 txt="SEC_E_WRONG_PRINCIPAL";
153 failf(data, "SSPI error: %s failed: %s\n", function, txt);
159 /* This is the SSPI-using version of this function */
160 CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
161 struct connectdata *conn)
163 struct SessionHandle *data = conn->data;
164 curl_socket_t sock = conn->sock[sockindex];
170 /* Needs GSSAPI authentication */
171 SECURITY_STATUS sspi_major_status, sspi_minor_status=0;
172 unsigned long sspi_ret_flags=0;
174 SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
175 SecBufferDesc input_desc, output_desc, wrap_desc;
176 SecPkgContext_Sizes sspi_sizes;
177 CredHandle cred_handle;
178 CtxtHandle sspi_context;
179 PCtxtHandle context_handle = NULL;
180 SecPkgCredentials_Names names;
182 char *service_name=NULL;
185 unsigned char socksreq[4]; /* room for gssapi exchange header only */
186 char *service = data->set.str[STRING_SOCKS5_GSSAPI_SERVICE];
189 timeout = Curl_timeleft(conn, NULL, TRUE);
191 /* GSSAPI request looks like
192 * +----+------+-----+----------------+
193 * |VER | MTYP | LEN | TOKEN |
194 * +----+------+----------------------+
195 * | 1 | 1 | 2 | up to 2^16 - 1 |
196 * +----+------+-----+----------------+
199 /* prepare service name */
200 if (strchr(service, '/')) {
201 service_name = malloc(strlen(service));
203 return CURLE_OUT_OF_MEMORY;
204 memcpy(service_name, service, strlen(service));
207 service_name = malloc(strlen(service) + strlen(conn->proxy.name) + 2);
209 return CURLE_OUT_OF_MEMORY;
210 snprintf(service_name,strlen(service) +strlen(conn->proxy.name)+2,"%s/%s",
211 service,conn->proxy.name);
214 input_desc.cBuffers = 1;
215 input_desc.pBuffers = &sspi_recv_token;
216 input_desc.ulVersion = SECBUFFER_VERSION;
218 sspi_recv_token.BufferType = SECBUFFER_TOKEN;
219 sspi_recv_token.cbBuffer = 0;
220 sspi_recv_token.pvBuffer = NULL;
222 output_desc.cBuffers = 1;
223 output_desc.pBuffers = &sspi_send_token;
224 output_desc.ulVersion = SECBUFFER_VERSION;
226 sspi_send_token.BufferType = SECBUFFER_TOKEN;
227 sspi_send_token.cbBuffer = 0;
228 sspi_send_token.pvBuffer = NULL;
230 wrap_desc.cBuffers = 3;
231 wrap_desc.pBuffers = sspi_w_token;
232 wrap_desc.ulVersion = SECBUFFER_VERSION;
234 cred_handle.dwLower = 0;
235 cred_handle.dwUpper = 0;
237 sspi_major_status = s_pSecFn->AcquireCredentialsHandleA( NULL,
239 SECPKG_CRED_OUTBOUND,
247 if(check_sspi_err(data, sspi_major_status,sspi_minor_status,
248 "AcquireCredentialsHandleA") ) {
249 failf(data, "Failed to acquire credentials.");
252 s_pSecFn->FreeCredentialsHandle(&cred_handle);
253 return CURLE_COULDNT_CONNECT;
256 /* As long as we need to keep sending some context info, and there's no */
257 /* errors, keep sending it... */
260 sspi_major_status = s_pSecFn->InitializeSecurityContextA(
264 ISC_REQ_MUTUAL_AUTH |
265 ISC_REQ_ALLOCATE_MEMORY |
266 ISC_REQ_CONFIDENTIALITY |
267 ISC_REQ_REPLAY_DETECT,
269 SECURITY_NATIVE_DREP,
277 if(sspi_recv_token.pvBuffer) {
278 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
279 sspi_recv_token.pvBuffer = NULL;
280 sspi_recv_token.cbBuffer = 0;
283 if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
284 "InitializeSecurityContextA") ){
287 s_pSecFn->FreeCredentialsHandle(&cred_handle);
288 s_pSecFn->DeleteSecurityContext(&sspi_context);
289 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
290 failf(data, "Failed to initialise security context.");
291 return CURLE_COULDNT_CONNECT;
294 if(sspi_send_token.cbBuffer != 0) {
295 socksreq[0] = 1; /* gssapi subnegotiation version */
296 socksreq[1] = 1; /* authentication message type */
297 us_length = htons((short)sspi_send_token.cbBuffer);
298 memcpy(socksreq+2, &us_length, sizeof(short));
300 code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
301 if((code != CURLE_OK) || (4 != written)) {
302 failf(data, "Failed to send SSPI authentication request.");
305 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
306 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
307 s_pSecFn->FreeCredentialsHandle(&cred_handle);
308 s_pSecFn->DeleteSecurityContext(&sspi_context);
309 return CURLE_COULDNT_CONNECT;
312 code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
313 sspi_send_token.cbBuffer, &written);
314 if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
315 failf(data, "Failed to send SSPI authentication token.");
318 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
319 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
320 s_pSecFn->FreeCredentialsHandle(&cred_handle);
321 s_pSecFn->DeleteSecurityContext(&sspi_context);
322 return CURLE_COULDNT_CONNECT;
327 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
328 sspi_send_token.pvBuffer = NULL;
329 sspi_send_token.cbBuffer = 0;
330 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
331 sspi_recv_token.pvBuffer = NULL;
332 sspi_recv_token.cbBuffer = 0;
333 if(sspi_major_status != SEC_I_CONTINUE_NEEDED) break;
335 /* analyse response */
337 /* GSSAPI response looks like
338 * +----+------+-----+----------------+
339 * |VER | MTYP | LEN | TOKEN |
340 * +----+------+----------------------+
341 * | 1 | 1 | 2 | up to 2^16 - 1 |
342 * +----+------+-----+----------------+
345 result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
346 &actualread, timeout);
347 if(result != CURLE_OK || actualread != 4) {
348 failf(data, "Failed to receive SSPI authentication response.");
351 s_pSecFn->FreeCredentialsHandle(&cred_handle);
352 s_pSecFn->DeleteSecurityContext(&sspi_context);
353 return CURLE_COULDNT_CONNECT;
356 /* ignore the first (VER) byte */
357 if(socksreq[1] == 255) { /* status / message type */
358 failf(data, "User was rejected by the SOCKS5 server (%d %d).",
359 socksreq[0], socksreq[1]);
362 s_pSecFn->FreeCredentialsHandle(&cred_handle);
363 s_pSecFn->DeleteSecurityContext(&sspi_context);
364 return CURLE_COULDNT_CONNECT;
367 if(socksreq[1] != 1) { /* status / messgae type */
368 failf(data, "Invalid SSPI authentication response type (%d %d).",
369 socksreq[0], socksreq[1]);
372 s_pSecFn->FreeCredentialsHandle(&cred_handle);
373 s_pSecFn->DeleteSecurityContext(&sspi_context);
374 return CURLE_COULDNT_CONNECT;
377 memcpy(&us_length, socksreq+2, sizeof(short));
378 us_length = ntohs(us_length);
380 sspi_recv_token.cbBuffer = us_length;
381 sspi_recv_token.pvBuffer = malloc(us_length);
383 if(!sspi_recv_token.pvBuffer) {
386 s_pSecFn->FreeCredentialsHandle(&cred_handle);
387 s_pSecFn->DeleteSecurityContext(&sspi_context);
388 return CURLE_OUT_OF_MEMORY;
390 result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
391 sspi_recv_token.cbBuffer,
392 &actualread, timeout);
394 if(result != CURLE_OK || actualread != us_length) {
395 failf(data, "Failed to receive SSPI authentication token.");
398 s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
399 s_pSecFn->FreeCredentialsHandle(&cred_handle);
400 s_pSecFn->DeleteSecurityContext(&sspi_context);
401 return CURLE_COULDNT_CONNECT;
404 context_handle = &sspi_context;
410 /* Everything is good so far, user was authenticated! */
411 sspi_major_status = s_pSecFn->QueryCredentialsAttributes( &cred_handle,
412 SECPKG_CRED_ATTR_NAMES,
414 s_pSecFn->FreeCredentialsHandle(&cred_handle);
415 if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
416 "QueryCredentialAttributes") ){
417 s_pSecFn->DeleteSecurityContext(&sspi_context);
418 s_pSecFn->FreeContextBuffer(names.sUserName);
419 failf(data, "Failed to determine user name.");
420 return CURLE_COULDNT_CONNECT;
422 infof(data, "SOCKS5 server authencticated user %s with gssapi.\n",
424 s_pSecFn->FreeContextBuffer(names.sUserName);
427 socksreq[0] = 1; /* gssapi subnegotiation version */
428 socksreq[1] = 2; /* encryption message type */
430 gss_enc = 0; /* no data protection */
431 /* do confidentiality protection if supported */
432 if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
434 /* else do integrity protection */
435 else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
438 infof(data, "SOCKS5 server supports gssapi %s data protection.\n",
439 (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
440 /* force to no data protection, avoid encryption/decryption for now */
443 * Sending the encryption type in clear seems wrong. It should be
444 * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
445 * The NEC reference implementations on which this is based is
448 * +------+------+------+.......................+
449 * + ver | mtyp | len | token |
450 * +------+------+------+.......................+
451 * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
452 * +------+------+------+.......................+
456 * - "ver" is the protocol version number, here 1 to represent the
457 * first version of the SOCKS/GSS-API protocol
459 * - "mtyp" is the message type, here 2 to represent a protection
460 * -level negotiation message
462 * - "len" is the length of the "token" field in octets
464 * - "token" is the GSS-API encapsulated protection level
466 * The token is produced by encapsulating an octet containing the
467 * required protection level using gss_seal()/gss_wrap() with conf_req
468 * set to FALSE. The token is verified using gss_unseal()/
473 if(data->set.socks5_gssapi_nec) {
474 us_length = htons((short)1);
475 memcpy(socksreq+2, &us_length, sizeof(short));
478 sspi_major_status = s_pSecFn->QueryContextAttributesA( &sspi_context,
481 if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
482 "QueryContextAttributesA")) {
483 s_pSecFn->DeleteSecurityContext(&sspi_context);
484 failf(data, "Failed to query security context attributes.");
485 return CURLE_COULDNT_CONNECT;
488 sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
489 sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
490 sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
492 if(!sspi_w_token[0].pvBuffer) {
493 s_pSecFn->DeleteSecurityContext(&sspi_context);
494 return CURLE_OUT_OF_MEMORY;
497 sspi_w_token[1].cbBuffer = 1;
498 sspi_w_token[1].pvBuffer = malloc(1);
499 if(!sspi_w_token[1].pvBuffer){
500 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
501 s_pSecFn->DeleteSecurityContext(&sspi_context);
502 return CURLE_OUT_OF_MEMORY;
505 memcpy(sspi_w_token[1].pvBuffer,&gss_enc,1);
506 sspi_w_token[2].BufferType = SECBUFFER_PADDING;
507 sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
508 sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
509 if(!sspi_w_token[2].pvBuffer) {
510 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
511 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
512 s_pSecFn->DeleteSecurityContext(&sspi_context);
513 return CURLE_OUT_OF_MEMORY;
515 sspi_major_status = s_pSecFn->EncryptMessage( &sspi_context,
516 KERB_WRAP_NO_ENCRYPT,
519 if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
520 "EncryptMessage") ) {
521 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
522 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
523 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
524 s_pSecFn->DeleteSecurityContext(&sspi_context);
525 failf(data, "Failed to query security context attributes.");
526 return CURLE_COULDNT_CONNECT;
528 sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
529 + sspi_w_token[1].cbBuffer
530 + sspi_w_token[2].cbBuffer;
531 sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
532 if(!sspi_send_token.pvBuffer) {
533 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
534 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
535 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
536 s_pSecFn->DeleteSecurityContext(&sspi_context);
537 return CURLE_OUT_OF_MEMORY;
540 memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
541 sspi_w_token[0].cbBuffer);
542 memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
543 sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
544 memcpy((PUCHAR) sspi_send_token.pvBuffer
545 +sspi_w_token[0].cbBuffer
546 +sspi_w_token[1].cbBuffer,
547 sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
549 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
550 sspi_w_token[0].pvBuffer = NULL;
551 sspi_w_token[0].cbBuffer = 0;
552 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
553 sspi_w_token[1].pvBuffer = NULL;
554 sspi_w_token[1].cbBuffer = 0;
555 s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
556 sspi_w_token[2].pvBuffer = NULL;
557 sspi_w_token[2].cbBuffer = 0;
559 us_length = htons((short)sspi_send_token.cbBuffer);
560 memcpy(socksreq+2,&us_length,sizeof(short));
563 code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
564 if((code != CURLE_OK) || (4 != written)) {
565 failf(data, "Failed to send SSPI encryption request.");
566 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
567 s_pSecFn->DeleteSecurityContext(&sspi_context);
568 return CURLE_COULDNT_CONNECT;
571 if(data->set.socks5_gssapi_nec) {
572 memcpy(socksreq,&gss_enc,1);
573 code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
574 if((code != CURLE_OK) || (1 != written)) {
575 failf(data, "Failed to send SSPI encryption type.");
576 s_pSecFn->DeleteSecurityContext(&sspi_context);
577 return CURLE_COULDNT_CONNECT;
580 code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
581 sspi_send_token.cbBuffer, &written);
582 if((code != CURLE_OK) || (sspi_send_token.cbBuffer != (size_t)written)) {
583 failf(data, "Failed to send SSPI encryption type.");
584 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
585 s_pSecFn->DeleteSecurityContext(&sspi_context);
586 return CURLE_COULDNT_CONNECT;
588 s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
591 result=Curl_blockread_all(conn, sock, (char *)socksreq, 4,
592 &actualread, timeout);
593 if(result != CURLE_OK || actualread != 4) {
594 failf(data, "Failed to receive SSPI encryption response.");
595 s_pSecFn->DeleteSecurityContext(&sspi_context);
596 return CURLE_COULDNT_CONNECT;
599 /* ignore the first (VER) byte */
600 if(socksreq[1] == 255) { /* status / message type */
601 failf(data, "User was rejected by the SOCKS5 server (%d %d).",
602 socksreq[0], socksreq[1]);
603 s_pSecFn->DeleteSecurityContext(&sspi_context);
604 return CURLE_COULDNT_CONNECT;
607 if(socksreq[1] != 2) { /* status / message type */
608 failf(data, "Invalid SSPI encryption response type (%d %d).",
609 socksreq[0], socksreq[1]);
610 s_pSecFn->DeleteSecurityContext(&sspi_context);
611 return CURLE_COULDNT_CONNECT;
614 memcpy(&us_length, socksreq+2, sizeof(short));
615 us_length = ntohs(us_length);
617 sspi_w_token[0].cbBuffer = us_length;
618 sspi_w_token[0].pvBuffer = malloc(us_length);
619 if(!sspi_w_token[0].pvBuffer) {
620 s_pSecFn->DeleteSecurityContext(&sspi_context);
621 return CURLE_OUT_OF_MEMORY;
624 result=Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
625 sspi_w_token[0].cbBuffer,
626 &actualread, timeout);
628 if(result != CURLE_OK || actualread != us_length) {
629 failf(data, "Failed to receive SSPI encryption type.");
630 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
631 s_pSecFn->DeleteSecurityContext(&sspi_context);
632 return CURLE_COULDNT_CONNECT;
636 if(!data->set.socks5_gssapi_nec) {
637 wrap_desc.cBuffers = 2;
638 sspi_w_token[0].BufferType = SECBUFFER_STREAM;
639 sspi_w_token[1].BufferType = SECBUFFER_DATA;
640 sspi_w_token[1].cbBuffer = 0;
641 sspi_w_token[1].pvBuffer = NULL;
643 sspi_major_status = s_pSecFn->DecryptMessage( &sspi_context,
648 if(check_sspi_err(data,sspi_major_status,sspi_minor_status,
650 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
651 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
652 s_pSecFn->DeleteSecurityContext(&sspi_context);
653 failf(data, "Failed to query security context attributes.");
654 return CURLE_COULDNT_CONNECT;
657 if(sspi_w_token[1].cbBuffer != 1) {
658 failf(data, "Invalid SSPI encryption response length (%d).",
659 sspi_w_token[1].cbBuffer);
660 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
661 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
662 s_pSecFn->DeleteSecurityContext(&sspi_context);
663 return CURLE_COULDNT_CONNECT;
666 memcpy(socksreq,sspi_w_token[1].pvBuffer,sspi_w_token[1].cbBuffer);
667 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
668 s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
670 if(sspi_w_token[0].cbBuffer != 1) {
671 failf(data, "Invalid SSPI encryption response length (%d).",
672 sspi_w_token[0].cbBuffer);
673 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
674 s_pSecFn->DeleteSecurityContext(&sspi_context);
675 return CURLE_COULDNT_CONNECT;
677 memcpy(socksreq,sspi_w_token[0].pvBuffer,sspi_w_token[0].cbBuffer);
678 s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
681 infof(data, "SOCKS5 access with%s protection granted.\n",
682 (socksreq[0]==0)?"out gssapi data":
683 ((socksreq[0]==1)?" gssapi integrity":" gssapi confidentiality"));
685 /* For later use if encryption is required
686 conn->socks5_gssapi_enctype = socksreq[0];
687 if (socksreq[0] != 0)
688 conn->socks5_sspi_context = sspi_context;
690 s_pSecFn->DeleteSecurityContext(&sspi_context);
691 conn->socks5_sspi_context = sspi_context;