Annotation of embedaddon/curl/lib/http_negotiate.c, revision 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>