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


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16