Annotation of embedaddon/curl/lib/http_ntlm.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: #include "curl_setup.h"
                     24: 
                     25: #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
                     26: 
                     27: /*
                     28:  * NTLM details:
                     29:  *
                     30:  * https://davenport.sourceforge.io/ntlm.html
                     31:  * https://www.innovation.ch/java/ntlm.html
                     32:  */
                     33: 
                     34: #define DEBUG_ME 0
                     35: 
                     36: #include "urldata.h"
                     37: #include "sendf.h"
                     38: #include "strcase.h"
                     39: #include "http_ntlm.h"
                     40: #include "curl_ntlm_core.h"
                     41: #include "curl_ntlm_wb.h"
                     42: #include "vauth/vauth.h"
                     43: #include "url.h"
                     44: 
                     45: /* SSL backend-specific #if branches in this file must be kept in the order
                     46:    documented in curl_ntlm_core. */
                     47: #if defined(USE_WINDOWS_SSPI)
                     48: #include "curl_sspi.h"
                     49: #endif
                     50: 
                     51: /* The last 3 #include files should be in this order */
                     52: #include "curl_printf.h"
                     53: #include "curl_memory.h"
                     54: #include "memdebug.h"
                     55: 
                     56: #if DEBUG_ME
                     57: # define DEBUG_OUT(x) x
                     58: #else
                     59: # define DEBUG_OUT(x) Curl_nop_stmt
                     60: #endif
                     61: 
                     62: CURLcode Curl_input_ntlm(struct connectdata *conn,
                     63:                          bool proxy,         /* if proxy or not */
                     64:                          const char *header) /* rest of the www-authenticate:
                     65:                                                 header */
                     66: {
                     67:   /* point to the correct struct with this */
                     68:   struct ntlmdata *ntlm;
                     69:   curlntlm *state;
                     70:   CURLcode result = CURLE_OK;
                     71: 
                     72:   ntlm = proxy ? &conn->proxyntlm : &conn->ntlm;
                     73:   state = proxy ? &conn->proxy_ntlm_state : &conn->http_ntlm_state;
                     74: 
                     75:   if(checkprefix("NTLM", header)) {
                     76:     header += strlen("NTLM");
                     77: 
                     78:     while(*header && ISSPACE(*header))
                     79:       header++;
                     80: 
                     81:     if(*header) {
                     82:       result = Curl_auth_decode_ntlm_type2_message(conn->data, header, ntlm);
                     83:       if(result)
                     84:         return result;
                     85: 
                     86:       *state = NTLMSTATE_TYPE2; /* We got a type-2 message */
                     87:     }
                     88:     else {
                     89:       if(*state == NTLMSTATE_LAST) {
                     90:         infof(conn->data, "NTLM auth restarted\n");
                     91:         Curl_http_auth_cleanup_ntlm(conn);
                     92:       }
                     93:       else if(*state == NTLMSTATE_TYPE3) {
                     94:         infof(conn->data, "NTLM handshake rejected\n");
                     95:         Curl_http_auth_cleanup_ntlm(conn);
                     96:         *state = NTLMSTATE_NONE;
                     97:         return CURLE_REMOTE_ACCESS_DENIED;
                     98:       }
                     99:       else if(*state >= NTLMSTATE_TYPE1) {
                    100:         infof(conn->data, "NTLM handshake failure (internal error)\n");
                    101:         return CURLE_REMOTE_ACCESS_DENIED;
                    102:       }
                    103: 
                    104:       *state = NTLMSTATE_TYPE1; /* We should send away a type-1 */
                    105:     }
                    106:   }
                    107: 
                    108:   return result;
                    109: }
                    110: 
                    111: /*
                    112:  * This is for creating ntlm header output
                    113:  */
                    114: CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
                    115: {
                    116:   char *base64 = NULL;
                    117:   size_t len = 0;
                    118:   CURLcode result;
                    119: 
                    120:   /* point to the address of the pointer that holds the string to send to the
                    121:      server, which is for a plain host or for a HTTP proxy */
                    122:   char **allocuserpwd;
                    123: 
                    124:   /* point to the username, password, service and host */
                    125:   const char *userp;
                    126:   const char *passwdp;
                    127:   const char *service = NULL;
                    128:   const char *hostname = NULL;
                    129: 
                    130:   /* point to the correct struct with this */
                    131:   struct ntlmdata *ntlm;
                    132:   curlntlm *state;
                    133:   struct auth *authp;
                    134: 
                    135:   DEBUGASSERT(conn);
                    136:   DEBUGASSERT(conn->data);
                    137: 
                    138:   if(proxy) {
                    139:     allocuserpwd = &conn->allocptr.proxyuserpwd;
                    140:     userp = conn->http_proxy.user;
                    141:     passwdp = conn->http_proxy.passwd;
                    142:     service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
                    143:               conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
                    144:     hostname = conn->http_proxy.host.name;
                    145:     ntlm = &conn->proxyntlm;
                    146:     state = &conn->proxy_ntlm_state;
                    147:     authp = &conn->data->state.authproxy;
                    148:   }
                    149:   else {
                    150:     allocuserpwd = &conn->allocptr.userpwd;
                    151:     userp = conn->user;
                    152:     passwdp = conn->passwd;
                    153:     service = conn->data->set.str[STRING_SERVICE_NAME] ?
                    154:               conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
                    155:     hostname = conn->host.name;
                    156:     ntlm = &conn->ntlm;
                    157:     state = &conn->http_ntlm_state;
                    158:     authp = &conn->data->state.authhost;
                    159:   }
                    160:   authp->done = FALSE;
                    161: 
                    162:   /* not set means empty */
                    163:   if(!userp)
                    164:     userp = "";
                    165: 
                    166:   if(!passwdp)
                    167:     passwdp = "";
                    168: 
                    169: #ifdef USE_WINDOWS_SSPI
                    170:   if(s_hSecDll == NULL) {
                    171:     /* not thread safe and leaks - use curl_global_init() to avoid */
                    172:     CURLcode err = Curl_sspi_global_init();
                    173:     if(s_hSecDll == NULL)
                    174:       return err;
                    175:   }
                    176: #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
                    177:   ntlm->sslContext = conn->sslContext;
                    178: #endif
                    179: #endif
                    180: 
                    181:   switch(*state) {
                    182:   case NTLMSTATE_TYPE1:
                    183:   default: /* for the weird cases we (re)start here */
                    184:     /* Create a type-1 message */
                    185:     result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
                    186:                                                  service, hostname,
                    187:                                                  ntlm, &base64,
                    188:                                                  &len);
                    189:     if(result)
                    190:       return result;
                    191: 
                    192:     if(base64) {
                    193:       free(*allocuserpwd);
                    194:       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                    195:                               proxy ? "Proxy-" : "",
                    196:                               base64);
                    197:       free(base64);
                    198:       if(!*allocuserpwd)
                    199:         return CURLE_OUT_OF_MEMORY;
                    200: 
                    201:       DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
                    202:     }
                    203:     break;
                    204: 
                    205:   case NTLMSTATE_TYPE2:
                    206:     /* We already received the type-2 message, create a type-3 message */
                    207:     result = Curl_auth_create_ntlm_type3_message(conn->data, userp, passwdp,
                    208:                                                  ntlm, &base64, &len);
                    209:     if(result)
                    210:       return result;
                    211: 
                    212:     if(base64) {
                    213:       free(*allocuserpwd);
                    214:       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
                    215:                               proxy ? "Proxy-" : "",
                    216:                               base64);
                    217:       free(base64);
                    218:       if(!*allocuserpwd)
                    219:         return CURLE_OUT_OF_MEMORY;
                    220: 
                    221:       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
                    222: 
                    223:       *state = NTLMSTATE_TYPE3; /* we send a type-3 */
                    224:       authp->done = TRUE;
                    225:     }
                    226:     break;
                    227: 
                    228:   case NTLMSTATE_TYPE3:
                    229:     /* connection is already authenticated,
                    230:      * don't send a header in future requests */
                    231:     *state = NTLMSTATE_LAST;
                    232:     /* FALLTHROUGH */
                    233:   case NTLMSTATE_LAST:
                    234:     Curl_safefree(*allocuserpwd);
                    235:     authp->done = TRUE;
                    236:     break;
                    237:   }
                    238: 
                    239:   return CURLE_OK;
                    240: }
                    241: 
                    242: void Curl_http_auth_cleanup_ntlm(struct connectdata *conn)
                    243: {
                    244:   Curl_auth_cleanup_ntlm(&conn->ntlm);
                    245:   Curl_auth_cleanup_ntlm(&conn->proxyntlm);
                    246: 
                    247: #if defined(NTLM_WB_ENABLED)
                    248:   Curl_http_auth_cleanup_ntlm_wb(conn);
                    249: #endif
                    250: }
                    251: 
                    252: #endif /* !CURL_DISABLE_HTTP && USE_NTLM */

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