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>