diff options
Diffstat (limited to 'libs/libcurl/src/curl_ntlm_wb.c')
-rw-r--r-- | libs/libcurl/src/curl_ntlm_wb.c | 154 |
1 files changed, 94 insertions, 60 deletions
diff --git a/libs/libcurl/src/curl_ntlm_wb.c b/libs/libcurl/src/curl_ntlm_wb.c index b1c20e1b3b..03f47a3a52 100644 --- a/libs/libcurl/src/curl_ntlm_wb.c +++ b/libs/libcurl/src/curl_ntlm_wb.c @@ -5,11 +5,11 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms - * are also available at http://curl.haxx.se/docs/copyright.html. + * are also available at https://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is @@ -22,13 +22,14 @@ #include "curl_setup.h" -#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) /* * NTLM details: * - * http://davenport.sourceforge.net/ntlm.html - * http://www.innovation.ch/java/ntlm.html + * https://davenport.sourceforge.io/ntlm.html + * https://www.innovation.ch/java/ntlm.html */ #define DEBUG_ME 0 @@ -39,19 +40,22 @@ #ifdef HAVE_SIGNAL_H #include <signal.h> #endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif #include "urldata.h" #include "sendf.h" #include "select.h" +#include "vauth/ntlm.h" +#include "curl_ntlm_core.h" #include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" #include "curl_memory.h" - -#define _MPRINTF_REPLACE /* use our functions only */ -#include <curl/mprintf.h> - -/* The last #include file should be: */ #include "memdebug.h" #if DEBUG_ME @@ -102,9 +106,9 @@ void Curl_ntlm_wb_cleanup(struct connectdata *conn) conn->ntlm_auth_hlpr_pid = 0; } - Curl_safefree(conn->challenge_header); + free(conn->challenge_header); conn->challenge_header = NULL; - Curl_safefree(conn->response_header); + free(conn->response_header); conn->response_header = NULL; } @@ -116,7 +120,10 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) char *slash, *domain = NULL; const char *ntlm_auth = NULL; char *ntlm_auth_alloc = NULL; - int error; +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + struct passwd pw, *pw_res; + char pwbuf[1024]; +#endif /* Return if communication with ntlm_auth already set up */ if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || @@ -124,9 +131,34 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) return CURLE_OK; username = userp; + /* The real ntlm_auth really doesn't like being invoked with an + empty username. It won't make inferences for itself, and expects + the client to do so (mostly because it's really designed for + servers like squid to use for auth, and client support is an + afterthought for it). So try hard to provide a suitable username + if we don't already have one. But if we can't, provide the + empty one anyway. Perhaps they have an implementation of the + ntlm_auth helper which *doesn't* need it so we might as well try */ + if(!username || !username[0]) { + username = getenv("NTLMUSER"); + if(!username || !username[0]) + username = getenv("LOGNAME"); + if(!username || !username[0]) + username = getenv("USER"); +#if defined(HAVE_GETPWUID_R) && defined(HAVE_GETEUID) + if((!username || !username[0]) && + !getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) && + pw_res) { + username = pw.pw_name; + } +#endif + if(!username || !username[0]) + username = userp; + } slash = strpbrk(username, "\\/"); if(slash) { - if((domain = strdup(username)) == NULL) + domain = strdup(username); + if(!domain) return CURLE_OUT_OF_MEMORY; slash = domain + (slash - username); *slash = '\0'; @@ -146,26 +178,23 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) ntlm_auth = NTLM_WB_FILE; if(access(ntlm_auth, X_OK) != 0) { - error = ERRNO; failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s", - ntlm_auth, error, Curl_strerror(conn, error)); + ntlm_auth, errno, Curl_strerror(conn, errno)); goto done; } if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) { - error = ERRNO; failf(conn->data, "Could not open socket pair. errno %d: %s", - error, Curl_strerror(conn, error)); + errno, Curl_strerror(conn, errno)); goto done; } child_pid = fork(); if(child_pid == -1) { - error = ERRNO; sclose(sockfds[0]); sclose(sockfds[1]); failf(conn->data, "Could not fork. errno %d: %s", - error, Curl_strerror(conn, error)); + errno, Curl_strerror(conn, errno)); goto done; } else if(!child_pid) { @@ -176,16 +205,14 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) /* Don't use sclose in the child since it fools the socket leak detector */ sclose_nolog(sockfds[0]); if(dup2(sockfds[1], STDIN_FILENO) == -1) { - error = ERRNO; failf(conn->data, "Could not redirect child stdin. errno %d: %s", - error, Curl_strerror(conn, error)); + errno, Curl_strerror(conn, errno)); exit(1); } if(dup2(sockfds[1], STDOUT_FILENO) == -1) { - error = ERRNO; failf(conn->data, "Could not redirect child stdout. errno %d: %s", - error, Curl_strerror(conn, error)); + errno, Curl_strerror(conn, errno)); exit(1); } @@ -203,33 +230,33 @@ static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) "--username", username, NULL); - error = ERRNO; sclose_nolog(sockfds[1]); failf(conn->data, "Could not execl(). errno %d: %s", - error, Curl_strerror(conn, error)); + errno, Curl_strerror(conn, errno)); exit(1); } sclose(sockfds[1]); conn->ntlm_auth_hlpr_socket = sockfds[0]; conn->ntlm_auth_hlpr_pid = child_pid; - Curl_safefree(domain); - Curl_safefree(ntlm_auth_alloc); + free(domain); + free(ntlm_auth_alloc); return CURLE_OK; done: - Curl_safefree(domain); - Curl_safefree(ntlm_auth_alloc); + free(domain); + free(ntlm_auth_alloc); return CURLE_REMOTE_ACCESS_DENIED; } static CURLcode ntlm_wb_response(struct connectdata *conn, const char *input, curlntlm state) { - ssize_t size; - char buf[200]; /* enough, type 1, 3 message length is less then 200 */ - char *tmpbuf = buf; - size_t len_in = strlen(input), len_out = sizeof(buf); + char *buf = malloc(NTLM_BUFSIZE); + size_t len_in = strlen(input), len_out = 0; + + if(!buf) + return CURLE_OUT_OF_MEMORY; while(len_in > 0) { ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); @@ -244,8 +271,11 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, len_in -= written; } /* Read one line */ - while(len_out > 0) { - size = sread(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out); + while(1) { + ssize_t size; + char *newbuf; + + size = sread(conn->ntlm_auth_hlpr_socket, buf + len_out, NTLM_BUFSIZE); if(size == -1) { if(errno == EINTR) continue; @@ -253,22 +283,26 @@ static CURLcode ntlm_wb_response(struct connectdata *conn, } else if(size == 0) goto done; - else if(tmpbuf[size - 1] == '\n') { - tmpbuf[size - 1] = '\0'; - goto wrfinish; + + len_out += size; + if(buf[len_out - 1] == '\n') { + buf[len_out - 1] = '\0'; + break; } - tmpbuf += size; - len_out -= size; + newbuf = Curl_saferealloc(buf, len_out + NTLM_BUFSIZE); + if(!newbuf) + return CURLE_OUT_OF_MEMORY; + + buf = newbuf; } - goto done; -wrfinish: + /* Samba/winbind installed but not configured */ if(state == NTLMSTATE_TYPE1 && - size == 3 && + len_out == 3 && buf[0] == 'P' && buf[1] == 'W') - return CURLE_REMOTE_ACCESS_DENIED; + goto done; /* invalid response */ - if(size < 4) + if(len_out < 4) goto done; if(state == NTLMSTATE_TYPE1 && (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) @@ -278,9 +312,11 @@ wrfinish: (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) goto done; - conn->response_header = aprintf("NTLM %.*s", size - 4, buf + 3); + conn->response_header = aprintf("NTLM %.*s", len_out - 4, buf + 3); + free(buf); return CURLE_OK; done: + free(buf); return CURLE_REMOTE_ACCESS_DENIED; } @@ -308,7 +344,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(proxy) { allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; + userp = conn->http_proxy.user; ntlm = &conn->proxyntlm; authp = &conn->data->state.authproxy; } @@ -322,7 +358,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, /* not set means empty */ if(!userp) - userp=""; + userp = ""; switch(ntlm->state) { case NTLMSTATE_TYPE1: @@ -331,8 +367,8 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, * by delegating the NTLM challenge/response protocal to a helper * in ntlm_auth. * http://devel.squid-cache.org/ntlm/squid_helper_protocol.html - * http://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html - * http://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html + * https://www.samba.org/samba/docs/man/manpages-3/winbindd.8.html + * https://www.samba.org/samba/docs/man/manpages-3/ntlm_auth.1.html * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute * filename of ntlm_auth helper. @@ -347,16 +383,16 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(res) return res; - Curl_safefree(*allocuserpwd); + free(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: %s\r\n", proxy ? "Proxy-" : "", conn->response_header); DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); - Curl_safefree(conn->response_header); + free(conn->response_header); conn->response_header = NULL; break; case NTLMSTATE_TYPE2: - input = aprintf("TT %s", conn->challenge_header); + input = aprintf("TT %s\n", conn->challenge_header); if(!input) return CURLE_OUT_OF_MEMORY; res = ntlm_wb_response(conn, input, ntlm->state); @@ -365,7 +401,7 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, if(res) return res; - Curl_safefree(*allocuserpwd); + free(*allocuserpwd); *allocuserpwd = aprintf("%sAuthorization: %s\r\n", proxy ? "Proxy-" : "", conn->response_header); @@ -377,10 +413,8 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, case NTLMSTATE_TYPE3: /* connection is already authenticated, * don't send a header in future requests */ - if(*allocuserpwd) { - free(*allocuserpwd); - *allocuserpwd=NULL; - } + free(*allocuserpwd); + *allocuserpwd = NULL; authp->done = TRUE; break; } @@ -388,4 +422,4 @@ CURLcode Curl_output_ntlm_wb(struct connectdata *conn, return CURLE_OK; } -#endif /* USE_NTLM && NTLM_WB_ENABLED */ +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ |