From 260ee6b7bfbc4a49832a1e322d1cc5d9d3c33ddf Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sat, 27 Aug 2011 19:16:10 +0200 Subject: [PATCH] NTLM_WB: move NTLM_WB specifics into curl_ntlm_wb.[ch] --- lib/Makefile.inc | 4 +- lib/Makefile.vc6 | 1 + lib/curl_ntlm.c | 4 +- lib/curl_ntlm.h | 5 + lib/curl_ntlm_wb.c | 385 +++++++++++++++++++++++++++++ lib/curl_ntlm_wb.h | 35 +++ lib/http.c | 1 + lib/http_ntlm.c | 326 +----------------------- lib/http_ntlm.h | 18 +- lib/setup.h | 1 + packages/Symbian/group/libcurl.mmp | 2 +- 11 files changed, 443 insertions(+), 339 deletions(-) create mode 100644 lib/curl_ntlm_wb.c create mode 100644 lib/curl_ntlm_wb.h diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 147921d57..a724f605b 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -22,7 +22,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c \ curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c \ idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c \ - asyn-ares.c asyn-thread.c curl_gssapi.c curl_ntlm.c + asyn-ares.c asyn-thread.c curl_gssapi.c curl_ntlm.c curl_ntlm_wb.c HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \ progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \ @@ -38,4 +38,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \ curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \ warnless.h curl_hmac.h polarssl.h curl_rtmp.h curl_gethostname.h \ gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h \ - curl_gssapi.h + curl_gssapi.h curl_ntlm_wb.h diff --git a/lib/Makefile.vc6 b/lib/Makefile.vc6 index 4c84d2b33..cbf4b8a03 100644 --- a/lib/Makefile.vc6 +++ b/lib/Makefile.vc6 @@ -507,6 +507,7 @@ X_OBJS= \ $(DIROBJ)\curl_gethostname.obj \ $(DIROBJ)\curl_memrchr.obj \ $(DIROBJ)\curl_ntlm.obj \ + $(DIROBJ)\curl_ntlm_wb.obj \ $(DIROBJ)\curl_rand.obj \ $(DIROBJ)\curl_rtmp.obj \ $(DIROBJ)\curl_sspi.obj \ diff --git a/lib/curl_ntlm.c b/lib/curl_ntlm.c index ea8936eb3..d4f2cc20b 100644 --- a/lib/curl_ntlm.c +++ b/lib/curl_ntlm.c @@ -28,7 +28,6 @@ http://www.innovation.ch/java/ntlm.html */ -#ifndef CURL_DISABLE_HTTP #ifdef USE_NTLM #define DEBUG_ME 0 @@ -47,6 +46,8 @@ #include #endif +#define BUILDING_CURL_NTLM_C + #include "urldata.h" #include "non-ascii.h" /* for Curl_convert_... prototypes */ #include "sendf.h" @@ -1298,4 +1299,3 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, } #endif /* USE_NTLM */ -#endif /* !CURL_DISABLE_HTTP */ diff --git a/lib/curl_ntlm.h b/lib/curl_ntlm.h index ef3dfc1e4..fb6cad764 100644 --- a/lib/curl_ntlm.h +++ b/lib/curl_ntlm.h @@ -50,6 +50,9 @@ void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm); /* NTLM buffer fixed size, large enough for long user + host + domain */ #define NTLM_BUFSIZE 1024 +/* Stuff only required for curl_ntlm.c */ +#ifdef BUILDING_CURL_NTLM_C + /* Flag bits definitions based on http://davenport.sourceforge.net/ntlm.html */ #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) @@ -154,6 +157,8 @@ void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm); #define NTLMFLAG_NEGOTIATE_56 (1<<31) /* Indicates that 56-bit encryption is supported. */ +#endif /* BUILDING_CURL_NTLM_C */ + #endif /* USE_NTLM */ #endif /* HEADER_CURL_NTLM_H */ diff --git a/lib/curl_ntlm_wb.c b/lib/curl_ntlm_wb.c new file mode 100644 index 000000000..fc7e09a57 --- /dev/null +++ b/lib/curl_ntlm_wb.c @@ -0,0 +1,385 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , 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. + * + * 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 + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "setup.h" + +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) + +#define DEBUG_ME 0 + +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) +#include +#endif + +#include "urldata.h" +#include "non-ascii.h" /* for Curl_convert_... prototypes */ +#include "sendf.h" +#include "select.h" +#include "rawstr.h" +#include "curl_base64.h" +#include "curl_ntlm_wb.h" +#include "url.h" +#include "strerror.h" +#include "curl_gethostname.h" +#include "curl_memory.h" + +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +/* The last #include file should be: */ +#include "memdebug.h" + +#if DEBUG_ME +# define DEBUG_OUT(x) x +#else +# define DEBUG_OUT(x) +#endif + +void Curl_ntlm_wb_cleanup(struct connectdata *conn) +{ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { + sclose(conn->ntlm_auth_hlpr_socket); + conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; + } + + if(conn->ntlm_auth_hlpr_pid) { + int i; + for(i = 0; i < 4; i++) { + pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); + if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) + break; + switch(i) { + case 0: + kill(conn->ntlm_auth_hlpr_pid, SIGTERM); + break; + case 1: + /* Give the process another moment to shut down cleanly before + bringing down the axe */ + Curl_wait_ms(1); + break; + case 2: + kill(conn->ntlm_auth_hlpr_pid, SIGKILL); + break; + case 3: + break; + } + } + conn->ntlm_auth_hlpr_pid = 0; + } + + Curl_safefree(conn->challenge_header); + conn->challenge_header = NULL; + Curl_safefree(conn->response_header); + conn->response_header = NULL; +} + +static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) +{ + curl_socket_t sockfds[2]; + pid_t child_pid; + const char *username; + char *slash, *domain = NULL; + const char *ntlm_auth = NULL; + char *ntlm_auth_alloc = NULL; + int error; + + /* Return if communication with ntlm_auth already set up */ + if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || + conn->ntlm_auth_hlpr_pid) + return CURLE_OK; + + username = userp; + slash = strpbrk(username, "\\/"); + if(slash) { + if((domain = strdup(username)) == NULL) + return CURLE_OUT_OF_MEMORY; + slash = domain + (slash - username); + *slash = '\0'; + username = username + (slash - domain) + 1; + } + + /* For testing purposes, when DEBUGBUILD is defined and environment + variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform + NTLM challenge/response which only accepts commands and output + strings pre-written in test case definitions */ +#ifdef DEBUGBUILD + ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE"); + if(ntlm_auth_alloc) + ntlm_auth = ntlm_auth_alloc; + else +#endif + 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)); + 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)); + 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)); + goto done; + } + else if(!child_pid) { + /* + * child process + */ + + sclose(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)); + 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)); + exit(1); + } + + if(domain) + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + "--domain", domain, + NULL); + else + execl(ntlm_auth, ntlm_auth, + "--helper-protocol", "ntlmssp-client-1", + "--use-cached-creds", + "--username", username, + NULL); + + error = ERRNO; + sclose(sockfds[1]); + failf(conn->data, "Could not execl(). errno %d: %s", + error, Curl_strerror(conn, error)); + 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); + return CURLE_OK; + +done: + Curl_safefree(domain); + Curl_safefree(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); + + while(len_in > 0) { + ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); + if(written == -1) { + /* Interrupted by a signal, retry it */ + if(errno == EINTR) + continue; + /* write failed if other errors happen */ + goto done; + } + input += written; + len_in -= written; + } + /* Read one line */ + while(len_out > 0) { + size = sread(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out); + if(size == -1) { + if(errno == EINTR) + continue; + goto done; + } + else if(size == 0) + goto done; + else if(tmpbuf[size - 1] == '\n') { + tmpbuf[size - 1] = '\0'; + goto wrfinish; + } + tmpbuf += size; + len_out -= size; + } + goto done; +wrfinish: + /* Samba/winbind installed but not configured */ + if(state == NTLMSTATE_TYPE1 && + size == 3 && + buf[0] == 'P' && buf[1] == 'W') + return CURLE_REMOTE_ACCESS_DENIED; + /* invalid response */ + if(size < 4) + goto done; + if(state == NTLMSTATE_TYPE1 && + (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) + goto done; + if(state == NTLMSTATE_TYPE2 && + (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') && + (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) + goto done; + + conn->response_header = aprintf("NTLM %.*s", size - 4, buf + 3); + return CURLE_OK; +done: + return CURLE_REMOTE_ACCESS_DENIED; +} + +/* + * This is for creating ntlm header output by delegating challenge/response + * to Samba's winbind daemon helper ntlm_auth. + */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, + bool proxy) +{ + /* point to the address of the pointer that holds the string to send to the + server, which is for a plain host or for a HTTP proxy */ + char **allocuserpwd; + /* point to the name and password for this */ + const char *userp; + /* point to the correct struct with this */ + struct ntlmdata *ntlm; + struct auth *authp; + + CURLcode res = CURLE_OK; + char *input; + + DEBUGASSERT(conn); + DEBUGASSERT(conn->data); + + if(proxy) { + allocuserpwd = &conn->allocptr.proxyuserpwd; + userp = conn->proxyuser; + ntlm = &conn->proxyntlm; + authp = &conn->data->state.authproxy; + } + else { + allocuserpwd = &conn->allocptr.userpwd; + userp = conn->user; + ntlm = &conn->ntlm; + authp = &conn->data->state.authhost; + } + authp->done = FALSE; + + /* not set means empty */ + if(!userp) + userp=""; + + switch(ntlm->state) { + case NTLMSTATE_TYPE1: + default: + /* Use Samba's 'winbind' daemon to support NTLM authentication, + * 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 + * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this + * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute + * filename of ntlm_auth helper. + * If NTLM authentication using winbind fails, go back to original + * request handling process. + */ + /* Create communication with ntlm_auth */ + res = ntlm_wb_init(conn, userp); + if(res) + return res; + res = ntlm_wb_response(conn, "YR\n", ntlm->state); + if(res) + return res; + + Curl_safefree(*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); + conn->response_header = NULL; + break; + case NTLMSTATE_TYPE2: + input = aprintf("TT %s", conn->challenge_header); + if(!input) + return CURLE_OUT_OF_MEMORY; + res = ntlm_wb_response(conn, input, ntlm->state); + free(input); + input = NULL; + if(res) + return res; + + Curl_safefree(*allocuserpwd); + *allocuserpwd = aprintf("%sAuthorization: %s\r\n", + proxy ? "Proxy-" : "", + conn->response_header); + DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); + ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ + authp->done = TRUE; + Curl_ntlm_wb_cleanup(conn); + break; + case NTLMSTATE_TYPE3: + /* connection is already authenticated, + * don't send a header in future requests */ + if(*allocuserpwd) { + free(*allocuserpwd); + *allocuserpwd=NULL; + } + authp->done = TRUE; + break; + } + + return CURLE_OK; +} + +#endif /* USE_NTLM && NTLM_WB_ENABLED */ diff --git a/lib/curl_ntlm_wb.h b/lib/curl_ntlm_wb.h new file mode 100644 index 000000000..b7448a736 --- /dev/null +++ b/lib/curl_ntlm_wb.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_NTLM_WB_H +#define HEADER_CURL_NTLM_WB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , 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. + * + * 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 + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#if defined(USE_NTLM) && defined(NTLM_WB_ENABLED) + +/* this is for creating ntlm header output by delegating challenge/response + to Samba's winbind daemon helper ntlm_auth */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); + +void Curl_ntlm_wb_cleanup(struct connectdata *conn); + +#endif + +#endif /* HEADER_CURL_NTLM_WB_H */ diff --git a/lib/http.c b/lib/http.c index c1a94712e..36062d7c2 100644 --- a/lib/http.c +++ b/lib/http.c @@ -63,6 +63,7 @@ #include "sslgen.h" #include "http_digest.h" #include "http_ntlm.h" +#include "curl_ntlm_wb.h" #include "http_negotiate.h" #include "url.h" #include "share.h" diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index 8d9a8a1b5..f7defe0a8 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -28,7 +28,6 @@ http://www.innovation.ch/java/ntlm.html */ -#ifndef CURL_DISABLE_HTTP #ifdef USE_NTLM #define DEBUG_ME 0 @@ -54,6 +53,8 @@ #include "rawstr.h" #include "curl_base64.h" #include "http_ntlm.h" +#include "curl_ntlm.h" +#include "curl_ntlm_wb.h" #include "url.h" #include "strerror.h" #include "curl_gethostname.h" @@ -124,326 +125,6 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, return result; } -#ifdef NTLM_WB_ENABLED -static void ntlm_wb_cleanup(struct connectdata *conn) -{ - if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD) { - sclose(conn->ntlm_auth_hlpr_socket); - conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD; - } - - if(conn->ntlm_auth_hlpr_pid) { - int i; - for(i = 0; i < 4; i++) { - pid_t ret = waitpid(conn->ntlm_auth_hlpr_pid, NULL, WNOHANG); - if(ret == conn->ntlm_auth_hlpr_pid || errno == ECHILD) - break; - switch(i) { - case 0: - kill(conn->ntlm_auth_hlpr_pid, SIGTERM); - break; - case 1: - /* Give the process another moment to shut down cleanly before - bringing down the axe */ - Curl_wait_ms(1); - break; - case 2: - kill(conn->ntlm_auth_hlpr_pid, SIGKILL); - break; - case 3: - break; - } - } - conn->ntlm_auth_hlpr_pid = 0; - } - - Curl_safefree(conn->challenge_header); - conn->challenge_header = NULL; - Curl_safefree(conn->response_header); - conn->response_header = NULL; -} - -static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp) -{ - curl_socket_t sockfds[2]; - pid_t child_pid; - const char *username; - char *slash, *domain = NULL; - const char *ntlm_auth = NULL; - char *ntlm_auth_alloc = NULL; - int error; - - /* Return if communication with ntlm_auth already set up */ - if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD || - conn->ntlm_auth_hlpr_pid) - return CURLE_OK; - - username = userp; - slash = strpbrk(username, "\\/"); - if(slash) { - if((domain = strdup(username)) == NULL) - return CURLE_OUT_OF_MEMORY; - slash = domain + (slash - username); - *slash = '\0'; - username = username + (slash - domain) + 1; - } - - /* For testing purposes, when DEBUGBUILD is defined and environment - variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform - NTLM challenge/response which only accepts commands and output - strings pre-written in test case definitions */ -#ifdef DEBUGBUILD - ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE"); - if(ntlm_auth_alloc) - ntlm_auth = ntlm_auth_alloc; - else -#endif - 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)); - 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)); - 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)); - goto done; - } - else if(!child_pid) { - /* - * child process - */ - - sclose(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)); - 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)); - exit(1); - } - - if(domain) - execl(ntlm_auth, ntlm_auth, - "--helper-protocol", "ntlmssp-client-1", - "--use-cached-creds", - "--username", username, - "--domain", domain, - NULL); - else - execl(ntlm_auth, ntlm_auth, - "--helper-protocol", "ntlmssp-client-1", - "--use-cached-creds", - "--username", username, - NULL); - - error = ERRNO; - sclose(sockfds[1]); - failf(conn->data, "Could not execl(). errno %d: %s", - error, Curl_strerror(conn, error)); - 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); - return CURLE_OK; - -done: - Curl_safefree(domain); - Curl_safefree(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); - - while(len_in > 0) { - ssize_t written = swrite(conn->ntlm_auth_hlpr_socket, input, len_in); - if(written == -1) { - /* Interrupted by a signal, retry it */ - if(errno == EINTR) - continue; - /* write failed if other errors happen */ - goto done; - } - input += written; - len_in -= written; - } - /* Read one line */ - while(len_out > 0) { - size = sread(conn->ntlm_auth_hlpr_socket, tmpbuf, len_out); - if(size == -1) { - if(errno == EINTR) - continue; - goto done; - } - else if(size == 0) - goto done; - else if(tmpbuf[size - 1] == '\n') { - tmpbuf[size - 1] = '\0'; - goto wrfinish; - } - tmpbuf += size; - len_out -= size; - } - goto done; -wrfinish: - /* Samba/winbind installed but not configured */ - if(state == NTLMSTATE_TYPE1 && - size == 3 && - buf[0] == 'P' && buf[1] == 'W') - return CURLE_REMOTE_ACCESS_DENIED; - /* invalid response */ - if(size < 4) - goto done; - if(state == NTLMSTATE_TYPE1 && - (buf[0]!='Y' || buf[1]!='R' || buf[2]!=' ')) - goto done; - if(state == NTLMSTATE_TYPE2 && - (buf[0]!='K' || buf[1]!='K' || buf[2]!=' ') && - (buf[0]!='A' || buf[1]!='F' || buf[2]!=' ')) - goto done; - - conn->response_header = aprintf("NTLM %.*s", size - 4, buf + 3); - return CURLE_OK; -done: - return CURLE_REMOTE_ACCESS_DENIED; -} - -/* - * This is for creating ntlm header output by delegating challenge/response - * to Samba's winbind daemon helper ntlm_auth. - */ -CURLcode Curl_output_ntlm_wb(struct connectdata *conn, - bool proxy) -{ - /* point to the address of the pointer that holds the string to send to the - server, which is for a plain host or for a HTTP proxy */ - char **allocuserpwd; - /* point to the name and password for this */ - const char *userp; - /* point to the correct struct with this */ - struct ntlmdata *ntlm; - struct auth *authp; - - CURLcode res = CURLE_OK; - char *input; - - DEBUGASSERT(conn); - DEBUGASSERT(conn->data); - - if(proxy) { - allocuserpwd = &conn->allocptr.proxyuserpwd; - userp = conn->proxyuser; - ntlm = &conn->proxyntlm; - authp = &conn->data->state.authproxy; - } - else { - allocuserpwd = &conn->allocptr.userpwd; - userp = conn->user; - ntlm = &conn->ntlm; - authp = &conn->data->state.authhost; - } - authp->done = FALSE; - - /* not set means empty */ - if(!userp) - userp=""; - - switch(ntlm->state) { - case NTLMSTATE_TYPE1: - default: - /* Use Samba's 'winbind' daemon to support NTLM authentication, - * 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 - * Preprocessor symbol 'NTLM_WB_ENABLED' is defined when this - * feature is enabled and 'NTLM_WB_FILE' symbol holds absolute - * filename of ntlm_auth helper. - * If NTLM authentication using winbind fails, go back to original - * request handling process. - */ - /* Create communication with ntlm_auth */ - res = ntlm_wb_init(conn, userp); - if(res) - return res; - res = ntlm_wb_response(conn, "YR\n", ntlm->state); - if(res) - return res; - - Curl_safefree(*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); - conn->response_header = NULL; - break; - case NTLMSTATE_TYPE2: - input = aprintf("TT %s", conn->challenge_header); - if(!input) - return CURLE_OUT_OF_MEMORY; - res = ntlm_wb_response(conn, input, ntlm->state); - free(input); - input = NULL; - if(res) - return res; - - Curl_safefree(*allocuserpwd); - *allocuserpwd = aprintf("%sAuthorization: %s\r\n", - proxy ? "Proxy-" : "", - conn->response_header); - DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); - ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ - authp->done = TRUE; - ntlm_wb_cleanup(conn); - break; - case NTLMSTATE_TYPE3: - /* connection is already authenticated, - * don't send a header in future requests */ - if(*allocuserpwd) { - free(*allocuserpwd); - *allocuserpwd=NULL; - } - authp->done = TRUE; - break; - } - - return CURLE_OK; -} -#endif /* NTLM_WB_ENABLED */ - /* * This is for creating ntlm header output */ @@ -563,11 +244,10 @@ void Curl_http_ntlm_cleanup(struct connectdata *conn) Curl_ntlm_sspi_cleanup(&conn->ntlm); Curl_ntlm_sspi_cleanup(&conn->proxyntlm); #elif defined(NTLM_WB_ENABLED) - ntlm_wb_cleanup(conn); + Curl_ntlm_wb_cleanup(conn); #else (void)conn; #endif } #endif /* USE_NTLM */ -#endif /* !CURL_DISABLE_HTTP */ diff --git a/lib/http_ntlm.h b/lib/http_ntlm.h index 635d6313b..a074380a3 100644 --- a/lib/http_ntlm.h +++ b/lib/http_ntlm.h @@ -22,6 +22,8 @@ * ***************************************************************************/ +#ifdef USE_NTLM + /* this is for ntlm header input */ CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, const char *header); @@ -29,18 +31,12 @@ CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, /* this is for creating ntlm header output */ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); -#ifdef NTLM_WB_ENABLED -/* this is for creating ntlm header output by delegating challenge/response - to Samba's winbind daemon helper ntlm_auth */ -CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); -#endif - -#ifdef USE_NTLM void Curl_http_ntlm_cleanup(struct connectdata *conn); -#else -#define Curl_http_ntlm_cleanup(x) -#endif -#include "curl_ntlm.h" +#else + +#define Curl_http_ntlm_cleanup(a) + +#endif #endif /* HEADER_CURL_HTTP_NTLM_H */ diff --git a/lib/setup.h b/lib/setup.h index f90cf8f31..c821bc6b4 100644 --- a/lib/setup.h +++ b/lib/setup.h @@ -568,6 +568,7 @@ int netware_init(void); #define USE_HTTP_NEGOTIATE #endif +/* Single point where USE_NTLM definition might be done */ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_NTLM) #if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \ defined(USE_GNUTLS) || defined(USE_NSS) diff --git a/packages/Symbian/group/libcurl.mmp b/packages/Symbian/group/libcurl.mmp index 8793892d0..1420ce886 100644 --- a/packages/Symbian/group/libcurl.mmp +++ b/packages/Symbian/group/libcurl.mmp @@ -36,7 +36,7 @@ SOURCE \ pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c \ curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c \ idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c \ - asyn-ares.c asyn-thread.c curl_ntlm.c + asyn-ares.c asyn-thread.c curl_ntlm.c curl_ntlm_wb.c USERINCLUDE ../../../lib ../../../include/curl #ifdef ENABLE_SSL