Annotation of embedaddon/curl/lib/socks_sspi.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9: * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
10: *
11: * This software is licensed as described in the file COPYING, which
12: * you should have received as part of this distribution. The terms
13: * are also available at https://curl.haxx.se/docs/copyright.html.
14: *
15: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16: * copies of the Software, and permit persons to whom the Software is
17: * furnished to do so, under the terms of the COPYING file.
18: *
19: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20: * KIND, either express or implied.
21: *
22: ***************************************************************************/
23:
24: #include "curl_setup.h"
25:
26: #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY)
27:
28: #include "urldata.h"
29: #include "sendf.h"
30: #include "connect.h"
31: #include "strerror.h"
32: #include "timeval.h"
33: #include "socks.h"
34: #include "curl_sspi.h"
35: #include "curl_multibyte.h"
36: #include "warnless.h"
37: #include "strdup.h"
38: /* The last 3 #include files should be in this order */
39: #include "curl_printf.h"
40: #include "curl_memory.h"
41: #include "memdebug.h"
42:
43: /*
44: * Helper sspi error functions.
45: */
46: static int check_sspi_err(struct connectdata *conn,
47: SECURITY_STATUS status,
48: const char *function)
49: {
50: if(status != SEC_E_OK &&
51: status != SEC_I_COMPLETE_AND_CONTINUE &&
52: status != SEC_I_COMPLETE_NEEDED &&
53: status != SEC_I_CONTINUE_NEEDED) {
54: char buffer[STRERROR_LEN];
55: failf(conn->data, "SSPI error: %s failed: %s", function,
56: Curl_sspi_strerror(status, buffer, sizeof(buffer)));
57: return 1;
58: }
59: return 0;
60: }
61:
62: /* This is the SSPI-using version of this function */
63: CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
64: struct connectdata *conn)
65: {
66: struct Curl_easy *data = conn->data;
67: curl_socket_t sock = conn->sock[sockindex];
68: CURLcode code;
69: ssize_t actualread;
70: ssize_t written;
71: int result;
72: /* Needs GSS-API authentication */
73: SECURITY_STATUS status;
74: unsigned long sspi_ret_flags = 0;
75: unsigned char gss_enc;
76: SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
77: SecBufferDesc input_desc, output_desc, wrap_desc;
78: SecPkgContext_Sizes sspi_sizes;
79: CredHandle cred_handle;
80: CtxtHandle sspi_context;
81: PCtxtHandle context_handle = NULL;
82: SecPkgCredentials_Names names;
83: TimeStamp expiry;
84: char *service_name = NULL;
85: unsigned short us_length;
86: unsigned long qop;
87: unsigned char socksreq[4]; /* room for GSS-API exchange header only */
88: const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
89: data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd";
90: const size_t service_length = strlen(service);
91:
92: /* GSS-API request looks like
93: * +----+------+-----+----------------+
94: * |VER | MTYP | LEN | TOKEN |
95: * +----+------+----------------------+
96: * | 1 | 1 | 2 | up to 2^16 - 1 |
97: * +----+------+-----+----------------+
98: */
99:
100: /* prepare service name */
101: if(strchr(service, '/')) {
102: service_name = strdup(service);
103: if(!service_name)
104: return CURLE_OUT_OF_MEMORY;
105: }
106: else {
107: service_name = malloc(service_length +
108: strlen(conn->socks_proxy.host.name) + 2);
109: if(!service_name)
110: return CURLE_OUT_OF_MEMORY;
111: msnprintf(service_name, service_length +
112: strlen(conn->socks_proxy.host.name) + 2, "%s/%s",
113: service, conn->socks_proxy.host.name);
114: }
115:
116: input_desc.cBuffers = 1;
117: input_desc.pBuffers = &sspi_recv_token;
118: input_desc.ulVersion = SECBUFFER_VERSION;
119:
120: sspi_recv_token.BufferType = SECBUFFER_TOKEN;
121: sspi_recv_token.cbBuffer = 0;
122: sspi_recv_token.pvBuffer = NULL;
123:
124: output_desc.cBuffers = 1;
125: output_desc.pBuffers = &sspi_send_token;
126: output_desc.ulVersion = SECBUFFER_VERSION;
127:
128: sspi_send_token.BufferType = SECBUFFER_TOKEN;
129: sspi_send_token.cbBuffer = 0;
130: sspi_send_token.pvBuffer = NULL;
131:
132: wrap_desc.cBuffers = 3;
133: wrap_desc.pBuffers = sspi_w_token;
134: wrap_desc.ulVersion = SECBUFFER_VERSION;
135:
136: cred_handle.dwLower = 0;
137: cred_handle.dwUpper = 0;
138:
139: status = s_pSecFn->AcquireCredentialsHandle(NULL,
140: (TCHAR *) TEXT("Kerberos"),
141: SECPKG_CRED_OUTBOUND,
142: NULL,
143: NULL,
144: NULL,
145: NULL,
146: &cred_handle,
147: &expiry);
148:
149: if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
150: failf(data, "Failed to acquire credentials.");
151: free(service_name);
152: s_pSecFn->FreeCredentialsHandle(&cred_handle);
153: return CURLE_COULDNT_CONNECT;
154: }
155:
156: (void)curlx_nonblock(sock, FALSE);
157:
158: /* As long as we need to keep sending some context info, and there's no */
159: /* errors, keep sending it... */
160: for(;;) {
161: TCHAR *sname;
162:
163: sname = Curl_convert_UTF8_to_tchar(service_name);
164: if(!sname)
165: return CURLE_OUT_OF_MEMORY;
166:
167: status = s_pSecFn->InitializeSecurityContext(&cred_handle,
168: context_handle,
169: sname,
170: ISC_REQ_MUTUAL_AUTH |
171: ISC_REQ_ALLOCATE_MEMORY |
172: ISC_REQ_CONFIDENTIALITY |
173: ISC_REQ_REPLAY_DETECT,
174: 0,
175: SECURITY_NATIVE_DREP,
176: &input_desc,
177: 0,
178: &sspi_context,
179: &output_desc,
180: &sspi_ret_flags,
181: &expiry);
182:
183: Curl_unicodefree(sname);
184:
185: if(sspi_recv_token.pvBuffer) {
186: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
187: sspi_recv_token.pvBuffer = NULL;
188: sspi_recv_token.cbBuffer = 0;
189: }
190:
191: if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
192: free(service_name);
193: s_pSecFn->FreeCredentialsHandle(&cred_handle);
194: s_pSecFn->DeleteSecurityContext(&sspi_context);
195: if(sspi_recv_token.pvBuffer)
196: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
197: failf(data, "Failed to initialise security context.");
198: return CURLE_COULDNT_CONNECT;
199: }
200:
201: if(sspi_send_token.cbBuffer != 0) {
202: socksreq[0] = 1; /* GSS-API subnegotiation version */
203: socksreq[1] = 1; /* authentication message type */
204: us_length = htons((short)sspi_send_token.cbBuffer);
205: memcpy(socksreq + 2, &us_length, sizeof(short));
206:
207: code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
208: if(code || (4 != written)) {
209: failf(data, "Failed to send SSPI authentication request.");
210: free(service_name);
211: if(sspi_send_token.pvBuffer)
212: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
213: if(sspi_recv_token.pvBuffer)
214: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
215: s_pSecFn->FreeCredentialsHandle(&cred_handle);
216: s_pSecFn->DeleteSecurityContext(&sspi_context);
217: return CURLE_COULDNT_CONNECT;
218: }
219:
220: code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
221: sspi_send_token.cbBuffer, &written);
222: if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
223: failf(data, "Failed to send SSPI authentication token.");
224: free(service_name);
225: if(sspi_send_token.pvBuffer)
226: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
227: if(sspi_recv_token.pvBuffer)
228: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
229: s_pSecFn->FreeCredentialsHandle(&cred_handle);
230: s_pSecFn->DeleteSecurityContext(&sspi_context);
231: return CURLE_COULDNT_CONNECT;
232: }
233:
234: }
235:
236: if(sspi_send_token.pvBuffer) {
237: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
238: sspi_send_token.pvBuffer = NULL;
239: }
240: sspi_send_token.cbBuffer = 0;
241:
242: if(sspi_recv_token.pvBuffer) {
243: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
244: sspi_recv_token.pvBuffer = NULL;
245: }
246: sspi_recv_token.cbBuffer = 0;
247:
248: if(status != SEC_I_CONTINUE_NEEDED)
249: break;
250:
251: /* analyse response */
252:
253: /* GSS-API response looks like
254: * +----+------+-----+----------------+
255: * |VER | MTYP | LEN | TOKEN |
256: * +----+------+----------------------+
257: * | 1 | 1 | 2 | up to 2^16 - 1 |
258: * +----+------+-----+----------------+
259: */
260:
261: result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
262: if(result || (actualread != 4)) {
263: failf(data, "Failed to receive SSPI authentication response.");
264: free(service_name);
265: s_pSecFn->FreeCredentialsHandle(&cred_handle);
266: s_pSecFn->DeleteSecurityContext(&sspi_context);
267: return CURLE_COULDNT_CONNECT;
268: }
269:
270: /* ignore the first (VER) byte */
271: if(socksreq[1] == 255) { /* status / message type */
272: failf(data, "User was rejected by the SOCKS5 server (%u %u).",
273: (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
274: free(service_name);
275: s_pSecFn->FreeCredentialsHandle(&cred_handle);
276: s_pSecFn->DeleteSecurityContext(&sspi_context);
277: return CURLE_COULDNT_CONNECT;
278: }
279:
280: if(socksreq[1] != 1) { /* status / messgae type */
281: failf(data, "Invalid SSPI authentication response type (%u %u).",
282: (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
283: free(service_name);
284: s_pSecFn->FreeCredentialsHandle(&cred_handle);
285: s_pSecFn->DeleteSecurityContext(&sspi_context);
286: return CURLE_COULDNT_CONNECT;
287: }
288:
289: memcpy(&us_length, socksreq + 2, sizeof(short));
290: us_length = ntohs(us_length);
291:
292: sspi_recv_token.cbBuffer = us_length;
293: sspi_recv_token.pvBuffer = malloc(us_length);
294:
295: if(!sspi_recv_token.pvBuffer) {
296: free(service_name);
297: s_pSecFn->FreeCredentialsHandle(&cred_handle);
298: s_pSecFn->DeleteSecurityContext(&sspi_context);
299: return CURLE_OUT_OF_MEMORY;
300: }
301: result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
302: sspi_recv_token.cbBuffer, &actualread);
303:
304: if(result || (actualread != us_length)) {
305: failf(data, "Failed to receive SSPI authentication token.");
306: free(service_name);
307: if(sspi_recv_token.pvBuffer)
308: s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
309: s_pSecFn->FreeCredentialsHandle(&cred_handle);
310: s_pSecFn->DeleteSecurityContext(&sspi_context);
311: return CURLE_COULDNT_CONNECT;
312: }
313:
314: context_handle = &sspi_context;
315: }
316:
317: free(service_name);
318:
319: /* Everything is good so far, user was authenticated! */
320: status = s_pSecFn->QueryCredentialsAttributes(&cred_handle,
321: SECPKG_CRED_ATTR_NAMES,
322: &names);
323: s_pSecFn->FreeCredentialsHandle(&cred_handle);
324: if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
325: s_pSecFn->DeleteSecurityContext(&sspi_context);
326: s_pSecFn->FreeContextBuffer(names.sUserName);
327: failf(data, "Failed to determine user name.");
328: return CURLE_COULDNT_CONNECT;
329: }
330: infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",
331: names.sUserName);
332: s_pSecFn->FreeContextBuffer(names.sUserName);
333:
334: /* Do encryption */
335: socksreq[0] = 1; /* GSS-API subnegotiation version */
336: socksreq[1] = 2; /* encryption message type */
337:
338: gss_enc = 0; /* no data protection */
339: /* do confidentiality protection if supported */
340: if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
341: gss_enc = 2;
342: /* else do integrity protection */
343: else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
344: gss_enc = 1;
345:
346: infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
347: (gss_enc == 0)?"no":((gss_enc == 1)?"integrity":"confidentiality") );
348: /* force to no data protection, avoid encryption/decryption for now */
349: gss_enc = 0;
350: /*
351: * Sending the encryption type in clear seems wrong. It should be
352: * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
353: * The NEC reference implementations on which this is based is
354: * therefore at fault
355: *
356: * +------+------+------+.......................+
357: * + ver | mtyp | len | token |
358: * +------+------+------+.......................+
359: * + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
360: * +------+------+------+.......................+
361: *
362: * Where:
363: *
364: * - "ver" is the protocol version number, here 1 to represent the
365: * first version of the SOCKS/GSS-API protocol
366: *
367: * - "mtyp" is the message type, here 2 to represent a protection
368: * -level negotiation message
369: *
370: * - "len" is the length of the "token" field in octets
371: *
372: * - "token" is the GSS-API encapsulated protection level
373: *
374: * The token is produced by encapsulating an octet containing the
375: * required protection level using gss_seal()/gss_wrap() with conf_req
376: * set to FALSE. The token is verified using gss_unseal()/
377: * gss_unwrap().
378: *
379: */
380:
381: if(data->set.socks5_gssapi_nec) {
382: us_length = htons((short)1);
383: memcpy(socksreq + 2, &us_length, sizeof(short));
384: }
385: else {
386: status = s_pSecFn->QueryContextAttributes(&sspi_context,
387: SECPKG_ATTR_SIZES,
388: &sspi_sizes);
389: if(check_sspi_err(conn, status, "QueryContextAttributes")) {
390: s_pSecFn->DeleteSecurityContext(&sspi_context);
391: failf(data, "Failed to query security context attributes.");
392: return CURLE_COULDNT_CONNECT;
393: }
394:
395: sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
396: sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
397: sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
398:
399: if(!sspi_w_token[0].pvBuffer) {
400: s_pSecFn->DeleteSecurityContext(&sspi_context);
401: return CURLE_OUT_OF_MEMORY;
402: }
403:
404: sspi_w_token[1].cbBuffer = 1;
405: sspi_w_token[1].pvBuffer = malloc(1);
406: if(!sspi_w_token[1].pvBuffer) {
407: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
408: s_pSecFn->DeleteSecurityContext(&sspi_context);
409: return CURLE_OUT_OF_MEMORY;
410: }
411:
412: memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
413: sspi_w_token[2].BufferType = SECBUFFER_PADDING;
414: sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
415: sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
416: if(!sspi_w_token[2].pvBuffer) {
417: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
418: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
419: s_pSecFn->DeleteSecurityContext(&sspi_context);
420: return CURLE_OUT_OF_MEMORY;
421: }
422: status = s_pSecFn->EncryptMessage(&sspi_context,
423: KERB_WRAP_NO_ENCRYPT,
424: &wrap_desc,
425: 0);
426: if(check_sspi_err(conn, status, "EncryptMessage")) {
427: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
428: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
429: s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
430: s_pSecFn->DeleteSecurityContext(&sspi_context);
431: failf(data, "Failed to query security context attributes.");
432: return CURLE_COULDNT_CONNECT;
433: }
434: sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
435: + sspi_w_token[1].cbBuffer
436: + sspi_w_token[2].cbBuffer;
437: sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
438: if(!sspi_send_token.pvBuffer) {
439: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
440: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
441: s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
442: s_pSecFn->DeleteSecurityContext(&sspi_context);
443: return CURLE_OUT_OF_MEMORY;
444: }
445:
446: memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
447: sspi_w_token[0].cbBuffer);
448: memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
449: sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
450: memcpy((PUCHAR) sspi_send_token.pvBuffer
451: + sspi_w_token[0].cbBuffer
452: + sspi_w_token[1].cbBuffer,
453: sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
454:
455: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
456: sspi_w_token[0].pvBuffer = NULL;
457: sspi_w_token[0].cbBuffer = 0;
458: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
459: sspi_w_token[1].pvBuffer = NULL;
460: sspi_w_token[1].cbBuffer = 0;
461: s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
462: sspi_w_token[2].pvBuffer = NULL;
463: sspi_w_token[2].cbBuffer = 0;
464:
465: us_length = htons((short)sspi_send_token.cbBuffer);
466: memcpy(socksreq + 2, &us_length, sizeof(short));
467: }
468:
469: code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
470: if(code || (4 != written)) {
471: failf(data, "Failed to send SSPI encryption request.");
472: if(sspi_send_token.pvBuffer)
473: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
474: s_pSecFn->DeleteSecurityContext(&sspi_context);
475: return CURLE_COULDNT_CONNECT;
476: }
477:
478: if(data->set.socks5_gssapi_nec) {
479: memcpy(socksreq, &gss_enc, 1);
480: code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
481: if(code || (1 != written)) {
482: failf(data, "Failed to send SSPI encryption type.");
483: s_pSecFn->DeleteSecurityContext(&sspi_context);
484: return CURLE_COULDNT_CONNECT;
485: }
486: }
487: else {
488: code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
489: sspi_send_token.cbBuffer, &written);
490: if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
491: failf(data, "Failed to send SSPI encryption type.");
492: if(sspi_send_token.pvBuffer)
493: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
494: s_pSecFn->DeleteSecurityContext(&sspi_context);
495: return CURLE_COULDNT_CONNECT;
496: }
497: if(sspi_send_token.pvBuffer)
498: s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
499: }
500:
501: result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
502: if(result || (actualread != 4)) {
503: failf(data, "Failed to receive SSPI encryption response.");
504: s_pSecFn->DeleteSecurityContext(&sspi_context);
505: return CURLE_COULDNT_CONNECT;
506: }
507:
508: /* ignore the first (VER) byte */
509: if(socksreq[1] == 255) { /* status / message type */
510: failf(data, "User was rejected by the SOCKS5 server (%u %u).",
511: (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
512: s_pSecFn->DeleteSecurityContext(&sspi_context);
513: return CURLE_COULDNT_CONNECT;
514: }
515:
516: if(socksreq[1] != 2) { /* status / message type */
517: failf(data, "Invalid SSPI encryption response type (%u %u).",
518: (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
519: s_pSecFn->DeleteSecurityContext(&sspi_context);
520: return CURLE_COULDNT_CONNECT;
521: }
522:
523: memcpy(&us_length, socksreq + 2, sizeof(short));
524: us_length = ntohs(us_length);
525:
526: sspi_w_token[0].cbBuffer = us_length;
527: sspi_w_token[0].pvBuffer = malloc(us_length);
528: if(!sspi_w_token[0].pvBuffer) {
529: s_pSecFn->DeleteSecurityContext(&sspi_context);
530: return CURLE_OUT_OF_MEMORY;
531: }
532:
533: result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
534: sspi_w_token[0].cbBuffer, &actualread);
535:
536: if(result || (actualread != us_length)) {
537: failf(data, "Failed to receive SSPI encryption type.");
538: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
539: s_pSecFn->DeleteSecurityContext(&sspi_context);
540: return CURLE_COULDNT_CONNECT;
541: }
542:
543:
544: if(!data->set.socks5_gssapi_nec) {
545: wrap_desc.cBuffers = 2;
546: sspi_w_token[0].BufferType = SECBUFFER_STREAM;
547: sspi_w_token[1].BufferType = SECBUFFER_DATA;
548: sspi_w_token[1].cbBuffer = 0;
549: sspi_w_token[1].pvBuffer = NULL;
550:
551: status = s_pSecFn->DecryptMessage(&sspi_context,
552: &wrap_desc,
553: 0,
554: &qop);
555:
556: if(check_sspi_err(conn, status, "DecryptMessage")) {
557: if(sspi_w_token[0].pvBuffer)
558: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
559: if(sspi_w_token[1].pvBuffer)
560: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
561: s_pSecFn->DeleteSecurityContext(&sspi_context);
562: failf(data, "Failed to query security context attributes.");
563: return CURLE_COULDNT_CONNECT;
564: }
565:
566: if(sspi_w_token[1].cbBuffer != 1) {
567: failf(data, "Invalid SSPI encryption response length (%lu).",
568: (unsigned long)sspi_w_token[1].cbBuffer);
569: if(sspi_w_token[0].pvBuffer)
570: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
571: if(sspi_w_token[1].pvBuffer)
572: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
573: s_pSecFn->DeleteSecurityContext(&sspi_context);
574: return CURLE_COULDNT_CONNECT;
575: }
576:
577: memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
578: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
579: s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
580: }
581: else {
582: if(sspi_w_token[0].cbBuffer != 1) {
583: failf(data, "Invalid SSPI encryption response length (%lu).",
584: (unsigned long)sspi_w_token[0].cbBuffer);
585: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
586: s_pSecFn->DeleteSecurityContext(&sspi_context);
587: return CURLE_COULDNT_CONNECT;
588: }
589: memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
590: s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
591: }
592: (void)curlx_nonblock(sock, TRUE);
593:
594: infof(data, "SOCKS5 access with%s protection granted.\n",
595: (socksreq[0] == 0)?"out GSS-API data":
596: ((socksreq[0] == 1)?" GSS-API integrity":" GSS-API confidentiality"));
597:
598: /* For later use if encryption is required
599: conn->socks5_gssapi_enctype = socksreq[0];
600: if(socksreq[0] != 0)
601: conn->socks5_sspi_context = sspi_context;
602: else {
603: s_pSecFn->DeleteSecurityContext(&sspi_context);
604: conn->socks5_sspi_context = sspi_context;
605: }
606: */
607: return CURLE_OK;
608: }
609: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>