File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / socks_sspi.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>