~ubuntu-branches/ubuntu/lucid/curl/lucid-201101212007

« back to all changes in this revision

Viewing changes to lib/http_negotiate.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2008-02-08 11:20:41 UTC
  • mto: (3.1.1 lenny) (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20080208112041-hed7sb5r6ghmjf8v
Tags: upstream-7.18.0
ImportĀ upstreamĀ versionĀ 7.18.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
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
 ***************************************************************************/
23
23
#include "setup.h"
24
24
 
51
51
static int
52
52
get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
53
53
{
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;
57
58
  char name[2048];
64
65
 
65
66
  /* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
66
67
 
67
 
  if (neg_ctx->gss)
 
68
  if(neg_ctx->gss)
68
69
    service = "KHTTP";
69
70
  else
70
71
    service = "HTTP";
71
72
 
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 :
 
74
                                              conn->host.name) + 1;
 
75
  if(token.length + 1 > sizeof(name))
74
76
    return EMSGSIZE;
75
77
 
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 :
 
79
           conn->host.name);
77
80
 
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);
98
101
  do {
99
 
    maj_stat = gss_display_status (&min_stat,
100
 
                                   error_status,
101
 
                                   GSS_C_MECH_CODE,
102
 
                                   GSS_C_NO_OID,
103
 
                                   &msg_ctx,
104
 
                                   &status_string);
105
 
      if (sizeof(buf) > len + status_string.length + 1) {
 
102
    maj_stat = gss_display_status(&min_stat,
 
103
                                  error_status,
 
104
                                  GSS_C_MECH_CODE,
 
105
                                  GSS_C_NO_OID,
 
106
                                  &msg_ctx,
 
107
                                  &status_string);
 
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;
109
112
    }
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);
112
115
 
113
116
  infof(conn->data, "%s", buf);
114
117
}
115
118
 
116
 
int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header)
 
119
int Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
120
                         const char *header)
117
121
{
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";
131
136
    gss = TRUE;
132
137
  }
133
 
  else if (checkprefix("Negotiate", header)) {
 
138
  else if(checkprefix("Negotiate", header)) {
134
139
    protocol = "Negotiate";
135
140
    gss = FALSE;
136
141
  }
137
142
  else
138
143
    return -1;
139
144
 
140
 
  if (neg_ctx->context) {
141
 
    if (neg_ctx->gss != gss) {
 
145
  if(neg_ctx->context) {
 
146
    if(neg_ctx->gss != gss) {
142
147
      return -1;
143
148
    }
144
149
  }
147
152
    neg_ctx->gss = gss;
148
153
  }
149
154
 
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 */
155
160
    return -1;
156
161
  }
157
162
 
158
 
  if (neg_ctx->server_name == NULL &&
 
163
  if(neg_ctx->server_name == NULL &&
159
164
      (ret = get_gss_name(conn, proxy, &neg_ctx->server_name)))
160
165
    return ret;
161
166
 
164
169
    header++;
165
170
 
166
171
  len = strlen(header);
167
 
  if (len > 0) {
168
 
    int rawlen = Curl_base64_decode(header, (unsigned char **)&input_token.value);
169
 
    if (rawlen < 0)
 
172
  if(len > 0) {
 
173
    int rawlen = Curl_base64_decode(header,
 
174
                                    (unsigned char **)&input_token.value);
 
175
    if(rawlen < 0)
170
176
      return -1;
171
177
    input_token.length = rawlen;
172
178
 
173
179
#ifdef HAVE_SPNEGO /* Handle SPNEGO */
174
 
    if (checkprefix("Negotiate", header)) {
 
180
    if(checkprefix("Negotiate", header)) {
175
181
        ASN1_OBJECT *   object            = NULL;
176
182
        int             rc                = 1;
177
183
        unsigned char * spnegoToken       = NULL;
180
186
        size_t          mechTokenLength   = 0;
181
187
 
182
188
        spnegoToken = malloc(input_token.length);
183
 
        if (input_token.value == NULL)
 
189
        if(input_token.value == NULL)
184
190
          return ENOMEM;
185
191
        spnegoTokenLength = input_token.length;
186
192
 
187
193
        object = OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
188
 
        if (!parseSpnegoTargetToken(spnegoToken,
 
194
        if(!parseSpnegoTargetToken(spnegoToken,
189
195
                                    spnegoTokenLength,
190
196
                                    NULL,
191
197
                                    NULL,
224
230
                                      &output_token,
225
231
                                      NULL,
226
232
                                      NULL);
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: ");
234
240
    return -1;
235
241
  }
236
242
 
237
 
  if (output_token.length == 0) {
 
243
  if(output_token.length == 0) {
238
244
    return -1;
239
245
  }
240
246
 
247
253
 
248
254
CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
249
255
{
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;
253
260
  int len;
254
261
 
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;
258
265
    int             rc                = 1;
259
266
    unsigned char * spnegoToken       = NULL;
262
269
    size_t          responseTokenLength = 0;
263
270
 
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;
270
277
 
271
278
    object=OBJ_txt2obj ("1.2.840.113554.1.2.2", 1);
272
 
    if (!makeSpnegoInitialToken (object,
 
279
    if(!makeSpnegoInitialToken (object,
273
280
                                 responseToken,
274
281
                                 responseTokenLength,
275
282
                                 &spnegoToken,
295
302
                           neg_ctx->output_token.length,
296
303
                           &encoded);
297
304
 
298
 
  if (len == 0)
 
305
  if(len == 0)
299
306
    return CURLE_OUT_OF_MEMORY;
300
307
 
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);
303
311
  free(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;
306
314
}
307
315
 
308
 
void Curl_cleanup_negotiate(struct SessionHandle *data)
 
316
static void cleanup(struct negotiatedata *neg_ctx)
309
317
{
310
318
  OM_uint32 minor_status;
311
 
  struct negotiatedata *neg_ctx = &data->state.negotiate;
312
 
 
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);
315
321
 
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);
318
324
 
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);
321
327
 
322
328
  memset(neg_ctx, 0, sizeof(*neg_ctx));
323
329
}
324
330
 
 
331
void Curl_cleanup_negotiate(struct SessionHandle *data)
 
332
{
 
333
  cleanup(&data->state.negotiate);
 
334
  cleanup(&data->state.proxyneg);
 
335
}
 
336
 
325
337
 
326
338
#endif
327
339
#endif