diff options
author | Yang Tse <yangsita@gmail.com> | 2011-08-27 19:16:10 +0200 |
---|---|---|
committer | Yang Tse <yangsita@gmail.com> | 2011-08-27 19:16:10 +0200 |
commit | 260ee6b7bfbc4a49832a1e322d1cc5d9d3c33ddf (patch) | |
tree | 41df8db943b4c899ec09a8806f6a9d55c3896905 /lib/http_ntlm.c | |
parent | b976d108f1beecff743f912f190ffc89f1ef9098 (diff) | |
download | curl-260ee6b7bfbc4a49832a1e322d1cc5d9d3c33ddf.tar.gz |
NTLM_WB: move NTLM_WB specifics into curl_ntlm_wb.[ch]
Diffstat (limited to 'lib/http_ntlm.c')
-rw-r--r-- | lib/http_ntlm.c | 326 |
1 files changed, 3 insertions, 323 deletions
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 */ |