socks_sspi.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  * Copyright (C) 2009, 2011, Markus Moeller, <markus_moeller@compuserve.com>
00010  *
00011  * This software is licensed as described in the file COPYING, which
00012  * you should have received as part of this distribution. The terms
00013  * are also available at https://curl.haxx.se/docs/copyright.html.
00014  *
00015  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00016  * copies of the Software, and permit persons to whom the Software is
00017  * furnished to do so, under the terms of the COPYING file.
00018  *
00019  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00020  * KIND, either express or implied.
00021  *
00022  ***************************************************************************/
00023 
00024 #include "curl_setup.h"
00025 
00026 #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY)
00027 
00028 #include "urldata.h"
00029 #include "sendf.h"
00030 #include "connect.h"
00031 #include "strerror.h"
00032 #include "timeval.h"
00033 #include "socks.h"
00034 #include "curl_sspi.h"
00035 #include "curl_multibyte.h"
00036 #include "warnless.h"
00037 #include "strdup.h"
00038 /* The last 3 #include files should be in this order */
00039 #include "curl_printf.h"
00040 #include "curl_memory.h"
00041 #include "memdebug.h"
00042 
00043 /*
00044  * Helper sspi error functions.
00045  */
00046 static int check_sspi_err(struct connectdata *conn,
00047                           SECURITY_STATUS status,
00048                           const char *function)
00049 {
00050   if(status != SEC_E_OK &&
00051      status != SEC_I_COMPLETE_AND_CONTINUE &&
00052      status != SEC_I_COMPLETE_NEEDED &&
00053      status != SEC_I_CONTINUE_NEEDED) {
00054     failf(conn->data, "SSPI error: %s failed: %s", function,
00055           Curl_sspi_strerror(conn, status));
00056     return 1;
00057   }
00058   return 0;
00059 }
00060 
00061 /* This is the SSPI-using version of this function */
00062 CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
00063                                       struct connectdata *conn)
00064 {
00065   struct Curl_easy *data = conn->data;
00066   curl_socket_t sock = conn->sock[sockindex];
00067   CURLcode code;
00068   ssize_t actualread;
00069   ssize_t written;
00070   int result;
00071   /* Needs GSS-API authentication */
00072   SECURITY_STATUS status;
00073   unsigned long sspi_ret_flags = 0;
00074   unsigned char gss_enc;
00075   SecBuffer sspi_send_token, sspi_recv_token, sspi_w_token[3];
00076   SecBufferDesc input_desc, output_desc, wrap_desc;
00077   SecPkgContext_Sizes sspi_sizes;
00078   CredHandle cred_handle;
00079   CtxtHandle sspi_context;
00080   PCtxtHandle context_handle = NULL;
00081   SecPkgCredentials_Names names;
00082   TimeStamp expiry;
00083   char *service_name = NULL;
00084   unsigned short us_length;
00085   unsigned long qop;
00086   unsigned char socksreq[4]; /* room for GSS-API exchange header only */
00087   const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
00088                         data->set.str[STRING_PROXY_SERVICE_NAME]  : "rcmd";
00089   const size_t service_length = strlen(service);
00090 
00091   /*   GSS-API request looks like
00092    * +----+------+-----+----------------+
00093    * |VER | MTYP | LEN |     TOKEN      |
00094    * +----+------+----------------------+
00095    * | 1  |  1   |  2  | up to 2^16 - 1 |
00096    * +----+------+-----+----------------+
00097    */
00098 
00099   /* prepare service name */
00100   if(strchr(service, '/')) {
00101     service_name = strdup(service);
00102     if(!service_name)
00103       return CURLE_OUT_OF_MEMORY;
00104   }
00105   else {
00106     service_name = malloc(service_length +
00107                           strlen(conn->socks_proxy.host.name) + 2);
00108     if(!service_name)
00109       return CURLE_OUT_OF_MEMORY;
00110     snprintf(service_name, service_length +
00111              strlen(conn->socks_proxy.host.name)+2, "%s/%s",
00112              service, conn->socks_proxy.host.name);
00113   }
00114 
00115   input_desc.cBuffers = 1;
00116   input_desc.pBuffers = &sspi_recv_token;
00117   input_desc.ulVersion = SECBUFFER_VERSION;
00118 
00119   sspi_recv_token.BufferType = SECBUFFER_TOKEN;
00120   sspi_recv_token.cbBuffer = 0;
00121   sspi_recv_token.pvBuffer = NULL;
00122 
00123   output_desc.cBuffers = 1;
00124   output_desc.pBuffers = &sspi_send_token;
00125   output_desc.ulVersion = SECBUFFER_VERSION;
00126 
00127   sspi_send_token.BufferType = SECBUFFER_TOKEN;
00128   sspi_send_token.cbBuffer = 0;
00129   sspi_send_token.pvBuffer = NULL;
00130 
00131   wrap_desc.cBuffers = 3;
00132   wrap_desc.pBuffers = sspi_w_token;
00133   wrap_desc.ulVersion = SECBUFFER_VERSION;
00134 
00135   cred_handle.dwLower = 0;
00136   cred_handle.dwUpper = 0;
00137 
00138   status = s_pSecFn->AcquireCredentialsHandle(NULL,
00139                                               (TCHAR *) TEXT("Kerberos"),
00140                                               SECPKG_CRED_OUTBOUND,
00141                                               NULL,
00142                                               NULL,
00143                                               NULL,
00144                                               NULL,
00145                                               &cred_handle,
00146                                               &expiry);
00147 
00148   if(check_sspi_err(conn, status, "AcquireCredentialsHandle")) {
00149     failf(data, "Failed to acquire credentials.");
00150     free(service_name);
00151     s_pSecFn->FreeCredentialsHandle(&cred_handle);
00152     return CURLE_COULDNT_CONNECT;
00153   }
00154 
00155   /* As long as we need to keep sending some context info, and there's no  */
00156   /* errors, keep sending it...                                            */
00157   for(;;) {
00158     TCHAR *sname;
00159 
00160     sname = Curl_convert_UTF8_to_tchar(service_name);
00161     if(!sname)
00162       return CURLE_OUT_OF_MEMORY;
00163 
00164     status = s_pSecFn->InitializeSecurityContext(&cred_handle,
00165                                                  context_handle,
00166                                                  sname,
00167                                                  ISC_REQ_MUTUAL_AUTH |
00168                                                  ISC_REQ_ALLOCATE_MEMORY |
00169                                                  ISC_REQ_CONFIDENTIALITY |
00170                                                  ISC_REQ_REPLAY_DETECT,
00171                                                  0,
00172                                                  SECURITY_NATIVE_DREP,
00173                                                  &input_desc,
00174                                                  0,
00175                                                  &sspi_context,
00176                                                  &output_desc,
00177                                                  &sspi_ret_flags,
00178                                                  &expiry);
00179 
00180     Curl_unicodefree(sname);
00181 
00182     if(sspi_recv_token.pvBuffer) {
00183       s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00184       sspi_recv_token.pvBuffer = NULL;
00185       sspi_recv_token.cbBuffer = 0;
00186     }
00187 
00188     if(check_sspi_err(conn, status, "InitializeSecurityContext")) {
00189       free(service_name);
00190       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00191       s_pSecFn->DeleteSecurityContext(&sspi_context);
00192       if(sspi_recv_token.pvBuffer)
00193         s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00194       failf(data, "Failed to initialise security context.");
00195       return CURLE_COULDNT_CONNECT;
00196     }
00197 
00198     if(sspi_send_token.cbBuffer != 0) {
00199       socksreq[0] = 1;    /* GSS-API subnegotiation version */
00200       socksreq[1] = 1;    /* authentication message type */
00201       us_length = htons((short)sspi_send_token.cbBuffer);
00202       memcpy(socksreq+2, &us_length, sizeof(short));
00203 
00204       code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
00205       if(code || (4 != written)) {
00206         failf(data, "Failed to send SSPI authentication request.");
00207         free(service_name);
00208         if(sspi_send_token.pvBuffer)
00209           s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00210         if(sspi_recv_token.pvBuffer)
00211           s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00212         s_pSecFn->FreeCredentialsHandle(&cred_handle);
00213         s_pSecFn->DeleteSecurityContext(&sspi_context);
00214         return CURLE_COULDNT_CONNECT;
00215       }
00216 
00217       code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
00218                               sspi_send_token.cbBuffer, &written);
00219       if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
00220         failf(data, "Failed to send SSPI authentication token.");
00221         free(service_name);
00222         if(sspi_send_token.pvBuffer)
00223           s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00224         if(sspi_recv_token.pvBuffer)
00225           s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00226         s_pSecFn->FreeCredentialsHandle(&cred_handle);
00227         s_pSecFn->DeleteSecurityContext(&sspi_context);
00228         return CURLE_COULDNT_CONNECT;
00229       }
00230 
00231     }
00232 
00233     if(sspi_send_token.pvBuffer) {
00234       s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00235       sspi_send_token.pvBuffer = NULL;
00236     }
00237     sspi_send_token.cbBuffer = 0;
00238 
00239     if(sspi_recv_token.pvBuffer) {
00240       s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00241       sspi_recv_token.pvBuffer = NULL;
00242     }
00243     sspi_recv_token.cbBuffer = 0;
00244 
00245     if(status != SEC_I_CONTINUE_NEEDED)
00246       break;
00247 
00248     /* analyse response */
00249 
00250     /*   GSS-API response looks like
00251      * +----+------+-----+----------------+
00252      * |VER | MTYP | LEN |     TOKEN      |
00253      * +----+------+----------------------+
00254      * | 1  |  1   |  2  | up to 2^16 - 1 |
00255      * +----+------+-----+----------------+
00256      */
00257 
00258     result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
00259     if(result || (actualread != 4)) {
00260       failf(data, "Failed to receive SSPI authentication response.");
00261       free(service_name);
00262       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00263       s_pSecFn->DeleteSecurityContext(&sspi_context);
00264       return CURLE_COULDNT_CONNECT;
00265     }
00266 
00267     /* ignore the first (VER) byte */
00268     if(socksreq[1] == 255) { /* status / message type */
00269       failf(data, "User was rejected by the SOCKS5 server (%u %u).",
00270             (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
00271       free(service_name);
00272       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00273       s_pSecFn->DeleteSecurityContext(&sspi_context);
00274       return CURLE_COULDNT_CONNECT;
00275     }
00276 
00277     if(socksreq[1] != 1) { /* status / messgae type */
00278       failf(data, "Invalid SSPI authentication response type (%u %u).",
00279             (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
00280       free(service_name);
00281       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00282       s_pSecFn->DeleteSecurityContext(&sspi_context);
00283       return CURLE_COULDNT_CONNECT;
00284     }
00285 
00286     memcpy(&us_length, socksreq+2, sizeof(short));
00287     us_length = ntohs(us_length);
00288 
00289     sspi_recv_token.cbBuffer = us_length;
00290     sspi_recv_token.pvBuffer = malloc(us_length);
00291 
00292     if(!sspi_recv_token.pvBuffer) {
00293       free(service_name);
00294       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00295       s_pSecFn->DeleteSecurityContext(&sspi_context);
00296       return CURLE_OUT_OF_MEMORY;
00297     }
00298     result = Curl_blockread_all(conn, sock, (char *)sspi_recv_token.pvBuffer,
00299                                 sspi_recv_token.cbBuffer, &actualread);
00300 
00301     if(result || (actualread != us_length)) {
00302       failf(data, "Failed to receive SSPI authentication token.");
00303       free(service_name);
00304       if(sspi_recv_token.pvBuffer)
00305         s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);
00306       s_pSecFn->FreeCredentialsHandle(&cred_handle);
00307       s_pSecFn->DeleteSecurityContext(&sspi_context);
00308       return CURLE_COULDNT_CONNECT;
00309     }
00310 
00311     context_handle = &sspi_context;
00312   }
00313 
00314   free(service_name);
00315 
00316   /* Everything is good so far, user was authenticated! */
00317   status = s_pSecFn->QueryCredentialsAttributes(&cred_handle,
00318                                                 SECPKG_CRED_ATTR_NAMES,
00319                                                 &names);
00320   s_pSecFn->FreeCredentialsHandle(&cred_handle);
00321   if(check_sspi_err(conn, status, "QueryCredentialAttributes")) {
00322     s_pSecFn->DeleteSecurityContext(&sspi_context);
00323     s_pSecFn->FreeContextBuffer(names.sUserName);
00324     failf(data, "Failed to determine user name.");
00325     return CURLE_COULDNT_CONNECT;
00326   }
00327   infof(data, "SOCKS5 server authencticated user %s with GSS-API.\n",
00328         names.sUserName);
00329   s_pSecFn->FreeContextBuffer(names.sUserName);
00330 
00331   /* Do encryption */
00332   socksreq[0] = 1;    /* GSS-API subnegotiation version */
00333   socksreq[1] = 2;    /* encryption message type */
00334 
00335   gss_enc = 0; /* no data protection */
00336   /* do confidentiality protection if supported */
00337   if(sspi_ret_flags & ISC_REQ_CONFIDENTIALITY)
00338     gss_enc = 2;
00339   /* else do integrity protection */
00340   else if(sspi_ret_flags & ISC_REQ_INTEGRITY)
00341     gss_enc = 1;
00342 
00343   infof(data, "SOCKS5 server supports GSS-API %s data protection.\n",
00344         (gss_enc==0)?"no":((gss_enc==1)?"integrity":"confidentiality") );
00345   /* force to no data protection, avoid encryption/decryption for now */
00346   gss_enc = 0;
00347   /*
00348    * Sending the encryption type in clear seems wrong. It should be
00349    * protected with gss_seal()/gss_wrap(). See RFC1961 extract below
00350    * The NEC reference implementations on which this is based is
00351    * therefore at fault
00352    *
00353    *  +------+------+------+.......................+
00354    *  + ver  | mtyp | len  |   token               |
00355    *  +------+------+------+.......................+
00356    *  + 0x01 | 0x02 | 0x02 | up to 2^16 - 1 octets |
00357    *  +------+------+------+.......................+
00358    *
00359    *   Where:
00360    *
00361    *  - "ver" is the protocol version number, here 1 to represent the
00362    *    first version of the SOCKS/GSS-API protocol
00363    *
00364    *  - "mtyp" is the message type, here 2 to represent a protection
00365    *    -level negotiation message
00366    *
00367    *  - "len" is the length of the "token" field in octets
00368    *
00369    *  - "token" is the GSS-API encapsulated protection level
00370    *
00371    * The token is produced by encapsulating an octet containing the
00372    * required protection level using gss_seal()/gss_wrap() with conf_req
00373    * set to FALSE.  The token is verified using gss_unseal()/
00374    * gss_unwrap().
00375    *
00376    */
00377 
00378   if(data->set.socks5_gssapi_nec) {
00379     us_length = htons((short)1);
00380     memcpy(socksreq+2, &us_length, sizeof(short));
00381   }
00382   else {
00383     status = s_pSecFn->QueryContextAttributes(&sspi_context,
00384                                               SECPKG_ATTR_SIZES,
00385                                               &sspi_sizes);
00386     if(check_sspi_err(conn, status, "QueryContextAttributes")) {
00387       s_pSecFn->DeleteSecurityContext(&sspi_context);
00388       failf(data, "Failed to query security context attributes.");
00389       return CURLE_COULDNT_CONNECT;
00390     }
00391 
00392     sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer;
00393     sspi_w_token[0].BufferType = SECBUFFER_TOKEN;
00394     sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer);
00395 
00396     if(!sspi_w_token[0].pvBuffer) {
00397       s_pSecFn->DeleteSecurityContext(&sspi_context);
00398       return CURLE_OUT_OF_MEMORY;
00399     }
00400 
00401     sspi_w_token[1].cbBuffer = 1;
00402     sspi_w_token[1].pvBuffer = malloc(1);
00403     if(!sspi_w_token[1].pvBuffer) {
00404       s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00405       s_pSecFn->DeleteSecurityContext(&sspi_context);
00406       return CURLE_OUT_OF_MEMORY;
00407     }
00408 
00409     memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1);
00410     sspi_w_token[2].BufferType = SECBUFFER_PADDING;
00411     sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize;
00412     sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize);
00413     if(!sspi_w_token[2].pvBuffer) {
00414       s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00415       s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00416       s_pSecFn->DeleteSecurityContext(&sspi_context);
00417       return CURLE_OUT_OF_MEMORY;
00418     }
00419     status = s_pSecFn->EncryptMessage(&sspi_context,
00420                                       KERB_WRAP_NO_ENCRYPT,
00421                                       &wrap_desc,
00422                                       0);
00423     if(check_sspi_err(conn, status, "EncryptMessage")) {
00424       s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00425       s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00426       s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
00427       s_pSecFn->DeleteSecurityContext(&sspi_context);
00428       failf(data, "Failed to query security context attributes.");
00429       return CURLE_COULDNT_CONNECT;
00430     }
00431     sspi_send_token.cbBuffer = sspi_w_token[0].cbBuffer
00432       + sspi_w_token[1].cbBuffer
00433       + sspi_w_token[2].cbBuffer;
00434     sspi_send_token.pvBuffer = malloc(sspi_send_token.cbBuffer);
00435     if(!sspi_send_token.pvBuffer) {
00436       s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00437       s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00438       s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
00439       s_pSecFn->DeleteSecurityContext(&sspi_context);
00440       return CURLE_OUT_OF_MEMORY;
00441     }
00442 
00443     memcpy(sspi_send_token.pvBuffer, sspi_w_token[0].pvBuffer,
00444            sspi_w_token[0].cbBuffer);
00445     memcpy((PUCHAR) sspi_send_token.pvBuffer +(int)sspi_w_token[0].cbBuffer,
00446            sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
00447     memcpy((PUCHAR) sspi_send_token.pvBuffer
00448            +sspi_w_token[0].cbBuffer
00449            +sspi_w_token[1].cbBuffer,
00450            sspi_w_token[2].pvBuffer, sspi_w_token[2].cbBuffer);
00451 
00452     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00453     sspi_w_token[0].pvBuffer = NULL;
00454     sspi_w_token[0].cbBuffer = 0;
00455     s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00456     sspi_w_token[1].pvBuffer = NULL;
00457     sspi_w_token[1].cbBuffer = 0;
00458     s_pSecFn->FreeContextBuffer(sspi_w_token[2].pvBuffer);
00459     sspi_w_token[2].pvBuffer = NULL;
00460     sspi_w_token[2].cbBuffer = 0;
00461 
00462     us_length = htons((short)sspi_send_token.cbBuffer);
00463     memcpy(socksreq+2, &us_length, sizeof(short));
00464   }
00465 
00466   code = Curl_write_plain(conn, sock, (char *)socksreq, 4, &written);
00467   if(code || (4 != written)) {
00468     failf(data, "Failed to send SSPI encryption request.");
00469     if(sspi_send_token.pvBuffer)
00470       s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00471     s_pSecFn->DeleteSecurityContext(&sspi_context);
00472     return CURLE_COULDNT_CONNECT;
00473   }
00474 
00475   if(data->set.socks5_gssapi_nec) {
00476     memcpy(socksreq, &gss_enc, 1);
00477     code = Curl_write_plain(conn, sock, (char *)socksreq, 1, &written);
00478     if(code || (1 != written)) {
00479       failf(data, "Failed to send SSPI encryption type.");
00480       s_pSecFn->DeleteSecurityContext(&sspi_context);
00481       return CURLE_COULDNT_CONNECT;
00482     }
00483   }
00484   else {
00485     code = Curl_write_plain(conn, sock, (char *)sspi_send_token.pvBuffer,
00486                             sspi_send_token.cbBuffer, &written);
00487     if(code || (sspi_send_token.cbBuffer != (size_t)written)) {
00488       failf(data, "Failed to send SSPI encryption type.");
00489       if(sspi_send_token.pvBuffer)
00490         s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00491       s_pSecFn->DeleteSecurityContext(&sspi_context);
00492       return CURLE_COULDNT_CONNECT;
00493     }
00494     if(sspi_send_token.pvBuffer)
00495       s_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer);
00496   }
00497 
00498   result = Curl_blockread_all(conn, sock, (char *)socksreq, 4, &actualread);
00499   if(result || (actualread != 4)) {
00500     failf(data, "Failed to receive SSPI encryption response.");
00501     s_pSecFn->DeleteSecurityContext(&sspi_context);
00502     return CURLE_COULDNT_CONNECT;
00503   }
00504 
00505   /* ignore the first (VER) byte */
00506   if(socksreq[1] == 255) { /* status / message type */
00507     failf(data, "User was rejected by the SOCKS5 server (%u %u).",
00508           (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
00509     s_pSecFn->DeleteSecurityContext(&sspi_context);
00510     return CURLE_COULDNT_CONNECT;
00511   }
00512 
00513   if(socksreq[1] != 2) { /* status / message type */
00514     failf(data, "Invalid SSPI encryption response type (%u %u).",
00515           (unsigned int)socksreq[0], (unsigned int)socksreq[1]);
00516     s_pSecFn->DeleteSecurityContext(&sspi_context);
00517     return CURLE_COULDNT_CONNECT;
00518   }
00519 
00520   memcpy(&us_length, socksreq+2, sizeof(short));
00521   us_length = ntohs(us_length);
00522 
00523   sspi_w_token[0].cbBuffer = us_length;
00524   sspi_w_token[0].pvBuffer = malloc(us_length);
00525   if(!sspi_w_token[0].pvBuffer) {
00526     s_pSecFn->DeleteSecurityContext(&sspi_context);
00527     return CURLE_OUT_OF_MEMORY;
00528   }
00529 
00530   result = Curl_blockread_all(conn, sock, (char *)sspi_w_token[0].pvBuffer,
00531                               sspi_w_token[0].cbBuffer, &actualread);
00532 
00533   if(result || (actualread != us_length)) {
00534     failf(data, "Failed to receive SSPI encryption type.");
00535     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00536     s_pSecFn->DeleteSecurityContext(&sspi_context);
00537     return CURLE_COULDNT_CONNECT;
00538   }
00539 
00540 
00541   if(!data->set.socks5_gssapi_nec) {
00542     wrap_desc.cBuffers = 2;
00543     sspi_w_token[0].BufferType = SECBUFFER_STREAM;
00544     sspi_w_token[1].BufferType = SECBUFFER_DATA;
00545     sspi_w_token[1].cbBuffer = 0;
00546     sspi_w_token[1].pvBuffer = NULL;
00547 
00548     status = s_pSecFn->DecryptMessage(&sspi_context,
00549                                       &wrap_desc,
00550                                       0,
00551                                       &qop);
00552 
00553     if(check_sspi_err(conn, status, "DecryptMessage")) {
00554       if(sspi_w_token[0].pvBuffer)
00555         s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00556       if(sspi_w_token[1].pvBuffer)
00557         s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00558       s_pSecFn->DeleteSecurityContext(&sspi_context);
00559       failf(data, "Failed to query security context attributes.");
00560       return CURLE_COULDNT_CONNECT;
00561     }
00562 
00563     if(sspi_w_token[1].cbBuffer != 1) {
00564       failf(data, "Invalid SSPI encryption response length (%lu).",
00565             (unsigned long)sspi_w_token[1].cbBuffer);
00566       if(sspi_w_token[0].pvBuffer)
00567         s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00568       if(sspi_w_token[1].pvBuffer)
00569         s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00570       s_pSecFn->DeleteSecurityContext(&sspi_context);
00571       return CURLE_COULDNT_CONNECT;
00572     }
00573 
00574     memcpy(socksreq, sspi_w_token[1].pvBuffer, sspi_w_token[1].cbBuffer);
00575     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00576     s_pSecFn->FreeContextBuffer(sspi_w_token[1].pvBuffer);
00577   }
00578   else {
00579     if(sspi_w_token[0].cbBuffer != 1) {
00580       failf(data, "Invalid SSPI encryption response length (%lu).",
00581             (unsigned long)sspi_w_token[0].cbBuffer);
00582       s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00583       s_pSecFn->DeleteSecurityContext(&sspi_context);
00584       return CURLE_COULDNT_CONNECT;
00585     }
00586     memcpy(socksreq, sspi_w_token[0].pvBuffer, sspi_w_token[0].cbBuffer);
00587     s_pSecFn->FreeContextBuffer(sspi_w_token[0].pvBuffer);
00588   }
00589 
00590   infof(data, "SOCKS5 access with%s protection granted.\n",
00591         (socksreq[0]==0)?"out GSS-API data":
00592         ((socksreq[0]==1)?" GSS-API integrity":" GSS-API confidentiality"));
00593 
00594   /* For later use if encryption is required
00595      conn->socks5_gssapi_enctype = socksreq[0];
00596      if(socksreq[0] != 0)
00597        conn->socks5_sspi_context = sspi_context;
00598      else {
00599        s_pSecFn->DeleteSecurityContext(&sspi_context);
00600        conn->socks5_sspi_context = sspi_context;
00601      }
00602   */
00603   return CURLE_OK;
00604 }
00605 #endif


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:06