1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, 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 53 if(proxy) { 54 userp = conn->http_proxy.user; 55 passwdp = conn->http_proxy.passwd; 56 service = data->set.str[STRING_PROXY_SERVICE_NAME] ? 57 data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; 58 host = conn->http_proxy.host.name; 59 neg_ctx = &data->state.proxyneg; 60 } 61 else { 62 userp = conn->user; 63 passwdp = conn->passwd; 64 service = data->set.str[STRING_SERVICE_NAME] ? 65 data->set.str[STRING_SERVICE_NAME] : "HTTP"; 66 host = conn->host.name; 67 neg_ctx = &data->state.negotiate; 68 } 69 70 /* Not set means empty */ 71 if(!userp) 72 userp = ""; 73 74 if(!passwdp) 75 passwdp = ""; 76 77 /* Obtain the input token, if any */ 78 header += strlen("Negotiate"); 79 while(*header && ISSPACE(*header)) 80 header++; 81 82 len = strlen(header); 83 if(!len) { 84 /* Is this the first call in a new negotiation? */ 85 if(neg_ctx->context) { 86 /* The server rejected our authentication and hasn't suppled any more 87 negotiation mechanisms */ 88 return CURLE_LOGIN_DENIED; 89 } 90 } 91 92 /* Initilise the security context and decode our challenge */ 93 result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, 94 host, header, neg_ctx); 95 96 if(result) 97 Curl_auth_spnego_cleanup(neg_ctx); 98 99 return result; 100 } 101 102 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) 103 { 104 struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg : 105 &conn->data->state.negotiate; 106 char *base64 = NULL; 107 size_t len = 0; 108 char *userp; 109 CURLcode result; 110 111 result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len); 112 if(result) 113 return result; 114 115 userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", 116 base64); 117 118 if(proxy) { 119 Curl_safefree(conn->allocptr.proxyuserpwd); 120 conn->allocptr.proxyuserpwd = userp; 121 } 122 else { 123 Curl_safefree(conn->allocptr.userpwd); 124 conn->allocptr.userpwd = userp; 125 } 126 127 free(base64); 128 129 return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; 130 } 131 132 void Curl_cleanup_negotiate(struct Curl_easy *data) 133 { 134 Curl_auth_spnego_cleanup(&data->state.negotiate); 135 Curl_auth_spnego_cleanup(&data->state.proxyneg); 136 } 137 138 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ 139