VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/socks_sspi.c@ 105284

Last change on this file since 105284 was 104083, checked in by vboxsync, 11 months ago

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette