source: UsbWattMeter/trunk/curl-7.47.1/lib/socks_sspi.c@ 164

Last change on this file since 164 was 164, checked in by coas-nagasima, 6 years ago

TOPPERS/ECNLサンプルアプリ「USB充電器電力計」を追加

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