18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: http_negotiate.c,v 1.21 2007-09-21 11:05:31 bagder Exp $
21
* $Id: http_negotiate.c,v 1.24 2007-11-20 23:17:08 bagder Exp $
22
22
***************************************************************************/
52
52
get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
54
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
54
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
55
&conn->data->state.negotiate;
55
56
OM_uint32 major_status, minor_status;
56
57
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
65
66
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
72
token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : conn->host.name) + 1;
73
if (token.length + 1 > sizeof(name))
73
token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
75
if(token.length + 1 > sizeof(name))
76
snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : conn->host.name);
78
snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name :
78
81
token.value = (void *) name;
79
82
major_status = gss_import_name(&minor_status,
96
99
snprintf(buf, sizeof(buf), "%s", prefix);
97
100
len = strlen(buf);
99
maj_stat = gss_display_status (&min_stat,
105
if (sizeof(buf) > len + status_string.length + 1) {
102
maj_stat = gss_display_status(&min_stat,
108
if(sizeof(buf) > len + status_string.length + 1) {
106
109
snprintf(buf + len, sizeof(buf) - len,
107
110
": %s", (char*) status_string.value);
108
111
len += status_string.length;
110
113
gss_release_buffer(&min_stat, &status_string);
111
} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
114
} while(!GSS_ERROR(maj_stat) && msg_ctx != 0);
113
116
infof(conn->data, "%s", buf);
116
int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header)
119
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
118
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
122
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
123
&conn->data->state.negotiate;
119
124
OM_uint32 major_status, minor_status, minor_status2;
120
125
gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
121
126
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
130
135
protocol = "GSS-Negotiate";
133
else if (checkprefix("Negotiate", header)) {
138
else if(checkprefix("Negotiate", header)) {
134
139
protocol = "Negotiate";
140
if (neg_ctx->context) {
141
if (neg_ctx->gss != gss) {
145
if(neg_ctx->context) {
146
if(neg_ctx->gss != gss) {
147
152
neg_ctx->gss = gss;
150
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
155
if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
151
156
/* We finished succesfully our part of authentication, but server
152
157
* rejected it (since we're again here). Exit with an error since we
153
158
* can't invent anything better */
166
171
len = strlen(header);
168
int rawlen = Curl_base64_decode(header, (unsigned char **)&input_token.value);
173
int rawlen = Curl_base64_decode(header,
174
(unsigned char **)&input_token.value);
171
177
input_token.length = rawlen;
173
179
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
174
if (checkprefix("Negotiate", header)) {
180
if(checkprefix("Negotiate", header)) {
175
181
ASN1_OBJECT * object = NULL;
177
183
unsigned char * spnegoToken = NULL;
180
186
size_t mechTokenLength = 0;
182
188
spnegoToken = malloc(input_token.length);
183
if (input_token.value == NULL)
189
if(input_token.value == NULL)
185
191
spnegoTokenLength = input_token.length;
187
193
object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
188
if (!parseSpnegoTargetToken(spnegoToken,
194
if(!parseSpnegoTargetToken(spnegoToken,
189
195
spnegoTokenLength,
227
if (input_token.length > 0)
233
if(input_token.length > 0)
228
234
gss_release_buffer(&minor_status2, &input_token);
229
235
neg_ctx->status = major_status;
230
if (GSS_ERROR(major_status)) {
236
if(GSS_ERROR(major_status)) {
231
237
/* Curl_cleanup_negotiate(conn->data) ??? */
232
238
log_gss_error(conn, minor_status,
233
239
(char *)"gss_init_sec_context() failed: ");
237
if (output_token.length == 0) {
243
if(output_token.length == 0) {
248
254
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
250
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
256
struct negotiatedata *neg_ctx = proxy?&conn->data->state.proxyneg:
257
&conn->data->state.negotiate;
251
258
OM_uint32 minor_status;
252
259
char *encoded = NULL;
255
262
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
256
if (checkprefix("Negotiate",neg_ctx->protocol)) {
263
if(checkprefix("Negotiate", neg_ctx->protocol)) {
257
264
ASN1_OBJECT * object = NULL;
259
266
unsigned char * spnegoToken = NULL;
262
269
size_t responseTokenLength = 0;
264
271
responseToken = malloc(neg_ctx->output_token.length);
265
if ( responseToken == NULL)
272
if( responseToken == NULL)
266
273
return CURLE_OUT_OF_MEMORY;
267
274
memcpy(responseToken, neg_ctx->output_token.value,
268
275
neg_ctx->output_token.length);
269
276
responseTokenLength = neg_ctx->output_token.length;
271
278
object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
272
if (!makeSpnegoInitialToken (object,
279
if(!makeSpnegoInitialToken (object,
274
281
responseTokenLength,
295
302
neg_ctx->output_token.length,
299
306
return CURLE_OUT_OF_MEMORY;
301
308
conn->allocptr.userpwd =
302
aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", neg_ctx->protocol, encoded);
309
aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "",
310
neg_ctx->protocol, encoded);
304
312
gss_release_buffer(&minor_status, &neg_ctx->output_token);
305
313
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
308
void Curl_cleanup_negotiate(struct SessionHandle *data)
316
static void cleanup(struct negotiatedata *neg_ctx)
310
318
OM_uint32 minor_status;
311
struct negotiatedata *neg_ctx = &data->state.negotiate;
313
if (neg_ctx->context != GSS_C_NO_CONTEXT)
319
if(neg_ctx->context != GSS_C_NO_CONTEXT)
314
320
gss_delete_sec_context(&minor_status, &neg_ctx->context, GSS_C_NO_BUFFER);
316
if (neg_ctx->output_token.length != 0)
322
if(neg_ctx->output_token.length != 0)
317
323
gss_release_buffer(&minor_status, &neg_ctx->output_token);
319
if (neg_ctx->server_name != GSS_C_NO_NAME)
325
if(neg_ctx->server_name != GSS_C_NO_NAME)
320
326
gss_release_name(&minor_status, &neg_ctx->server_name);
322
328
memset(neg_ctx, 0, sizeof(*neg_ctx));
331
void Curl_cleanup_negotiate(struct SessionHandle *data)
333
cleanup(&data->state.negotiate);
334
cleanup(&data->state.proxyneg);