Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "curl_setup.h"
00026
00027 #if defined(HAVE_GSSAPI) && defined(USE_SPNEGO)
00028
00029 #include <curl/curl.h>
00030
00031 #include "vauth/vauth.h"
00032 #include "urldata.h"
00033 #include "curl_base64.h"
00034 #include "curl_gssapi.h"
00035 #include "warnless.h"
00036 #include "curl_multibyte.h"
00037 #include "sendf.h"
00038
00039
00040 #include "curl_memory.h"
00041 #include "memdebug.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 bool Curl_auth_is_spnego_supported(void)
00053 {
00054 return TRUE;
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
00076 const char *user,
00077 const char *password,
00078 const char *service,
00079 const char *host,
00080 const char *chlg64,
00081 struct negotiatedata *nego)
00082 {
00083 CURLcode result = CURLE_OK;
00084 size_t chlglen = 0;
00085 unsigned char *chlg = NULL;
00086 OM_uint32 major_status;
00087 OM_uint32 minor_status;
00088 OM_uint32 unused_status;
00089 gss_buffer_desc spn_token = GSS_C_EMPTY_BUFFER;
00090 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
00091 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
00092
00093 (void) user;
00094 (void) password;
00095
00096 if(nego->context && nego->status == GSS_S_COMPLETE) {
00097
00098
00099
00100 Curl_auth_spnego_cleanup(nego);
00101 return CURLE_LOGIN_DENIED;
00102 }
00103
00104 if(!nego->spn) {
00105
00106 char *spn = Curl_auth_build_spn(service, NULL, host);
00107 if(!spn)
00108 return CURLE_OUT_OF_MEMORY;
00109
00110
00111 spn_token.value = spn;
00112 spn_token.length = strlen(spn);
00113
00114
00115 major_status = gss_import_name(&minor_status, &spn_token,
00116 GSS_C_NT_HOSTBASED_SERVICE,
00117 &nego->spn);
00118 if(GSS_ERROR(major_status)) {
00119 Curl_gss_log_error(data, "gss_import_name() failed: ",
00120 major_status, minor_status);
00121
00122 free(spn);
00123
00124 return CURLE_OUT_OF_MEMORY;
00125 }
00126
00127 free(spn);
00128 }
00129
00130 if(chlg64 && *chlg64) {
00131
00132 if(*chlg64 != '=') {
00133 result = Curl_base64_decode(chlg64, &chlg, &chlglen);
00134 if(result)
00135 return result;
00136 }
00137
00138
00139 if(!chlg) {
00140 infof(data, "SPNEGO handshake failure (empty challenge message)\n");
00141
00142 return CURLE_BAD_CONTENT_ENCODING;
00143 }
00144
00145
00146 input_token.value = chlg;
00147 input_token.length = chlglen;
00148 }
00149
00150
00151 major_status = Curl_gss_init_sec_context(data,
00152 &minor_status,
00153 &nego->context,
00154 nego->spn,
00155 &Curl_spnego_mech_oid,
00156 GSS_C_NO_CHANNEL_BINDINGS,
00157 &input_token,
00158 &output_token,
00159 TRUE,
00160 NULL);
00161
00162
00163 Curl_safefree(input_token.value);
00164
00165 nego->status = major_status;
00166 if(GSS_ERROR(major_status)) {
00167 if(output_token.value)
00168 gss_release_buffer(&unused_status, &output_token);
00169
00170 Curl_gss_log_error(data, "gss_init_sec_context() failed: ",
00171 major_status, minor_status);
00172
00173 return CURLE_OUT_OF_MEMORY;
00174 }
00175
00176 if(!output_token.value || !output_token.length) {
00177 if(output_token.value)
00178 gss_release_buffer(&unused_status, &output_token);
00179
00180 return CURLE_OUT_OF_MEMORY;
00181 }
00182
00183 nego->output_token = output_token;
00184
00185 return CURLE_OK;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data,
00205 struct negotiatedata *nego,
00206 char **outptr, size_t *outlen)
00207 {
00208 CURLcode result;
00209 OM_uint32 minor_status;
00210
00211
00212 result = Curl_base64_encode(data,
00213 nego->output_token.value,
00214 nego->output_token.length,
00215 outptr, outlen);
00216
00217 if(result) {
00218 gss_release_buffer(&minor_status, &nego->output_token);
00219 nego->output_token.value = NULL;
00220 nego->output_token.length = 0;
00221
00222 return result;
00223 }
00224
00225 if(!*outptr || !*outlen) {
00226 gss_release_buffer(&minor_status, &nego->output_token);
00227 nego->output_token.value = NULL;
00228 nego->output_token.length = 0;
00229
00230 return CURLE_REMOTE_ACCESS_DENIED;
00231 }
00232
00233 return CURLE_OK;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
00247 {
00248 OM_uint32 minor_status;
00249
00250
00251 if(nego->context != GSS_C_NO_CONTEXT) {
00252 gss_delete_sec_context(&minor_status, &nego->context, GSS_C_NO_BUFFER);
00253 nego->context = GSS_C_NO_CONTEXT;
00254 }
00255
00256
00257 if(nego->output_token.value) {
00258 gss_release_buffer(&minor_status, &nego->output_token);
00259 nego->output_token.value = NULL;
00260 nego->output_token.length = 0;
00261
00262 }
00263
00264
00265 if(nego->spn != GSS_C_NO_NAME) {
00266 gss_release_name(&minor_status, &nego->spn);
00267 nego->spn = GSS_C_NO_NAME;
00268 }
00269
00270
00271 nego->status = 0;
00272 }
00273
00274 #endif