ntlm.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
00026 
00027 /*
00028  * NTLM details:
00029  *
00030  * http://davenport.sourceforge.net/ntlm.html
00031  * https://www.innovation.ch/java/ntlm.html
00032  */
00033 
00034 #define DEBUG_ME 0
00035 
00036 #include "urldata.h"
00037 #include "non-ascii.h"
00038 #include "sendf.h"
00039 #include "curl_base64.h"
00040 #include "curl_ntlm_core.h"
00041 #include "curl_gethostname.h"
00042 #include "curl_multibyte.h"
00043 #include "warnless.h"
00044 #include "rand.h"
00045 #include "vtls/vtls.h"
00046 
00047 #ifdef USE_NSS
00048 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
00049 #endif
00050 
00051 #define BUILDING_CURL_NTLM_MSGS_C
00052 #include "vauth/vauth.h"
00053 #include "vauth/ntlm.h"
00054 #include "curl_endian.h"
00055 #include "curl_printf.h"
00056 
00057 /* The last #include files should be: */
00058 #include "curl_memory.h"
00059 #include "memdebug.h"
00060 
00061 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
00062 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
00063 
00064 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
00065 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
00066   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
00067 
00068 #if DEBUG_ME
00069 # define DEBUG_OUT(x) x
00070 static void ntlm_print_flags(FILE *handle, unsigned long flags)
00071 {
00072   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
00073     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
00074   if(flags & NTLMFLAG_NEGOTIATE_OEM)
00075     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
00076   if(flags & NTLMFLAG_REQUEST_TARGET)
00077     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
00078   if(flags & (1<<3))
00079     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
00080   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
00081     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
00082   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
00083     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
00084   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
00085     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
00086   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
00087     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
00088   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
00089     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
00090   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
00091     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
00092   if(flags & (1<<10))
00093     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
00094   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
00095     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
00096   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
00097     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
00098   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
00099     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
00100   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
00101     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
00102   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
00103     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
00104   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
00105     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
00106   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
00107     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
00108   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
00109     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
00110   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
00111     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
00112   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
00113     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
00114   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
00115     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
00116   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
00117     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
00118   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
00119     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
00120   if(flags & (1<<24))
00121     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
00122   if(flags & (1<<25))
00123     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
00124   if(flags & (1<<26))
00125     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
00126   if(flags & (1<<27))
00127     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
00128   if(flags & (1<<28))
00129     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
00130   if(flags & NTLMFLAG_NEGOTIATE_128)
00131     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
00132   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
00133     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
00134   if(flags & NTLMFLAG_NEGOTIATE_56)
00135     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
00136 }
00137 
00138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
00139 {
00140   const char *p = buf;
00141 
00142   (void) handle;
00143 
00144   fprintf(stderr, "0x");
00145   while(len-- > 0)
00146     fprintf(stderr, "%02.2x", (unsigned int)*p++);
00147 }
00148 #else
00149 # define DEBUG_OUT(x) Curl_nop_stmt
00150 #endif
00151 
00152 /*
00153  * ntlm_decode_type2_target()
00154  *
00155  * This is used to decode the "target info" in the NTLM type-2 message
00156  * received.
00157  *
00158  * Parameters:
00159  *
00160  * data      [in]     - The session handle.
00161  * buffer    [in]     - The decoded type-2 message.
00162  * size      [in]     - The input buffer size, at least 32 bytes.
00163  * ntlm      [in/out] - The NTLM data struct being used and modified.
00164  *
00165  * Returns CURLE_OK on success.
00166  */
00167 static CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
00168                                          unsigned char *buffer,
00169                                          size_t size,
00170                                          struct ntlmdata *ntlm)
00171 {
00172   unsigned short target_info_len = 0;
00173   unsigned int target_info_offset = 0;
00174 
00175 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
00176   (void) data;
00177 #endif
00178 
00179   if(size >= 48) {
00180     target_info_len = Curl_read16_le(&buffer[40]);
00181     target_info_offset = Curl_read32_le(&buffer[44]);
00182     if(target_info_len > 0) {
00183       if(((target_info_offset + target_info_len) > size) ||
00184          (target_info_offset < 48)) {
00185         infof(data, "NTLM handshake failure (bad type-2 message). "
00186                     "Target Info Offset Len is set incorrect by the peer\n");
00187         return CURLE_BAD_CONTENT_ENCODING;
00188       }
00189 
00190       ntlm->target_info = malloc(target_info_len);
00191       if(!ntlm->target_info)
00192         return CURLE_OUT_OF_MEMORY;
00193 
00194       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
00195     }
00196   }
00197 
00198   ntlm->target_info_len = target_info_len;
00199 
00200   return CURLE_OK;
00201 }
00202 
00203 /*
00204   NTLM message structure notes:
00205 
00206   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
00207 
00208   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
00209 
00210   A 'security buffer' represents a triplet used to point to a buffer,
00211   consisting of two shorts and one long:
00212 
00213     1. A 'short' containing the length of the buffer content in bytes.
00214     2. A 'short' containing the allocated space for the buffer in bytes.
00215     3. A 'long' containing the offset to the start of the buffer in bytes,
00216        from the beginning of the NTLM message.
00217 */
00218 
00219 /*
00220  * Curl_auth_is_ntlm_supported()
00221  *
00222  * This is used to evaluate if NTLM is supported.
00223  *
00224  * Parameters: None
00225  *
00226  * Returns TRUE as NTLM as handled by libcurl.
00227  */
00228 bool Curl_auth_is_ntlm_supported(void)
00229 {
00230   return TRUE;
00231 }
00232 
00233 /*
00234  * Curl_auth_decode_ntlm_type2_message()
00235  *
00236  * This is used to decode an already encoded NTLM type-2 message. The message
00237  * is first decoded from a base64 string into a raw NTLM message and checked
00238  * for validity before the appropriate data for creating a type-3 message is
00239  * written to the given NTLM data structure.
00240  *
00241  * Parameters:
00242  *
00243  * data     [in]     - The session handle.
00244  * type2msg [in]     - The base64 encoded type-2 message.
00245  * ntlm     [in/out] - The NTLM data struct being used and modified.
00246  *
00247  * Returns CURLE_OK on success.
00248  */
00249 CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
00250                                              const char *type2msg,
00251                                              struct ntlmdata *ntlm)
00252 {
00253   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
00254 
00255   /* NTLM type-2 message structure:
00256 
00257           Index  Description            Content
00258             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
00259                                         (0x4e544c4d53535000)
00260             8    NTLM Message Type      long (0x02000000)
00261            12    Target Name            security buffer
00262            20    Flags                  long
00263            24    Challenge              8 bytes
00264           (32)   Context                8 bytes (two consecutive longs) (*)
00265           (40)   Target Information     security buffer (*)
00266           (48)   OS Version Structure   8 bytes (*)
00267   32 (48) (56)   Start of data block    (*)
00268                                         (*) -> Optional
00269   */
00270 
00271   CURLcode result = CURLE_OK;
00272   unsigned char *type2 = NULL;
00273   size_t type2_len = 0;
00274 
00275 #if defined(USE_NSS)
00276   /* Make sure the crypto backend is initialized */
00277   result = Curl_nss_force_init(data);
00278   if(result)
00279     return result;
00280 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
00281   (void)data;
00282 #endif
00283 
00284   /* Decode the base-64 encoded type-2 message */
00285   if(strlen(type2msg) && *type2msg != '=') {
00286     result = Curl_base64_decode(type2msg, &type2, &type2_len);
00287     if(result)
00288       return result;
00289   }
00290 
00291   /* Ensure we have a valid type-2 message */
00292   if(!type2) {
00293     infof(data, "NTLM handshake failure (empty type-2 message)\n");
00294     return CURLE_BAD_CONTENT_ENCODING;
00295   }
00296 
00297   ntlm->flags = 0;
00298 
00299   if((type2_len < 32) ||
00300      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
00301      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
00302     /* This was not a good enough type-2 message */
00303     free(type2);
00304     infof(data, "NTLM handshake failure (bad type-2 message)\n");
00305     return CURLE_BAD_CONTENT_ENCODING;
00306   }
00307 
00308   ntlm->flags = Curl_read32_le(&type2[20]);
00309   memcpy(ntlm->nonce, &type2[24], 8);
00310 
00311   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
00312     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
00313     if(result) {
00314       free(type2);
00315       infof(data, "NTLM handshake failure (bad type-2 message)\n");
00316       return result;
00317     }
00318   }
00319 
00320   DEBUG_OUT({
00321     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
00322     ntlm_print_flags(stderr, ntlm->flags);
00323     fprintf(stderr, "\n                  nonce=");
00324     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
00325     fprintf(stderr, "\n****\n");
00326     fprintf(stderr, "**** Header %s\n ", header);
00327   });
00328 
00329   free(type2);
00330 
00331   return result;
00332 }
00333 
00334 /* copy the source to the destination and fill in zeroes in every
00335    other destination byte! */
00336 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
00337 {
00338   size_t i;
00339   for(i = 0; i < length; i++) {
00340     dest[2 * i] = (unsigned char)src[i];
00341     dest[2 * i + 1] = '\0';
00342   }
00343 }
00344 
00345 /*
00346  * Curl_auth_create_ntlm_type1_message()
00347  *
00348  * This is used to generate an already encoded NTLM type-1 message ready for
00349  * sending to the recipient using the appropriate compile time crypto API.
00350  *
00351  * Parameters:
00352  *
00353  * userp   [in]     - The user name in the format User or Domain\User.
00354  * passdwp [in]     - The user's password.
00355  * ntlm    [in/out] - The NTLM data struct being used and modified.
00356  * outptr  [in/out] - The address where a pointer to newly allocated memory
00357  *                    holding the result will be stored upon completion.
00358  * outlen  [out]    - The length of the output message.
00359  *
00360  * Returns CURLE_OK on success.
00361  */
00362 CURLcode Curl_auth_create_ntlm_type1_message(const char *userp,
00363                                              const char *passwdp,
00364                                              struct ntlmdata *ntlm,
00365                                              char **outptr, size_t *outlen)
00366 {
00367   /* NTLM type-1 message structure:
00368 
00369        Index  Description            Content
00370          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
00371                                      (0x4e544c4d53535000)
00372          8    NTLM Message Type      long (0x01000000)
00373         12    Flags                  long
00374        (16)   Supplied Domain        security buffer (*)
00375        (24)   Supplied Workstation   security buffer (*)
00376        (32)   OS Version Structure   8 bytes (*)
00377   (32) (40)   Start of data block    (*)
00378                                      (*) -> Optional
00379   */
00380 
00381   size_t size;
00382 
00383   unsigned char ntlmbuf[NTLM_BUFSIZE];
00384   const char *host = "";              /* empty */
00385   const char *domain = "";            /* empty */
00386   size_t hostlen = 0;
00387   size_t domlen = 0;
00388   size_t hostoff = 0;
00389   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
00390                                          domain are empty */
00391   (void)userp;
00392   (void)passwdp;
00393 
00394   /* Clean up any former leftovers and initialise to defaults */
00395   Curl_auth_ntlm_cleanup(ntlm);
00396 
00397 #if USE_NTRESPONSES && USE_NTLM2SESSION
00398 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
00399 #else
00400 #define NTLM2FLAG 0
00401 #endif
00402   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
00403            NTLMSSP_SIGNATURE "%c"
00404            "\x01%c%c%c" /* 32-bit type = 1 */
00405            "%c%c%c%c"   /* 32-bit NTLM flag field */
00406            "%c%c"       /* domain length */
00407            "%c%c"       /* domain allocated space */
00408            "%c%c"       /* domain name offset */
00409            "%c%c"       /* 2 zeroes */
00410            "%c%c"       /* host length */
00411            "%c%c"       /* host allocated space */
00412            "%c%c"       /* host name offset */
00413            "%c%c"       /* 2 zeroes */
00414            "%s"         /* host name */
00415            "%s",        /* domain string */
00416            0,           /* trailing zero */
00417            0, 0, 0,     /* part of type-1 long */
00418 
00419            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
00420                        NTLMFLAG_REQUEST_TARGET |
00421                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
00422                        NTLM2FLAG |
00423                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
00424            SHORTPAIR(domlen),
00425            SHORTPAIR(domlen),
00426            SHORTPAIR(domoff),
00427            0, 0,
00428            SHORTPAIR(hostlen),
00429            SHORTPAIR(hostlen),
00430            SHORTPAIR(hostoff),
00431            0, 0,
00432            host,  /* this is empty */
00433            domain /* this is empty */);
00434 
00435   /* Initial packet length */
00436   size = 32 + hostlen + domlen;
00437 
00438   DEBUG_OUT({
00439     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
00440             "0x%08.8x ",
00441             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
00442                         NTLMFLAG_REQUEST_TARGET |
00443                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
00444                         NTLM2FLAG |
00445                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
00446             NTLMFLAG_NEGOTIATE_OEM |
00447             NTLMFLAG_REQUEST_TARGET |
00448             NTLMFLAG_NEGOTIATE_NTLM_KEY |
00449             NTLM2FLAG |
00450             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
00451     ntlm_print_flags(stderr,
00452                      NTLMFLAG_NEGOTIATE_OEM |
00453                      NTLMFLAG_REQUEST_TARGET |
00454                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
00455                      NTLM2FLAG |
00456                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
00457     fprintf(stderr, "\n****\n");
00458   });
00459 
00460   /* Return with binary blob encoded into base64 */
00461   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
00462 }
00463 
00464 /*
00465  * Curl_auth_create_ntlm_type3_message()
00466  *
00467  * This is used to generate an already encoded NTLM type-3 message ready for
00468  * sending to the recipient using the appropriate compile time crypto API.
00469  *
00470  * Parameters:
00471  *
00472  * data    [in]     - The session handle.
00473  * userp   [in]     - The user name in the format User or Domain\User.
00474  * passdwp [in]     - The user's password.
00475  * ntlm    [in/out] - The NTLM data struct being used and modified.
00476  * outptr  [in/out] - The address where a pointer to newly allocated memory
00477  *                    holding the result will be stored upon completion.
00478  * outlen  [out]    - The length of the output message.
00479  *
00480  * Returns CURLE_OK on success.
00481  */
00482 CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
00483                                              const char *userp,
00484                                              const char *passwdp,
00485                                              struct ntlmdata *ntlm,
00486                                              char **outptr, size_t *outlen)
00487 
00488 {
00489   /* NTLM type-3 message structure:
00490 
00491           Index  Description            Content
00492             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
00493                                         (0x4e544c4d53535000)
00494             8    NTLM Message Type      long (0x03000000)
00495            12    LM/LMv2 Response       security buffer
00496            20    NTLM/NTLMv2 Response   security buffer
00497            28    Target Name            security buffer
00498            36    User Name              security buffer
00499            44    Workstation Name       security buffer
00500           (52)   Session Key            security buffer (*)
00501           (60)   Flags                  long (*)
00502           (64)   OS Version Structure   8 bytes (*)
00503   52 (64) (72)   Start of data block
00504                                           (*) -> Optional
00505   */
00506 
00507   CURLcode result = CURLE_OK;
00508   size_t size;
00509   unsigned char ntlmbuf[NTLM_BUFSIZE];
00510   int lmrespoff;
00511   unsigned char lmresp[24]; /* fixed-size */
00512 #if USE_NTRESPONSES
00513   int ntrespoff;
00514   unsigned int ntresplen = 24;
00515   unsigned char ntresp[24]; /* fixed-size */
00516   unsigned char *ptr_ntresp = &ntresp[0];
00517   unsigned char *ntlmv2resp = NULL;
00518 #endif
00519   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
00520   char host[HOSTNAME_MAX + 1] = "";
00521   const char *user;
00522   const char *domain = "";
00523   size_t hostoff = 0;
00524   size_t useroff = 0;
00525   size_t domoff = 0;
00526   size_t hostlen = 0;
00527   size_t userlen = 0;
00528   size_t domlen = 0;
00529 
00530   user = strchr(userp, '\\');
00531   if(!user)
00532     user = strchr(userp, '/');
00533 
00534   if(user) {
00535     domain = userp;
00536     domlen = (user - domain);
00537     user++;
00538   }
00539   else
00540     user = userp;
00541 
00542   if(user)
00543     userlen = strlen(user);
00544 
00545   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
00546      qualified domain name */
00547   if(Curl_gethostname(host, sizeof(host))) {
00548     infof(data, "gethostname() failed, continuing without!\n");
00549     hostlen = 0;
00550   }
00551   else {
00552     hostlen = strlen(host);
00553   }
00554 
00555 #if USE_NTRESPONSES && USE_NTLM_V2
00556   if(ntlm->target_info_len) {
00557     unsigned char ntbuffer[0x18];
00558     unsigned int entropy[2];
00559     unsigned char ntlmv2hash[0x18];
00560 
00561     result = Curl_rand(data, &entropy[0], 2);
00562     if(result)
00563       return result;
00564 
00565     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
00566     if(result)
00567       return result;
00568 
00569     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
00570                                            ntbuffer, ntlmv2hash);
00571     if(result)
00572       return result;
00573 
00574     /* LMv2 response */
00575     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
00576                                          (unsigned char *)&entropy[0],
00577                                          &ntlm->nonce[0], lmresp);
00578     if(result)
00579       return result;
00580 
00581     /* NTLMv2 response */
00582     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
00583                                            (unsigned char *)&entropy[0],
00584                                            ntlm, &ntlmv2resp, &ntresplen);
00585     if(result)
00586       return result;
00587 
00588     ptr_ntresp = ntlmv2resp;
00589   }
00590   else
00591 #endif
00592 
00593 #if USE_NTRESPONSES && USE_NTLM2SESSION
00594   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
00595   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
00596     unsigned char ntbuffer[0x18];
00597     unsigned char tmp[0x18];
00598     unsigned char md5sum[MD5_DIGEST_LENGTH];
00599     unsigned int entropy[2];
00600 
00601     /* Need to create 8 bytes random data */
00602     result = Curl_rand(data, &entropy[0], 2);
00603     if(result)
00604       return result;
00605 
00606     /* 8 bytes random data as challenge in lmresp */
00607     memcpy(lmresp, entropy, 8);
00608 
00609     /* Pad with zeros */
00610     memset(lmresp + 8, 0, 0x10);
00611 
00612     /* Fill tmp with challenge(nonce?) + entropy */
00613     memcpy(tmp, &ntlm->nonce[0], 8);
00614     memcpy(tmp + 8, entropy, 8);
00615 
00616     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
00617     if(!result)
00618       /* We shall only use the first 8 bytes of md5sum, but the des code in
00619          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
00620       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
00621     if(result)
00622       return result;
00623 
00624     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
00625 
00626     /* End of NTLM2 Session code */
00627 
00628   }
00629   else
00630 #endif
00631   {
00632 
00633 #if USE_NTRESPONSES
00634     unsigned char ntbuffer[0x18];
00635 #endif
00636     unsigned char lmbuffer[0x18];
00637 
00638 #if USE_NTRESPONSES
00639     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
00640     if(result)
00641       return result;
00642 
00643     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
00644 #endif
00645 
00646     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
00647     if(result)
00648       return result;
00649 
00650     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
00651 
00652     /* A safer but less compatible alternative is:
00653      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
00654      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
00655   }
00656 
00657   if(unicode) {
00658     domlen = domlen * 2;
00659     userlen = userlen * 2;
00660     hostlen = hostlen * 2;
00661   }
00662 
00663   lmrespoff = 64; /* size of the message header */
00664 #if USE_NTRESPONSES
00665   ntrespoff = lmrespoff + 0x18;
00666   domoff = ntrespoff + ntresplen;
00667 #else
00668   domoff = lmrespoff + 0x18;
00669 #endif
00670   useroff = domoff + domlen;
00671   hostoff = useroff + userlen;
00672 
00673   /* Create the big type-3 message binary blob */
00674   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
00675                   NTLMSSP_SIGNATURE "%c"
00676                   "\x03%c%c%c"  /* 32-bit type = 3 */
00677 
00678                   "%c%c"  /* LanManager length */
00679                   "%c%c"  /* LanManager allocated space */
00680                   "%c%c"  /* LanManager offset */
00681                   "%c%c"  /* 2 zeroes */
00682 
00683                   "%c%c"  /* NT-response length */
00684                   "%c%c"  /* NT-response allocated space */
00685                   "%c%c"  /* NT-response offset */
00686                   "%c%c"  /* 2 zeroes */
00687 
00688                   "%c%c"  /* domain length */
00689                   "%c%c"  /* domain allocated space */
00690                   "%c%c"  /* domain name offset */
00691                   "%c%c"  /* 2 zeroes */
00692 
00693                   "%c%c"  /* user length */
00694                   "%c%c"  /* user allocated space */
00695                   "%c%c"  /* user offset */
00696                   "%c%c"  /* 2 zeroes */
00697 
00698                   "%c%c"  /* host length */
00699                   "%c%c"  /* host allocated space */
00700                   "%c%c"  /* host offset */
00701                   "%c%c"  /* 2 zeroes */
00702 
00703                   "%c%c"  /* session key length (unknown purpose) */
00704                   "%c%c"  /* session key allocated space (unknown purpose) */
00705                   "%c%c"  /* session key offset (unknown purpose) */
00706                   "%c%c"  /* 2 zeroes */
00707 
00708                   "%c%c%c%c",  /* flags */
00709 
00710                   /* domain string */
00711                   /* user string */
00712                   /* host string */
00713                   /* LanManager response */
00714                   /* NT response */
00715 
00716                   0,                /* zero termination */
00717                   0, 0, 0,          /* type-3 long, the 24 upper bits */
00718 
00719                   SHORTPAIR(0x18),  /* LanManager response length, twice */
00720                   SHORTPAIR(0x18),
00721                   SHORTPAIR(lmrespoff),
00722                   0x0, 0x0,
00723 
00724 #if USE_NTRESPONSES
00725                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
00726                   SHORTPAIR(ntresplen),
00727                   SHORTPAIR(ntrespoff),
00728                   0x0, 0x0,
00729 #else
00730                   0x0, 0x0,
00731                   0x0, 0x0,
00732                   0x0, 0x0,
00733                   0x0, 0x0,
00734 #endif
00735                   SHORTPAIR(domlen),
00736                   SHORTPAIR(domlen),
00737                   SHORTPAIR(domoff),
00738                   0x0, 0x0,
00739 
00740                   SHORTPAIR(userlen),
00741                   SHORTPAIR(userlen),
00742                   SHORTPAIR(useroff),
00743                   0x0, 0x0,
00744 
00745                   SHORTPAIR(hostlen),
00746                   SHORTPAIR(hostlen),
00747                   SHORTPAIR(hostoff),
00748                   0x0, 0x0,
00749 
00750                   0x0, 0x0,
00751                   0x0, 0x0,
00752                   0x0, 0x0,
00753                   0x0, 0x0,
00754 
00755                   LONGQUARTET(ntlm->flags));
00756 
00757   DEBUGASSERT(size == 64);
00758   DEBUGASSERT(size == (size_t)lmrespoff);
00759 
00760   /* We append the binary hashes */
00761   if(size < (NTLM_BUFSIZE - 0x18)) {
00762     memcpy(&ntlmbuf[size], lmresp, 0x18);
00763     size += 0x18;
00764   }
00765 
00766   DEBUG_OUT({
00767     fprintf(stderr, "**** TYPE3 header lmresp=");
00768     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
00769   });
00770 
00771 #if USE_NTRESPONSES
00772   if(size < (NTLM_BUFSIZE - ntresplen)) {
00773     DEBUGASSERT(size == (size_t)ntrespoff);
00774     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
00775     size += ntresplen;
00776   }
00777 
00778   DEBUG_OUT({
00779     fprintf(stderr, "\n   ntresp=");
00780     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
00781   });
00782 
00783   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
00784 
00785 #endif
00786 
00787   DEBUG_OUT({
00788     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
00789             LONGQUARTET(ntlm->flags), ntlm->flags);
00790     ntlm_print_flags(stderr, ntlm->flags);
00791     fprintf(stderr, "\n****\n");
00792   });
00793 
00794   /* Make sure that the domain, user and host strings fit in the
00795      buffer before we copy them there. */
00796   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
00797     failf(data, "user + domain + host name too big");
00798     return CURLE_OUT_OF_MEMORY;
00799   }
00800 
00801   DEBUGASSERT(size == domoff);
00802   if(unicode)
00803     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
00804   else
00805     memcpy(&ntlmbuf[size], domain, domlen);
00806 
00807   size += domlen;
00808 
00809   DEBUGASSERT(size == useroff);
00810   if(unicode)
00811     unicodecpy(&ntlmbuf[size], user, userlen / 2);
00812   else
00813     memcpy(&ntlmbuf[size], user, userlen);
00814 
00815   size += userlen;
00816 
00817   DEBUGASSERT(size == hostoff);
00818   if(unicode)
00819     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
00820   else
00821     memcpy(&ntlmbuf[size], host, hostlen);
00822 
00823   size += hostlen;
00824 
00825   /* Convert domain, user, and host to ASCII but leave the rest as-is */
00826   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
00827                                    size - domoff);
00828   if(result)
00829     return CURLE_CONV_FAILED;
00830 
00831   /* Return with binary blob encoded into base64 */
00832   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
00833 
00834   Curl_auth_ntlm_cleanup(ntlm);
00835 
00836   return result;
00837 }
00838 
00839 /*
00840 * Curl_auth_ntlm_cleanup()
00841 *
00842 * This is used to clean up the NTLM specific data.
00843 *
00844 * Parameters:
00845 *
00846 * ntlm    [in/out] - The NTLM data struct being cleaned up.
00847 *
00848 */
00849 void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
00850 {
00851   /* Free the target info */
00852   Curl_safefree(ntlm->target_info);
00853 
00854   /* Reset any variables */
00855   ntlm->target_info_len = 0;
00856 }
00857 
00858 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */


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