Annotation of embedaddon/curl/lib/http_negotiate.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_SPNEGO)
26:
27: #include "urldata.h"
28: #include "sendf.h"
29: #include "http_negotiate.h"
30: #include "vauth/vauth.h"
31:
32: /* The last 3 #include files should be in this order */
33: #include "curl_printf.h"
34: #include "curl_memory.h"
35: #include "memdebug.h"
36:
37: CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
38: const char *header)
39: {
40: CURLcode result;
41: struct Curl_easy *data = conn->data;
42: size_t len;
43:
44: /* Point to the username, password, service and host */
45: const char *userp;
46: const char *passwdp;
47: const char *service;
48: const char *host;
49:
50: /* Point to the correct struct with this */
51: struct negotiatedata *neg_ctx;
52: curlnegotiate state;
53:
54: if(proxy) {
55: userp = conn->http_proxy.user;
56: passwdp = conn->http_proxy.passwd;
57: service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
58: data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
59: host = conn->http_proxy.host.name;
60: neg_ctx = &conn->proxyneg;
61: state = conn->proxy_negotiate_state;
62: }
63: else {
64: userp = conn->user;
65: passwdp = conn->passwd;
66: service = data->set.str[STRING_SERVICE_NAME] ?
67: data->set.str[STRING_SERVICE_NAME] : "HTTP";
68: host = conn->host.name;
69: neg_ctx = &conn->negotiate;
70: state = conn->http_negotiate_state;
71: }
72:
73: /* Not set means empty */
74: if(!userp)
75: userp = "";
76:
77: if(!passwdp)
78: passwdp = "";
79:
80: /* Obtain the input token, if any */
81: header += strlen("Negotiate");
82: while(*header && ISSPACE(*header))
83: header++;
84:
85: len = strlen(header);
86: neg_ctx->havenegdata = len != 0;
87: if(!len) {
88: if(state == GSS_AUTHSUCC) {
89: infof(conn->data, "Negotiate auth restarted\n");
90: Curl_http_auth_cleanup_negotiate(conn);
91: }
92: else if(state != GSS_AUTHNONE) {
93: /* The server rejected our authentication and hasn't supplied any more
94: negotiation mechanisms */
95: Curl_http_auth_cleanup_negotiate(conn);
96: return CURLE_LOGIN_DENIED;
97: }
98: }
99:
100: /* Supports SSL channel binding for Windows ISS extended protection */
101: #if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
102: neg_ctx->sslContext = conn->sslContext;
103: #endif
104:
105: /* Initialize the security context and decode our challenge */
106: result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
107: host, header, neg_ctx);
108:
109: if(result)
110: Curl_http_auth_cleanup_negotiate(conn);
111:
112: return result;
113: }
114:
115: CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
116: {
117: struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
118: &conn->negotiate;
119: struct auth *authp = proxy ? &conn->data->state.authproxy :
120: &conn->data->state.authhost;
121: curlnegotiate *state = proxy ? &conn->proxy_negotiate_state :
122: &conn->http_negotiate_state;
123: char *base64 = NULL;
124: size_t len = 0;
125: char *userp;
126: CURLcode result;
127:
128: authp->done = FALSE;
129:
130: if(*state == GSS_AUTHRECV) {
131: if(neg_ctx->havenegdata) {
132: neg_ctx->havemultiplerequests = TRUE;
133: }
134: }
135: else if(*state == GSS_AUTHSUCC) {
136: if(!neg_ctx->havenoauthpersist) {
137: neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests;
138: }
139: }
140:
141: if(neg_ctx->noauthpersist ||
142: (*state != GSS_AUTHDONE && *state != GSS_AUTHSUCC)) {
143:
144: if(neg_ctx->noauthpersist && *state == GSS_AUTHSUCC) {
145: infof(conn->data, "Curl_output_negotiate, "
146: "no persistent authentication: cleanup existing context");
147: Curl_http_auth_cleanup_negotiate(conn);
148: }
149: if(!neg_ctx->context) {
150: result = Curl_input_negotiate(conn, proxy, "Negotiate");
151: if(result == CURLE_AUTH_ERROR) {
152: /* negotiate auth failed, let's continue unauthenticated to stay
153: * compatible with the behavior before curl-7_64_0-158-g6c6035532 */
154: authp->done = TRUE;
155: return CURLE_OK;
156: }
157: else if(result)
158: return result;
159: }
160:
161: result = Curl_auth_create_spnego_message(conn->data,
162: neg_ctx, &base64, &len);
163: if(result)
164: return result;
165:
166: userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
167: base64);
168:
169: if(proxy) {
170: Curl_safefree(conn->allocptr.proxyuserpwd);
171: conn->allocptr.proxyuserpwd = userp;
172: }
173: else {
174: Curl_safefree(conn->allocptr.userpwd);
175: conn->allocptr.userpwd = userp;
176: }
177:
178: free(base64);
179:
180: if(userp == NULL) {
181: return CURLE_OUT_OF_MEMORY;
182: }
183:
184: *state = GSS_AUTHSENT;
185: #ifdef HAVE_GSSAPI
186: if(neg_ctx->status == GSS_S_COMPLETE ||
187: neg_ctx->status == GSS_S_CONTINUE_NEEDED) {
188: *state = GSS_AUTHDONE;
189: }
190: #else
191: #ifdef USE_WINDOWS_SSPI
192: if(neg_ctx->status == SEC_E_OK ||
193: neg_ctx->status == SEC_I_CONTINUE_NEEDED) {
194: *state = GSS_AUTHDONE;
195: }
196: #endif
197: #endif
198: }
199:
200: if(*state == GSS_AUTHDONE || *state == GSS_AUTHSUCC) {
201: /* connection is already authenticated,
202: * don't send a header in future requests */
203: authp->done = TRUE;
204: }
205:
206: neg_ctx->havenegdata = FALSE;
207:
208: return CURLE_OK;
209: }
210:
211: void Curl_http_auth_cleanup_negotiate(struct connectdata *conn)
212: {
213: conn->http_negotiate_state = GSS_AUTHNONE;
214: conn->proxy_negotiate_state = GSS_AUTHNONE;
215:
216: Curl_auth_cleanup_spnego(&conn->negotiate);
217: Curl_auth_cleanup_spnego(&conn->proxyneg);
218: }
219:
220: #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>