1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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 "rawstr.h" 30 #include "http_negotiate.h" 31 #include "vauth/vauth.h" 32 33 /* The last 3 #include files should be in this order */ 34 #include "curl_printf.h" 35 #include "curl_memory.h" 36 #include "memdebug.h" 37 38 CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, 39 const char *header) 40 { 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->proxyuser; 55 passwdp = conn->proxypasswd; 56 service = data->set.str[STRING_PROXY_SERVICE_NAME] ? 57 data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; 58 host = conn->proxy.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 return Curl_auth_decode_spnego_message(data, userp, passwdp, service, host, 94 header, neg_ctx); 95 } 96 97 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) 98 { 99 struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg : 100 &conn->data->state.negotiate; 101 char *base64 = NULL; 102 size_t len = 0; 103 char *userp; 104 CURLcode result; 105 106 result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len); 107 if(result) 108 return result; 109 110 userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "", 111 base64); 112 113 if(proxy) { 114 Curl_safefree(conn->allocptr.proxyuserpwd); 115 conn->allocptr.proxyuserpwd = userp; 116 } 117 else { 118 Curl_safefree(conn->allocptr.userpwd); 119 conn->allocptr.userpwd = userp; 120 } 121 122 free(base64); 123 124 return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; 125 } 126 127 void Curl_cleanup_negotiate(struct Curl_easy *data) 128 { 129 Curl_auth_spnego_cleanup(&data->state.negotiate); 130 Curl_auth_spnego_cleanup(&data->state.proxyneg); 131 } 132 133 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */ 134