Annotation of embedaddon/curl/lib/http_ntlm.c, revision 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>