2
* Copyright 1999-2006 University of Chicago
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
20
* @author Sam Lang, Sam Meder
22
* $RCSfile: init.c,v $
24
* $Date: 2007/08/09 14:24:23 $
28
#include "globus_i_gss_assist.h"
31
extern gss_OID gss_nt_service_name;
34
* @name Init Security Context
38
* @ingroup globus_gsi_gss_assist
39
* Initialize a gssapi security connection. Used by the client.
40
* The context_handle is returned, and there is one for each
41
* connection. This routine will take cake of the looping
42
* and token processing, using the supplied get_token and
43
* send_token routines.
46
* GSSAPI return code. The new minor_status is a globus_result_t
47
* cast to an OM_uint32. If the call was successful, the minor
48
* status is equivalant to GLOBUS_SUCCESS. Otherwise, it is a
49
* globus error object ID that can be passed to globus_error_get
50
* to get the error object. The error object needs to be freed
51
* with globus_object_free.
52
* @param initiator_cred_handle
53
* the cred handle obtained by acquire_cred.
54
* @param context_handle
55
* pointer to returned context.
56
* @param target_name_char
57
* char string repersentation of the
58
* server to be contacted.
60
* request flags, such as GSS_C_DELEG_FLAG for delegation
61
* and the GSS_C_MUTUAL_FLAG for mutual authentication.
63
* Pointer to which services are available after
64
* the connection is established. Maybe NULL if not wanted.
66
* The Follwing are particular to this assist routine:
69
* the assist routine's get/send token status
70
* @param gss_assist_get_token
71
* function pointer for getting the token
72
* @param gss_assist_get_context
73
* first argument passed to the
74
* gss_assist_get_token function
75
* @param gss_assist_set_token
76
* function pointer for setting the token
77
* @param gss_assist_set_context
78
* first argument passed to the
79
* gss_assist_set_token function pointer
85
globus_gss_assist_init_sec_context(
86
OM_uint32 * minor_status,
87
const gss_cred_id_t cred_handle,
88
gss_ctx_id_t * context_handle,
89
char * target_name_char,
91
OM_uint32 * ret_flags,
93
int (*gss_assist_get_token)(void *, void **, size_t *),
94
void * gss_assist_get_context,
95
int (*gss_assist_send_token)(void *, void *, size_t),
96
void * gss_assist_send_context)
98
int context_established = 0;
99
OM_uint32 major_status = GSS_S_COMPLETE;
100
OM_uint32 minor_status1 = 0;
101
OM_uint32 minor_status2 = 0;
102
gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER;
103
gss_buffer_t input_token = &input_token_desc;
104
gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER;
105
gss_buffer_t output_token = &output_token_desc;
106
gss_name_t target_name = GSS_C_NO_NAME;
107
gss_OID target_name_type = GSS_C_NO_OID;
108
gss_OID mech_type = GSS_C_NO_OID;
109
OM_uint32 time_req = 0;
110
OM_uint32 time_rec = 0;
111
gss_channel_bindings_t input_chan_bindings =
112
GSS_C_NO_CHANNEL_BINDINGS;
113
gss_OID * actual_mech_type = NULL;
114
gss_buffer_desc tmp_buffer_desc = GSS_C_EMPTY_BUFFER;
115
gss_buffer_t tmp_buffer = &tmp_buffer_desc;
116
globus_result_t result = GLOBUS_SUCCESS;
117
static char * _function_name_ =
118
"globus_gss_assist_init_sec_context";
119
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER;
122
* should not set context_handle to NULL since it may have been
123
* allocated by a call to set_sec_context_option
126
/* *context_handle = GSS_C_NO_CONTEXT; */
132
/* supply the service name to the gss-api
133
* If NULL, then we want user_to_user
134
* so get it from the cred
137
if (target_name_char)
139
if(!strncmp("GSI-NO-TARGET", target_name_char, 13))
141
target_name = GSS_C_NO_NAME;
145
tmp_buffer->value = target_name_char;
146
tmp_buffer->length = strlen(target_name_char);
149
* A gss_nt_service_name is of the form service@FQDN
150
* At least the Globus gssapi, and the Kerberos gssapi
151
* use the same form. We will check for
152
* two special forms here: host@FQDN and ftp@FQDN
153
* This could be another parameter to the gss_assist
157
if (strchr(target_name_char,'@') &&
158
!strstr(target_name_char,"CN="))
160
target_name_type = gss_nt_service_name;
163
major_status = gss_import_name(&minor_status1,
171
major_status = gss_inquire_cred(&minor_status1,
179
if (major_status == GSS_S_COMPLETE)
181
while (!context_established)
183
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF(
184
4, (globus_i_gsi_gss_assist_debug_fstream,
185
_GASL("req_flags: %8.8x input_token length: %u\n"),
186
(unsigned int) req_flags,
187
input_token->length));
189
major_status = gss_init_sec_context(&minor_status1,
203
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF(
204
4, (globus_i_gsi_gss_assist_debug_fstream,
205
_GASL("major:%8.8x minor:%8.8x ret_flags: %8.8x\n "
206
"output_token length: %u context_handle: %p\n"),
207
(unsigned int) major_status,
208
(unsigned int) minor_status1,
209
(unsigned int) ((ret_flags) ? *ret_flags : -1),
210
output_token->length,
213
if (input_token->length > 0)
215
free(input_token->value);
216
input_token->length = 0;
219
if (output_token->length != 0)
221
if ((*token_status = gss_assist_send_token(
222
gss_assist_send_context,
224
output_token->length)) != 0)
227
GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_WRITE;
230
gss_release_buffer(&minor_status2,
234
if (GSS_ERROR(major_status))
236
if (*context_handle != GSS_C_NO_CONTEXT)
238
gss_delete_sec_context(&minor_status2,
245
if (major_status & GSS_S_CONTINUE_NEEDED)
247
if ((*token_status = gss_assist_get_token(
248
gss_assist_get_context,
250
&input_token->length)) != 0)
253
GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_READ;
260
context_established = 1;
262
} /* end of GSS loop */
265
if (input_token->length > 0)
267
free(input_token->value); /* alloc done by g_get_token */
268
input_token->value = NULL;
269
input_token->length = 0;
272
if (target_name != GSS_C_NO_NAME)
274
gss_release_name(&minor_status2,&target_name);
277
result = (globus_result_t) minor_status1;
278
if(result != GLOBUS_SUCCESS)
280
GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT(
282
GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_INIT);
284
*minor_status = (OM_uint32) result;
286
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT;
292
* @name Init Security Context Async
296
* @ingroup globus_gsi_gss_assist
297
* This is a asynchronous version of the
298
* globus_gss_assist_init_sec_context() function. Instead of looping
299
* itself it passes in and out the read and written buffers and
300
* the calling application is responsible for doing the I/O directly.
302
* @param minor_status
303
* GSSAPI return code. The new minor status is a globus_result_t
304
* cast to a OM_uint32. If an error occurred (GSS_ERROR(major_status))
305
* the minor_status is a globus error object id. The error object
306
* can be obtained via globus_error_get and should be destroyed
307
* with globus_object_free when no longer needed. If no error
308
* occurred, the minor status is equal to GLOBUS_SUCCESS.
309
* @param initiator_cred_handle
310
* the cred handle obtained by acquire_cred.
311
* @param context_handle
312
* pointer to returned context.
313
* @param target_name_char
314
* char string repersentation of the
315
* server to be contacted.
317
* request flags, such as GSS_C_DELEG_FLAG for delegation
318
* and the GSS_C_MUTUAL_FLAG for mutual authentication.
320
* Pointer to which services are available after
321
* the connection is established. Maybe NULL if not wanted.
322
* @param input_buffer
323
* pointer to a buffer received from peer. Should
324
* be NULL on first call.
325
* @param input_buffer_len
326
* length of the buffer input_buffer. Should
327
* be zero on first call.
328
* @param output_bufferp
329
* pointer to a pointer which will be filled in
330
* with a pointer to a allocated block of memory. If
331
* non-NULL the contents of this block should be written
332
* to the peer where they will be fed into the
333
* gss_assist_init_sec_context_async() function.
334
* @param output_buffer_lenp
335
* pointer to an integer which will be filled
336
* in with the length of the allocated output buffer
337
* pointed to by *output_bufferp.
339
* GSS_S_COMPLETE on successful completion when this function does not
340
* need to be called again.
342
* GSS_S_CONTINUE_NEEDED when *output_bufferp should be sent to the
343
* peer and a new input_buffer read and this function called again.
345
* Other gss errors on failure.
348
globus_gss_assist_init_sec_context_async(
349
OM_uint32 * minor_status,
350
const gss_cred_id_t cred_handle,
351
gss_ctx_id_t * context_handle,
352
char * target_name_char,
354
OM_uint32 * ret_flags,
356
size_t input_buffer_len,
357
void ** output_bufferp,
358
size_t * output_buffer_lenp)
360
OM_uint32 major_status = GSS_S_COMPLETE;
361
OM_uint32 minor_status1 = 0;
362
OM_uint32 minor_status2 = 0;
363
gss_buffer_desc input_token_desc = GSS_C_EMPTY_BUFFER;
364
gss_buffer_t input_token = &input_token_desc;
365
gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER;
366
gss_buffer_t output_token = &output_token_desc;
367
gss_name_t target_name = GSS_C_NO_NAME;
368
gss_OID target_name_type = GSS_C_NO_OID;
369
gss_OID mech_type = GSS_C_NO_OID;
370
OM_uint32 time_req = 0;
371
OM_uint32 time_rec = 0;
372
gss_channel_bindings_t input_chan_bindings =
373
GSS_C_NO_CHANNEL_BINDINGS;
374
gss_OID * actual_mech_type = NULL;
375
gss_buffer_desc tmp_buffer_desc = GSS_C_EMPTY_BUFFER;
376
gss_buffer_t tmp_buffer = &tmp_buffer_desc;
377
globus_result_t result = GLOBUS_SUCCESS;
378
static char * _function_name_ =
379
"globus_gss_assist_init_sec_context_async";
380
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_ENTER;
382
/* Set up our input token from passed buffer */
383
if ((input_buffer != NULL) && (input_buffer_len != 0))
385
input_token_desc.length = input_buffer_len;
386
input_token_desc.value = input_buffer;
389
/* Do initialization first time through the loop */
391
/* This will not work if the context handle has been initialized
392
before the first call. Don't know how to fix it since I can't
393
access fields in the handle outside the GSS API. - Sam
395
if (*context_handle == GSS_C_NO_CONTEXT)
403
/* supply the service name to the gss-api
404
* If NULL, then we want user_to_user
405
* so get it from the cred
408
if (target_name_char)
410
if(!strncmp("GSI-NO-TARGET",target_name_char,13))
412
target_name = GSS_C_NO_NAME;
416
tmp_buffer->value = target_name_char;
417
tmp_buffer->length = strlen(target_name_char);
420
* A gss_nt_service_name is of the form service@FQDN
421
* At least the Globus gssapi, and the Kerberos gssapi
422
* use the same form. We will check for
423
* two special forms here: host@FQDN and ftp@FQDN
424
* This could be another parameter to the gss_assist
428
if (strchr(target_name_char, '@') &&
429
!strstr(target_name_char, "CN="))
431
target_name_type = gss_nt_service_name;
434
major_status = gss_import_name(&minor_status1,
443
major_status = gss_inquire_cred(&minor_status1,
451
if (major_status == GSS_S_COMPLETE)
453
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF(
454
4, (globus_i_gsi_gss_assist_debug_fstream,
455
_GASL("req_flags: %8.8x input_token length: %u\n"),
456
(unsigned int) req_flags,
457
input_token->length));
459
major_status = gss_init_sec_context(&minor_status1,
472
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_FPRINTF(
473
4, (globus_i_gsi_gss_assist_debug_fstream,
474
_GASL("major: %8.8x minor: %8.8x ret_flags: %8.8x\n"
475
"output_token length: %u context_handle: %p\n"),
476
(unsigned int) major_status,
477
(unsigned int) minor_status1,
478
(unsigned int) ((ret_flags) ? *ret_flags : -1),
479
output_token->length,
482
if (output_token->length != 0)
484
*output_bufferp = output_token->value;
485
*output_buffer_lenp = output_token->length;
486
/* These will now be freed by the caller */
490
*output_bufferp = NULL;
491
*output_buffer_lenp = 0;
494
if (GSS_ERROR(major_status))
496
if (*context_handle != GSS_C_NO_CONTEXT)
497
gss_delete_sec_context(&minor_status2,
504
if (target_name != GSS_C_NO_NAME)
506
gss_release_name(&minor_status2,&target_name);
510
result = (globus_result_t) minor_status1;
511
if(result != GLOBUS_SUCCESS)
513
GLOBUS_GSI_GSS_ASSIST_ERROR_CHAIN_RESULT(
515
GLOBUS_GSI_GSS_ASSIST_ERROR_WITH_INIT);
517
*minor_status = (OM_uint32) result;
519
GLOBUS_I_GSI_GSS_ASSIST_DEBUG_EXIT;