/** * Passes back the mech set of available mechs. * We only have one for now. * * @param minor_status * @param mech_set * * @return */ OM_uint32 GSS_CALLCONV gss_indicate_mechs( OM_uint32 * minor_status, gss_OID_set * mech_set) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; gss_OID_set_desc * set; static char * _function_name_ = "gss_indicate_mechs"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; if (minor_status == NULL || mech_set == NULL) { major_status = GSS_S_FAILURE; if (minor_status != NULL) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid parameter"))); } goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; major_status = gss_create_empty_oid_set(&local_minor_status, &set); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_MECH); goto exit; } major_status = gss_add_oid_set_member( &local_minor_status, (const gss_OID) gss_mech_globus_gssapi_openssl, &set); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OID); gss_release_oid_set(&local_minor_status, &set); goto exit; } *mech_set = set; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
globus_result_t globus_i_gsi_gssapi_error_chain_result( globus_result_t chain_result, int error_type, const char * filename, const char * function_name, int line_number, const char * short_desc, const char * long_desc) { globus_result_t result; globus_object_t * error_object; static char * _function_name_ = "globus_i_gsi_gssapi_error_chain_result"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; error_object = globus_error_construct_error( GLOBUS_GSI_GSSAPI_MODULE, globus_error_get(chain_result), error_type, filename, function_name, line_number, "%s%s%s", (error_type < 0 || error_type >= GLOBUS_GSI_GSSAPI_ERROR_LAST) ? _GGSL("Unknown error") : _GGSL(globus_l_gsi_gssapi_error_strings[error_type]), short_desc ? ": " : "", short_desc ? short_desc : ""); if(long_desc) { globus_error_set_long_desc(error_object, long_desc); } result = globus_error_put(error_object); GLOBUS_I_GSI_GSSAPI_INTERNAL_DEBUG_EXIT; return result; }
/** * Interrogates an Object Identifier set to determine whether a * specified Object Identifier is a member. This routine is * intended to be used with OID sets returned by * GSS_Indicate_mechs(), GSS_Acquire_cred(), and * GSS_Inquire_cred(). * * @param minor_status * @param member * @param set * @param present * * @return * GSS_S_COMPLETE indicates successful completion * GSS_S_FAILURE indicates that the operation failed */ OM_uint32 GSS_CALLCONV gss_test_oid_set_member( OM_uint32 * minor_status, const gss_OID member, const gss_OID_set set, int * present) { OM_uint32 major_status = GSS_S_COMPLETE; int index; static char * _function_name_ = "gss_test_oid_set_member"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check arguments */ if ((minor_status == NULL) || (member == NULL) || (member->elements == NULL) || (set == NULL) || (present == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid argument passed to function"))); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; *present = 0; for (index = 0; index < set->count; index++) { /* Sanity check */ if (set->elements[index].elements == NULL) { continue; } if ((set->elements[index].length == member->length) && (memcmp(set->elements[index].elements, member->elements, member->length) == 0)) { *present = 1; break; } } exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Free a Buffer Set * @ingroup globus_gsi_gssapi_buffer_set * @details * This function will free all memory associated with a buffer * set. Note that it will also free all memory associated with the * buffers int the buffer set. * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param buffer_set * Pointer to a buffer set structure. This pointer will point * at a NULL value upon return. * * @retval GSS_S_COMPLETE Success * @retval GSS_S_FAILURE Failure * * @see gss_create_empty_buffer_set * @see gss_add_buffer_set_member */ OM_uint32 GSS_CALLCONV gss_release_buffer_set( OM_uint32 * minor_status, gss_buffer_set_t * buffer_set) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; int index; static char * _function_name_ = "gss_release_buffer_set"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; *minor_status = GLOBUS_SUCCESS; if (buffer_set == NULL || *buffer_set == GSS_C_NO_BUFFER_SET) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL parameters passed to function: %s"), _function_name_)); major_status = GSS_S_FAILURE; goto exit; } for(index = 0; index < (*buffer_set)->count; index++) { major_status = gss_release_buffer(&local_minor_status, &(*buffer_set)->elements[index]); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); major_status = GSS_S_FAILURE; goto exit; } } free((*buffer_set)->elements); free(*buffer_set); *buffer_set = NULL; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Create a empty buffer set. * @ingroup globus_gsi_gssapi_buffer_set * @details * This function allocates and initializes a empty buffer set. The * memory allocated in this function should be freed by a call to * gss_release_buffer_set. * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param buffer_set * Pointer to a buffer set structure. * * @retval GSS_S_COMPLETE Success * @retval GSS_S_FAILURE Failure * * @see gss_add_buffer_set_member * @see gss_release_buffer_set */ OM_uint32 GSS_CALLCONV gss_create_empty_buffer_set( OM_uint32 * minor_status, gss_buffer_set_t * buffer_set) { OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_create_empty_buffer_set"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((buffer_set == NULL) || (minor_status == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL parameters passed to function: %s"), _function_name_)); goto exit; } *minor_status = GLOBUS_SUCCESS; *buffer_set = (gss_buffer_set_desc *) malloc( sizeof(gss_buffer_set_desc)); if (!*buffer_set) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } (*buffer_set)->count = 0; (*buffer_set)->elements = NULL; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return GSS_S_COMPLETE; }
/** * * Creates an object identifier set containing no object identifiers, * to which members may be subsequently added * using the GSS_Add_OID_set_member() * routine. These routines are intended to be * used to construct sets of mechanism * object identifiers, for input to GSS_Acquire_cred(). * * @param minor_status * @param oid_set * * @return * GSS_S_COMPLETE indicates successful completion * GSS_S_FAILURE indicates that the operation failed */ OM_uint32 GSS_CALLCONV gss_create_empty_oid_set( OM_uint32 * minor_status, gss_OID_set * oid_set) { OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_create_empty_oid_set"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((oid_set == NULL) || (minor_status == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid argument passed to function"))); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; *oid_set = (gss_OID_set_desc *) malloc(sizeof(gss_OID_set_desc)); if (!*oid_set) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } (*oid_set)->count = 0; (*oid_set)->elements = NULL; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @defgroup globus_i_gsi_gssapi_error Internal GSS-API Error Functions */ globus_result_t globus_i_gsi_gssapi_openssl_error_result( int error_type, const char * filename, const char * function_name, int line_number, const char * short_desc, const char * long_desc) { globus_object_t * error_object; globus_result_t result; static char * _function_name_ = "globus_i_gsi_gssapi_openssl_error_result"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; error_object = globus_error_wrap_openssl_error( GLOBUS_GSI_GSSAPI_MODULE, error_type, filename, function_name, line_number, "%s%s%s", _GGSL(globus_l_gsi_gssapi_error_strings[error_type]), short_desc ? ": " : "", short_desc ? short_desc : ""); if(long_desc) { globus_error_set_long_desc(error_object, long_desc); } result = globus_error_put(error_object); GLOBUS_I_GSI_GSSAPI_INTERNAL_DEBUG_EXIT; return result; }
int main(int argc, char **argv) { int debug=0; int verify=0; int mismatch=0; char *program; int badops=0; char *certfile=NULL; char *out1file=NULL; char *out2file=NULL; char *home=NULL; char *pin=NULL; char *argp; char *ss; BIO *bio_err; X509 *ucert; FILE *fp; FILE *fpout; #ifdef USE_PKCS11 CK_SESSION_HANDLE hSession = 0; #endif #ifdef WIN32 CRYPTO_malloc_init(); #endif ERR_load_prxyerr_strings(0); SSLeay_add_ssl_algorithms(); if ((bio_err=BIO_new(BIO_s_file())) != NULL) { BIO_set_fp(bio_err,stderr,BIO_NOCLOSE); } program=argv[0]; argc--; argv++; while (argc >= 1) { argp = *argv; if ( *argp == '-' && *(argp+1) == '-') { argp++; } if (strcmp(argp,"-debug") == 0) { debug++; } else if (strcmp(argp,"-cert") == 0) { if (--argc < 1) goto bad; certfile=*(++argv); } else if (strcmp(argp,"-out1") == 0) { if (--argc < 1) goto bad; out1file=*(++argv); } else if (strcmp(argp,"-out2") == 0) { if (--argc < 1) goto bad; out2file=*(++argv); } else if (strcmp(argp,"-help") == 0) { badops=1; break; } else { fprintf(stderr,_GGSL("unknown option %s\n"),*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: fprintf(stderr,_GGSL("%s [options]\n"),program); fprintf(stderr,_GGSL("where options are\n")); fprintf(stderr,_GGSL(" --help show this list\n")); fprintf(stderr,_GGSL(" --debug set debugging on\n")); fprintf(stderr,_GGSL(" --cert file name of long term certificate\n")); fprintf(stderr,_GGSL(" --out1 file name for name\n")); fprintf(stderr,_GGSL(" --out2 file name for commonName\n"); exit(1); } home = (char *)getenv("HOME"); if (home == NULL) { #ifndef WIN32 fprintf(stderr,_GGSL("$HOME not defined")); exit(1); #else home = "c:\\windows"; #endif } if (!strncmp(certfile,"SC:",3)) { #ifdef USE_PKCS11 char *cp; char *kp; int rc; cp = certfile + 3; kp = strchr(cp,':'); if (kp == NULL) { fprintf(stderr,_GGSL("Bad format of cert name, SC:card:cert\n")); exit (2); } kp++; /* skip the : */ if (hSession == 0) { rc = sc_init(&hSession, cp, NULL, pin, CKU_USER, 0); if (rc) { fprintf(stderr,_GGSL("Failed to open card session\n")); ERR_print_errors_fp (stderr); exit(2); } } rc = sc_get_cert_obj_by_label(hSession,kp,&ucert); if (rc) { fprintf(stderr,_GGSL("Failed to find certificate on card \n")); ERR_print_errors_fp (stderr); exit(2); } #else fprintf(stderr,_GGSL("Smart card support not compiled with this program\n")); exit (2); #endif /* USE_PKCS11 */ } else { fp = fopen (certfile, "r"); if (fp == NULL) { fprintf(stderr,_GGSL(" failed to open %s\n",certfile)); exit (1); } ucert = PEM_read_X509 (fp, NULL, OPENSSL_PEM_CB(NULL, NULL)); fclose (fp); } if (ucert == NULL) { ERR_print_errors_fp (stderr); exit (1); } if (out1file) { if (strcmp("-",out1file)) { fpout=fopen(out1file,"w"); } else { fpout = stdout; } if (fpout == NULL) { fprintf (stderr,"Unable to open out1 file:%s\n", out1file); exit(4); } ss = X509_NAME_oneline(ucert->cert_info->subject,NULL,0); while (1) { if (!strcmp(ss+strlen(ss)-strlen("/CN=limited proxy"), "/CN=limited proxy")) { *(ss+strlen(ss)-strlen("/CN=limited proxy"))= '\0'; } else if (!strcmp(ss+strlen(ss)-strlen("/CN=proxy"), "/CN=proxy")) { *(ss+strlen(ss)-strlen("/CN=proxy")) = '\0'; } else { break; } } fprintf(fpout,"%s\n",ss); OPENSSL_free(ss); if (fpout != stdout) { fclose(fpout); } } if (out2file) { if (strcmp("-",out2file)) { fpout=fopen(out2file,"w"); } else { fpout = stdout; } if (fpout == NULL) { fprintf (stderr,"Unable to open out2 file:%s\n", out2file); exit(4); } { X509_NAME *subject; X509_NAME_ENTRY *ne; ASN1_STRING *data; X509_NAME_ENTRY *o = NULL; X509_NAME_ENTRY *ou1 = NULL; X509_NAME_ENTRY *ou2 = NULL; int i; subject=X509_get_subject_name(ucert); i = X509_NAME_entry_count(subject)-1; while (i > 0) { ne=X509_NAME_get_entry(subject,i); if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_organizationName))) { if (!o) { o = ne; } } if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_organizationalUnitName))) { if (ou2) { ou1 = ne; } else { ou2 = ne; } } if (!OBJ_cmp(ne->object, OBJ_nid2obj(NID_commonName))) { data=X509_NAME_ENTRY_get_data(ne); if ((data->length == 5 && !memcmp(data->data,"proxy",5)) || (data->length == 13 && !memcmp(data->data,"limited proxy",13))) { i--; continue; } fprintf(fpout,"%.*s\n",data->length,data->data); /* break; */ } i--; } if (o) { data=X509_NAME_ENTRY_get_data(o); fprintf(fpout,"%.*s\n",data->length,data->data); } if (ou1) { data=X509_NAME_ENTRY_get_data(ou1); fprintf(fpout,"%.*s\n",data->length,data->data); } if (ou2) { data=X509_NAME_ENTRY_get_data(ou2); fprintf(fpout,"%.*s\n",data->length,data->data); } } /* inline section */ if (fpout != stdout) { fclose(fpout); } } /* out2file */ return 0; }
/** * Accept a delegated credential. * * This functions drives the accepting side of the credential * delegation process. It is expected to be called in tandem with the * gss_init_delegation function. * * @param minor_status * The minor status returned by this function. This paramter * will be 0 upon success. * @param context_handle * The security context over which the credential is * delegated. * @param extension_oids * A set of extension oids corresponding to buffers in the * extension_buffers paramter below. May be * GSS_C_NO_BUFFER_SET. Currently not used. * @param extension_buffers * A set of extension buffers corresponding to oids in the * extension_oids paramter above. May be * GSS_C_NO_BUFFER_SET. Currently not used. * @param input_token * The token that was produced by a prior call to * gss_init_delegation. * @param req_flags * Flags that modify the behavior of the function. Currently * only GSS_C_GLOBUS_SSL_COMPATIBLE is checked for. This flag * results in tokens that aren't wrapped. * @param time_req * The requested period of validity (seconds) of the delegated * credential. Currently a noop. * @param time_rec * This parameter will contain the received period of validity * of the delegated credential upon success. May be NULL. * @param delegated_cred_handle * This parameter will contain the delegated credential upon * success. * @param mech_type * Returns the security mechanism upon success. Currently not * implemented. May be NULL. * @param output_token * A token that should be passed to gss_init_delegation if the * return value is GSS_S_CONTINUE_NEEDED. * @return * GSS_S_COMPLETE upon successful completion * GSS_S_CONTINUE_NEEDED if the function needs to be called * again. * GSS_S_FAILURE upon failure */ OM_uint32 GSS_CALLCONV gss_accept_delegation( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_OID_set extension_oids, const gss_buffer_set_t extension_buffers, const gss_buffer_t input_token, OM_uint32 req_flags, OM_uint32 time_req, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle, gss_OID * mech_type, gss_buffer_t output_token) { BIO * bio = NULL; BIO * read_bio = NULL; BIO * write_bio = NULL; X509 * peer_cert = NULL; const EVP_MD * peer_digest; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; globus_result_t local_result = GLOBUS_SUCCESS; gss_ctx_id_desc * context; globus_gsi_cred_handle_t delegated_cred = NULL; char dbuf[1]; static char * _function_name_ = "gss_accept_delegation"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* parameter checking goes here */ if(minor_status == NULL) { major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(context_handle == GSS_C_NO_CONTEXT) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } context = (gss_ctx_id_desc *) context_handle; if(delegated_cred_handle == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid delegated_cred_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(extension_oids != GSS_C_NO_OID_SET && (extension_buffers == GSS_C_NO_BUFFER_SET || extension_oids->count != extension_buffers->count)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid restriction parameters passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(output_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid output token passed to function"))); major_status = GSS_S_FAILURE; goto exit; } output_token->length = 0; if(input_token == GSS_C_NO_BUFFER) { major_status |= GSS_S_CONTINUE_NEEDED; goto exit; } if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { bio = BIO_new(BIO_s_mem()); read_bio = bio; write_bio = bio; } else { bio = context->gss_sslbio; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); major_status = globus_i_gsi_gss_put_token(&local_minor_status, context, read_bio, input_token); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } switch(context->delegation_state) { case GSS_DELEGATION_START: /* generate the proxy */ BIO_read(bio, dbuf, 1); GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "delegation flag: %.1s\n", dbuf)); if (dbuf[0] == 'D') { globus_gsi_proxy_handle_attrs_t proxy_handle_attrs; int key_bits; /* * The delegated credential always generated 512 bit keys * irrespective of the key strength of the peer credential (bug * 3794). Fix for that is added below. */ local_result = globus_gsi_cred_get_key_bits( context->peer_cred_handle->cred_handle, &key_bits); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_init( &proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_set_keybits( proxy_handle_attrs, key_bits); if(local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert( context->peer_cred_handle->cred_handle, &peer_cert); if (local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } peer_digest = EVP_get_digestbynid( OBJ_obj2nid(peer_cert->sig_alg->algorithm)); local_result = globus_gsi_proxy_handle_attrs_set_signing_algorithm( proxy_handle_attrs, (EVP_MD *) peer_digest); if (local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } if(context->proxy_handle) { globus_gsi_proxy_handle_destroy(context->proxy_handle); } local_result = globus_gsi_proxy_handle_init( &context->proxy_handle, proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { globus_gsi_proxy_handle_attrs_destroy(proxy_handle_attrs); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_attrs_destroy( proxy_handle_attrs); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_proxy_create_req(context->proxy_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION); major_status = GSS_S_FAILURE; goto mutex_unlock; } context->delegation_state = GSS_DELEGATION_COMPLETE_CRED; } else { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_DELEGATION, (_GGSL("Invalid initial hello message, expecting: 'D', " "received: '%c'"), dbuf[0])); major_status = GSS_S_FAILURE; goto mutex_unlock; } break; case GSS_DELEGATION_COMPLETE_CRED: /* get the signed cert and the key chain and insert them into * the cred structure */ local_result = globus_gsi_proxy_assemble_cred( context->proxy_handle, &delegated_cred, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto mutex_unlock; } major_status = globus_i_gsi_gss_create_cred(&local_minor_status, GSS_C_BOTH, delegated_cred_handle, &delegated_cred); if(GSS_ERROR(major_status)) { globus_gsi_cred_handle_destroy(delegated_cred); GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); goto mutex_unlock; } /* reset state machine */ context->delegation_state = GSS_DELEGATION_START; if (time_rec != NULL) { time_t lifetime; local_result = globus_gsi_cred_get_lifetime( ((gss_cred_id_desc *)(*delegated_cred_handle))->cred_handle, &lifetime); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; goto mutex_unlock; } *time_rec = (OM_uint32) lifetime; } case GSS_DELEGATION_SIGN_CERT: case GSS_DELEGATION_DONE: break; } /* returns empty token when there is no output */ major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, write_bio, output_token); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } if (context->delegation_state != GSS_DELEGATION_START) { major_status |= GSS_S_CONTINUE_NEEDED; } mutex_unlock: if (peer_cert) { X509_free(peer_cert); } globus_mutex_unlock(&context->mutex); exit: if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { BIO_free(bio); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
OM_uint32 GSS_CALLCONV gss_inquire_names_for_mech( OM_uint32 * minor_status, const gss_OID mechanism, gss_OID_set * name_types ) { static char * _function_name_ = "gss_inquire_names_for_mech"; OM_uint32 major_status; int i; gss_OID oids[] = { GSS_C_NT_HOSTBASED_SERVICE, GSS_C_NT_ANONYMOUS, GSS_C_NT_EXPORT_NAME, (gss_OID) gss_nt_host_ip, (gss_OID) gss_nt_x509, NULL }; if (minor_status == NULL || mechanism == NULL || name_types == NULL) { if (minor_status != NULL) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid parameter"))); } major_status = GSS_S_FAILURE; goto out; } if (! g_OID_equal(mechanism, gss_mech_globus_gssapi_openssl)) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_MECH, (_GGSL("Requested mechanism not supported"))); major_status = GSS_S_BAD_MECH; goto out; } major_status = gss_create_empty_oid_set(minor_status, name_types); if (major_status != GSS_S_COMPLETE) { goto out; } for (i = 0; oids[i] != NULL; i++) { major_status = gss_add_oid_set_member( minor_status, oids[i], name_types); if (major_status != GSS_S_COMPLETE) { goto free_oids; } } free_oids: if (major_status != GSS_S_COMPLETE) { OM_uint32 local_major; OM_uint32 local_minor; local_major = gss_release_oid_set( &local_minor, name_types); } out: return major_status; }
/** * @brief Export a GSSAPI credential * @ingroup globus_gsi_gssapi_extensions * @details * Saves the credential so it can be checkpointed and * imported by gss_import_cred * * @param minor_status * @param cred_handle * @param desired_mech * Should either be gss_mech_globus_gssapi_openssl or * NULL (in which case gss_mech_globus_gssapi_openssl is * assumed). * @param option_req * @param export_buffer * * @return */ OM_uint32 GSS_CALLCONV gss_export_cred( OM_uint32 * minor_status, const gss_cred_id_t cred_handle, const gss_OID desired_mech, OM_uint32 option_req, gss_buffer_t export_buffer) { OM_uint32 major_status = GLOBUS_SUCCESS; BIO * bp = NULL; gss_cred_id_desc * cred_desc = NULL; globus_result_t local_result; char * proxy_filename = NULL; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; cred_desc = (gss_cred_id_desc *) cred_handle; *minor_status = (OM_uint32) GLOBUS_SUCCESS; if (export_buffer == NULL || export_buffer == GSS_C_NO_BUFFER) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL or empty export_buffer parameter passed to function: %s"), __func__)); goto exit; } export_buffer->length = 0; export_buffer->value = NULL; if (cred_handle == NULL) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL or empty export_buffer parameter passed to function: %s"), __func__)); goto exit; } if(desired_mech != NULL && g_OID_equal(desired_mech, (gss_OID) gss_mech_globus_gssapi_openssl)) { major_status = GSS_S_BAD_MECH; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_MECH, (_GGSL("The desired mechanism of: %s, is not supported by this " "GSS implementation"), desired_mech->elements)); goto exit; } if(option_req == GSS_IMPEXP_OPAQUE_FORM) { /* When option_req is equal to EXPORT_OPAQUE_FORM (0), it exports * an opaque buffer suitable for storage in memory or on * disk or passing to another process, which * can import the buffer with gss_import_cred(). */ bp = BIO_new(BIO_s_mem()); if(bp == NULL) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't initialize IO bio for exporting credential"))); major_status = GSS_S_FAILURE; goto exit; } local_result = globus_gsi_cred_write(cred_desc->cred_handle, bp); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_IMPEXP_BIO_SSL); major_status = GSS_S_FAILURE; goto exit; } export_buffer->length = BIO_pending(bp); if (export_buffer->length > 0) { export_buffer->value = (char *) malloc(export_buffer->length); if (export_buffer->value == NULL) { export_buffer->length = 0; GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } BIO_read(bp, export_buffer->value, export_buffer->length); } else { export_buffer->value = NULL; } major_status = GSS_S_COMPLETE; } else if(option_req == GSS_IMPEXP_MECH_SPECIFIC) { /* With option_req is equal to EXPORT_MECH_SPECIFIC (1), * it exports a buffer filled with mechanism-specific * information that the calling application can use * to pass the credentials to another process that * is not written to the GSS-API. */ local_result = GLOBUS_GSI_SYSCONFIG_GET_UNIQUE_PROXY_FILENAME(&proxy_filename); if(local_result != GLOBUS_SUCCESS) { proxy_filename = NULL; GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto exit; } GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 3, (globus_i_gsi_gssapi_debug_fstream, "Writing exported cred to: %s\n", proxy_filename)); local_result = globus_gsi_cred_write_proxy(cred_desc->cred_handle, proxy_filename); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto exit; } export_buffer->value = globus_common_create_string( "X509_USER_PROXY=%s", proxy_filename); export_buffer->length = strlen(export_buffer->value)+1; } else { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Unrecognized option_req of: %d"), option_req)); goto exit; } exit: if(proxy_filename != NULL) { free(proxy_filename); } if (bp) { BIO_free(bp); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Wrap Size Limit * @ingroup globus_gsi_gssapi * @details * GSSAPI routine to take a buffer, calculate a MIC * which is returned as a token. We will use the SSL * protocol here. * * @param minor_status * @param context_handle * @param conf_req_flag * @param qop_req * @param req_output_size * @param max_input_size */ OM_uint32 GSS_CALLCONV gss_wrap_size_limit( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size, OM_uint32 * max_input_size) { gss_ctx_id_desc * context = (gss_ctx_id_desc *)context_handle; OM_uint32 max; OM_uint32 overhead; OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_wrap_size_limit"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; *minor_status = (OM_uint32) GLOBUS_SUCCESS; if (context_handle == GSS_C_NO_CONTEXT) { major_status = GSS_S_NO_CONTEXT; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context handle passed to function"))); goto exit; } /* This may not be correct as SSL is vague about * the max size, and there is even a Microsoft hack as well! * DEE this may need work. SSL adds * 1024 as overhead for encryption and compression. * These appear to be over kill, so our max size may be * very low. */ if (conf_req_flag == 0 && qop_req == GSS_C_QOP_GLOBUS_GSSAPI_OPENSSL_BIG) { #if OPENSSL_VERSION_NUMBER < 0x10000000L overhead = 17 + EVP_MD_size(context->gss_ssl->write_hash); #else overhead = 17 + EVP_MD_size(context->gss_ssl->write_hash->digest); #endif max = req_output_size - overhead; *max_input_size = max; } else { overhead = SSL3_RT_MAX_PACKET_SIZE - SSL3_RT_MAX_PLAIN_LENGTH; max = req_output_size - (req_output_size / SSL3_RT_MAX_PACKET_SIZE + 1) * overhead; *max_input_size = max; } exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Wrap * @ingroup globus_gsi_gssapi * @details * Wrap a message for integrity and protection. * We do this using the SSLv3 routines, by writing to the * SSL bio, and pulling off the buffer from the back * of the write BIO. But we can't do everything SSL * might want, such as control messages, or segment the messages * here, since we are forced to using the GSSAPI tokens, * and can not communicate directly with our peer. * So there maybe some failures which would work with true * SSL. * * @param minor_status * @param context_handle * @param conf_req_flag * @param qop_req * @param input_message_buffer * @param conf_state * @param output_message_buffer * * @return */ OM_uint32 GSS_CALLCONV gss_wrap( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, int * conf_state, gss_buffer_t output_message_buffer) { gss_ctx_id_desc * context = (gss_ctx_id_desc *)context_handle; gss_buffer_desc mic_buf_desc; gss_buffer_t mic_buf = (gss_buffer_desc *) &mic_buf_desc; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; unsigned char * message_value; time_t context_goodtill; static char * _function_name_ = "gss_wrap"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(GLOBUS_I_GSI_GSSAPI_DEBUG(3)) { BIO * debug_bio; fprintf(globus_i_gsi_gssapi_debug_fstream, "input message: length = %u\n" " value = \n", (unsigned) input_message_buffer->length); debug_bio = BIO_new_fp(globus_i_gsi_gssapi_debug_fstream, BIO_NOCLOSE); BIO_dump(debug_bio, input_message_buffer->value, input_message_buffer->length); } output_message_buffer->value = NULL; output_message_buffer->length = 0; GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "gss_wrap conf_req_flag=%d qop_req=%d\n", conf_req_flag, (int) qop_req)); if (context_handle == GSS_C_NO_CONTEXT) { major_status = GSS_S_NO_CONTEXT; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context handle passed to function"))); goto exit; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); if(context->ctx_flags & GSS_I_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION) { time_t current_time; current_time = time(NULL); major_status = globus_i_gsi_gss_get_context_goodtill( &local_minor_status, context, &context_goodtill); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT); goto unlock_mutex_error; } if(current_time > context_goodtill) { major_status = GSS_S_CONTEXT_EXPIRED; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_EXPIRED_CREDENTIAL, (_GGSL("Expired credential: %s < %s"), ctime(&context_goodtill), ctime(¤t_time))); goto unlock_mutex_error; } } if (conf_req_flag == GSS_INTEGRITY_ONLY && qop_req == GSS_C_QOP_GLOBUS_GSSAPI_OPENSSL_BIG) { /* unlock the context mutex */ globus_mutex_unlock(&context->mutex); major_status = gss_get_mic(&local_minor_status, context_handle, qop_req, input_message_buffer, mic_buf); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_MIC); goto unlock_mutex_error; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); output_message_buffer->value = (char *) malloc(5 + mic_buf->length + input_message_buffer->length); if (output_message_buffer->value == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); gss_release_buffer(&local_minor_status, mic_buf); major_status = GSS_S_FAILURE; goto unlock_mutex_error; } output_message_buffer->length = 5 + mic_buf->length + input_message_buffer->length; message_value = output_message_buffer->value; *message_value++ = SSL3_RT_GSSAPI_OPENSSL; *message_value++ = 3; *message_value++ = 0; S2N(mic_buf->length, (char *) message_value); message_value += 2; memcpy(message_value, mic_buf->value, mic_buf->length); message_value = message_value + mic_buf->length; memcpy(message_value, input_message_buffer->value, input_message_buffer->length); if (conf_state) { *conf_state = GSS_INTEGRITY_ONLY; } } else { int rc; rc = SSL_write(context->gss_ssl, input_message_buffer->value, input_message_buffer->length); if (rc != input_message_buffer->length) { /* problem, did not take the whole buffer */ GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WRAP_BIO, (_GGSL("SSL failed wrapping entire message: " "SSL_write wrote %d bytes, should be %d bytes"), rc, input_message_buffer->length)); major_status = GSS_S_FAILURE; goto unlock_mutex_error; } if (conf_state) { if (SSL_CIPHER_get_bits( SSL_get_current_cipher(context->gss_ssl), NULL) == 0) { *conf_state = GSS_INTEGRITY_ONLY; } else { *conf_state = GSS_CONFIDENTIALITY; } } /* get the data from the write BIO */ major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, NULL, output_message_buffer); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto unlock_mutex_error; } } unlock_mutex_error: globus_mutex_unlock(&context->mutex); exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Add a buffer to a buffer set * @ingroup globus_gsi_gssapi_buffer_set * @details * This function allocates a new gss_buffer_t, initializes it with the * values in the member_buffer parameter. * * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param member_buffer * Buffer to insert into the buffer set. * @param buffer_set * Pointer to a initialized buffer set structure. * * @retval GSS_S_COMPLETE Success * @retval GSS_S_FAILURE Failure * * @see gss_create_empty_buffer_set * @see gss_release_buffer_set */ OM_uint32 GSS_CALLCONV gss_add_buffer_set_member( OM_uint32 * minor_status, const gss_buffer_t member_buffer, gss_buffer_set_t * buffer_set) { int new_count; gss_buffer_t new_elements; gss_buffer_set_t set; OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_add_buffer_set_member"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((minor_status == NULL) || (member_buffer == NULL) || (buffer_set == NULL) || (*buffer_set == GSS_C_NO_BUFFER_SET)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid buffer_set passed to function"))); goto exit; } set = *buffer_set; new_count = set->count + 1; new_elements = malloc(sizeof(gss_buffer_desc) * new_count); if (new_elements == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } if (set->count > 0) { /* Copy existing buffers */ memcpy(new_elements, set->elements, sizeof(gss_buffer_desc) * set->count); } /* And append new buffer */ new_elements[set->count].value = malloc(member_buffer->length); if(new_elements[set->count].value == NULL) { free(new_elements); GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } memcpy(new_elements[set->count].value, member_buffer->value, member_buffer->length); new_elements[set->count].length = member_buffer->length; set->count = new_count; free(set->elements); set->elements = new_elements; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Set Security Context Option * @ingroup globus_gsi_gssapi_extensions * @details * GSSAPI routine to initiate the sending of a security context * See: <draft-ietf-cat-gssv2-cbind-04.txt> * * @param minor_status * @param context_handle * @param option * @param value * * @return */ OM_uint32 GSS_CALLCONV gss_set_sec_context_option( OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_OID option, const gss_buffer_t value) { gss_ctx_id_desc * context = NULL; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; globus_result_t local_result = GLOBUS_SUCCESS; int index; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; if(minor_status == NULL) { major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(context_handle == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function - cannot be NULL"))); major_status = GSS_S_FAILURE; goto exit; } context = *context_handle; if(option == GSS_C_NO_OID) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid option passed to function with value: GSS_C_NO_OID"))); major_status = GSS_S_FAILURE; goto exit; } if (*context_handle == GSS_C_NO_CONTEXT) { /* for now just malloc and zero the context */ context = (gss_ctx_id_desc *) malloc(sizeof(gss_ctx_id_desc)); if (context == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto exit; } *context_handle = context; memset(context, 0, sizeof(gss_ctx_id_desc)); context->ctx_flags = 0; major_status = gss_create_empty_oid_set( &local_minor_status, (gss_OID_set *) &context->extension_oids); /* initialize the callback_data in the context. This needs * to be done so the verify_callback func can be set later. */ local_result = globus_gsi_callback_data_init( &context->callback_data); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT, (_GGSL("The callback data in the context " "could not be initialized."))); major_status = GSS_S_FAILURE; goto exit; } } else if(context->ctx_flags & GSS_I_CTX_INITIALIZED) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT, (_GGSL("The context has already been initialized! %s should be " "called on a context before initialization"), __func__)); major_status = GSS_S_FAILURE; goto exit; } if(g_OID_equal(option, GSS_DISALLOW_ENCRYPTION)) { context->ctx_flags |= GSS_I_DISALLOW_ENCRYPTION; } else if(g_OID_equal(option, GSS_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION)) { context->ctx_flags |= GSS_I_PROTECTION_FAIL_ON_CONTEXT_EXPIRATION; } else if(g_OID_equal(option, GSS_APPLICATION_WILL_HANDLE_EXTENSIONS)) { if(value == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid buffer passed to function"))); major_status = GSS_S_FAILURE; goto exit; } for(index = 0; index < ((gss_OID_set_desc *) value->value)->count; index++) { major_status = gss_add_oid_set_member( &local_minor_status, (gss_OID) &((gss_OID_set_desc *) value->value)->elements[index], (gss_OID_set *) &context->extension_oids); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OID); goto exit; } } local_result = globus_gsi_callback_set_extension_cb( context->callback_data, globus_i_gsi_gss_verify_extensions_callback); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto exit; } /* if the extension_oids are set, * then we set them in the callback data */ local_result = globus_gsi_callback_set_extension_oids( context->callback_data, (void *) context->extension_oids); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto exit; } context->ctx_flags |= GSS_I_APPLICATION_WILL_HANDLE_EXTENSIONS; } else { /* unknown option */ GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_UNKNOWN_OPTION, (NULL)); major_status = GSS_S_FAILURE; goto exit; } *context_handle = context; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Initiate Delegation * @ingroup globus_gsi_gssapi_extensions_delegation * @details * This functions drives the initiating side of the credential * delegation process. It is expected to be called in tandem with the * gss_accept_delegation function. * * @param minor_status * The minor status returned by this function. This parameter * will be 0 upon success. * @param context_handle * The security context over which the credential is * delegated. * @param cred_handle * The credential to be delegated. May be GSS_C_NO_CREDENTIAL * in which case the credential associated with the security * context is used. * @param desired_mech * The desired security mechanism. Currently not used. May be * GSS_C_NO_OID. * @param extension_oids * A set of extension OIDs corresponding to buffers in the * extension_buffers parameter below. The extensions specified * will be added to the delegated credential. May be * GSS_C_NO_BUFFER_SET. * @param extension_buffers * A set of extension buffers corresponding to OIDs in the * extension_oids parameter above. May be * GSS_C_NO_BUFFER_SET. * @param input_token * The token that was produced by a prior call to * gss_accept_delegation. This parameter will be ignored the * first time this function is called. * @param req_flags * Flags that modify the behavior of the function. Currently * only GSS_C_GLOBUS_SSL_COMPATIBLE and * GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG are checked for. The * GSS_C_GLOBUS_SSL_COMPATIBLE flag results in tokens that * aren't wrapped and GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG * causes the delegated proxy to be limited (requires that no * extensions are specified. * * @param time_req * The requested period of validity (seconds) of the delegated * credential. Passing a time_req of 0 cause the delegated credential to * have the same lifetime as the credential that issued it. * @param output_token * A token that should be passed to gss_accept_delegation if the * return value is GSS_S_CONTINUE_NEEDED. * @retval GSS_S_COMPLETE Success * @retval GSS_S_CONTINUE_NEEDED This function needs to be called again. * @retval GSS_S_FAILURE upon failure */ OM_uint32 GSS_CALLCONV gss_init_delegation( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_cred_id_t cred_handle, const gss_OID desired_mech, const gss_OID_set extension_oids, const gss_buffer_set_t extension_buffers, const gss_buffer_t input_token, OM_uint32 req_flags, OM_uint32 time_req, gss_buffer_t output_token) { BIO * bio = NULL; BIO * read_bio = NULL; BIO * write_bio = NULL; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; gss_ctx_id_desc * context; gss_cred_id_desc * cred; X509 * cert = NULL; STACK_OF(X509) * cert_chain = NULL; PROXYCERTINFO * pci; globus_gsi_cert_utils_cert_type_t cert_type; int index; globus_result_t local_result = GLOBUS_SUCCESS; static char * _function_name_ = "init_delegation"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; if(minor_status == NULL) { major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(context_handle == GSS_C_NO_CONTEXT) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } context = (gss_ctx_id_desc *) context_handle; cred = (gss_cred_id_desc *) cred_handle; if (cred_handle == GSS_C_NO_CREDENTIAL) { cred = (gss_cred_id_desc *) context->cred_handle; } if(cred == GSS_C_NO_CREDENTIAL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Couldn't initialize delegation credential handle"))); major_status = GSS_S_FAILURE; goto exit; } if(desired_mech != GSS_C_NO_OID && desired_mech != (gss_OID) gss_mech_globus_gssapi_openssl) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid desired_mech passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(extension_oids != GSS_C_NO_OID_SET && (extension_buffers == GSS_C_NO_BUFFER_SET || extension_oids->count != extension_buffers->count)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid extension parameters passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(output_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid output_token passed to function"))); major_status = GSS_S_FAILURE; goto exit; } output_token->length = 0; if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { bio = BIO_new(BIO_s_mem()); read_bio = bio; write_bio = bio; } else { bio = context->gss_sslbio; } /* lock the context mutex */ globus_mutex_lock(&context->mutex); /* pass the input to the BIO */ if(context->delegation_state != GSS_DELEGATION_START) { /* * first time there is no input token, but after that * there will always be one */ if(input_token == GSS_C_NO_BUFFER) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid input_token passed to function: " "delegation is not at initial state"))); major_status = GSS_S_FAILURE; goto mutex_unlock; } major_status = globus_i_gsi_gss_put_token(&local_minor_status, context, read_bio, input_token); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } } /* delegation state machine */ switch (context->delegation_state) { case GSS_DELEGATION_START: /* start delegation by sending a "D" */ BIO_write(bio, "D", 1); context->delegation_state = GSS_DELEGATION_SIGN_CERT; break; case GSS_DELEGATION_SIGN_CERT: /* get the returned cert from the ssl BIO, make sure it is * correct and then sign it and place it in the output_token */ local_result = globus_gsi_proxy_inquire_req(context->proxy_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert_type( context->cred_handle->cred_handle, &cert_type); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* set the requested time */ if(time_req != 0) { if(time_req%60) { /* round up */ time_req += 60; } local_result = globus_gsi_proxy_handle_set_time_valid( context->proxy_handle, time_req/60); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } } /* clear the proxycertinfo */ local_result = globus_gsi_proxy_handle_clear_cert_info(context->proxy_handle); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } if(cert_type == GLOBUS_GSI_CERT_UTILS_TYPE_CA) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } local_result = globus_gsi_proxy_handle_set_type( context->proxy_handle, (req_flags & GSS_C_GLOBUS_DELEGATE_LIMITED_PROXY_FLAG) ? GLOBUS_GSI_CERT_UTILS_TYPE_LIMITED_PROXY : GLOBUS_GSI_CERT_UTILS_TYPE_IMPERSONATION_PROXY); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* set the proxycertinfo here */ if(extension_oids != GSS_C_NO_OID_SET) { if(GLOBUS_GSI_CERT_UTILS_IS_GSI_2_PROXY(cert_type)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("A restricted globus proxy may not be created " "from a legacy globus proxy"))); context->delegation_state = GSS_DELEGATION_DONE; major_status = GSS_S_FAILURE; goto mutex_unlock; } for(index = 0; index < extension_oids->count; index++) { if(g_OID_equal((gss_OID) &extension_oids->elements[index], gss_proxycertinfo_extension)) { pci = extension_buffers->elements[index].value; local_result = globus_gsi_proxy_handle_set_proxy_cert_info( context->proxy_handle, pci); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } } } } local_result = globus_gsi_proxy_sign_req( context->proxy_handle, cred->cred_handle, bio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } local_result = globus_gsi_cred_get_cert(cred->cred_handle, &cert); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } /* push the cert used to sign the proxy */ i2d_X509_bio(bio, cert); X509_free(cert); /* push the number of certs in the cert chain */ local_result = globus_gsi_cred_get_cert_chain(cred->cred_handle, &cert_chain); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } for(index = 0; index < sk_X509_num(cert_chain); index++) { cert = sk_X509_value(cert_chain, index); if(!cert) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get cert from cert chain"))); major_status = GSS_S_FAILURE; context->delegation_state = GSS_DELEGATION_DONE; goto mutex_unlock; } i2d_X509_bio(bio, cert); } sk_X509_pop_free(cert_chain, X509_free); /* reset state machine */ context->delegation_state = GSS_DELEGATION_START; break; case GSS_DELEGATION_COMPLETE_CRED: case GSS_DELEGATION_DONE: break; } major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, write_bio, output_token); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto mutex_unlock; } if (context->delegation_state != GSS_DELEGATION_START) { major_status |= GSS_S_CONTINUE_NEEDED; } mutex_unlock: globus_mutex_unlock(&context->mutex); exit: if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { BIO_free(bio); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
OM_uint32 GSS_CALLCONV gss_add_oid_set_member( OM_uint32 * minor_status, const gss_OID member_oid, gss_OID_set * oid_set) { int new_count; gss_OID new_elements; gss_OID_set set = NULL; OM_uint32 major_status = GSS_S_COMPLETE; static char * _function_name_ = "gss_add_oid_set_member"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* Sanity check */ if ((minor_status == NULL) || (member_oid == NULL) || (oid_set == NULL)) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid argument passed to function"))); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; set = *oid_set; new_count = set->count + 1; new_elements = malloc(sizeof(gss_OID_desc) * new_count); if (new_elements == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto free_set_exit; } if (set->count > 0) { /* Copy existing oids */ memcpy(new_elements, set->elements, sizeof(gss_OID_desc) * set->count); } /* And append new oid */ memcpy(&new_elements[set->count], member_oid, sizeof(gss_OID_desc)); free_set_exit: if (set->elements) { free(set->elements); } set->count = new_count; set->elements = new_elements; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Init Sec Context * @ingroup globus_gsi_gssapi */ OM_uint32 GSS_CALLCONV gss_init_sec_context( OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, gss_ctx_id_t * context_handle_P, const gss_name_t target_name, const gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, const gss_channel_bindings_t input_chan_bindings, const gss_buffer_t input_token, gss_OID * actual_mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec) { gss_ctx_id_desc * context = NULL; OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; OM_uint32 local_major_status; globus_result_t local_result; int rc; char cbuf[1]; globus_gsi_cert_utils_cert_type_t cert_type; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; *minor_status = (OM_uint32) GLOBUS_SUCCESS; output_token->length = 0; context = *context_handle_P; /* module activation if not already done by calling * globus_module_activate */ globus_thread_once( &once_control, globus_l_gsi_gssapi_activate_once); globus_mutex_lock(&globus_i_gssapi_activate_mutex); if (!globus_i_gssapi_active) { globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE); } globus_mutex_unlock(&globus_i_gssapi_activate_mutex); if(req_flags & GSS_C_ANON_FLAG && req_flags & GSS_C_DELEG_FLAG) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Can't initialize a context to be both anonymous and " "provide delegation"))); goto error_exit; } if(req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE && req_flags & GSS_C_DELEG_FLAG) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Can't initialize a context to both use SSL compatible " "context establishment and provide delegation"))); goto error_exit; } if(req_flags & GSS_C_DELEG_FLAG && target_name == GSS_C_NO_NAME) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Need a target name for authorization prior " "to doing delegation"))); goto error_exit; } if ((context == (gss_ctx_id_t) GSS_C_NO_CONTEXT) || !(context->ctx_flags & GSS_I_CTX_INITIALIZED)) { GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "Creating context w/ %s.\n", (initiator_cred_handle == GSS_C_NO_CREDENTIAL) ? "GSS_C_NO_CREDENTIAL" : "Credentials provided")); major_status = globus_i_gsi_gss_create_and_fill_context(&local_minor_status, &context, initiator_cred_handle, GSS_C_INITIATE, req_flags); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT); goto error_exit; } *context_handle_P = context; if (actual_mech_type != NULL) { *actual_mech_type = (gss_OID) gss_mech_globus_gssapi_openssl; } if (ret_flags != NULL) { *ret_flags = 0 ; } } else { /* first time there is no input token, but after that * there will always be one */ major_status = globus_i_gsi_gss_put_token(&local_minor_status, context, NULL, input_token); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); goto error_exit; } } switch (context->gss_state) { case(GSS_CON_ST_HANDSHAKE): /* do the handshake work */ major_status = globus_i_gsi_gss_handshake(&local_minor_status, context); if (major_status == GSS_S_CONTINUE_NEEDED) { break; } if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_HANDSHAKE); context->gss_state = GSS_CON_ST_DONE; break; } /* make sure we are talking to the correct server */ major_status = globus_i_gsi_gss_retrieve_peer(&local_minor_status, context, GSS_C_INITIATE); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT); context->gss_state = GSS_CON_ST_DONE; break; } local_result = globus_gsi_callback_get_cert_type( context->callback_data, &cert_type); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto error_exit; } /* * Need to check if the server is using a limited proxy. * And if that is acceptable here. * Caller tells us if it is not acceptable to * use a limited proxy. */ if ((context->req_flags & GSS_C_GLOBUS_DONT_ACCEPT_LIMITED_PROXY_FLAG) && GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type)) { major_status = GSS_S_UNAUTHORIZED; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_PROXY_VIOLATION, (_GGSL("Function set to not accept limited proxies"))); context->gss_state = GSS_CON_ST_DONE; break; } /* this is the mutual authentication test */ if (target_name != NULL) { major_status = gss_compare_name(&local_minor_status, context->peer_cred_handle->globusid, target_name, &rc); if (GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_NAME); context->gss_state = GSS_CON_ST_DONE; break; } else if(rc == GSS_NAMES_NOT_EQUAL) { char * expected_name; char * actual_name; if(g_OID_equal(((gss_name_desc*) target_name)->name_oid, GSS_C_NT_HOSTBASED_SERVICE)) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_AUTHZ_DENIED, (_GGSL("The expected name for the remote host (%s%s%s) does not match the authenticated " "name of the remote host (%s%s%s). This happens when the name in the host certificate does not match the information obtained from DNS and is often a DNS configuration problem."), target_name->service_name ? target_name->service_name : "", target_name->service_name ? "@" : "", target_name->host_name ? target_name->host_name : "unknown", context->peer_cred_handle->globusid->service_name ? context->peer_cred_handle->globusid->service_name : "", context->peer_cred_handle->globusid->service_name ? "@" : "", context->peer_cred_handle->globusid->host_name ? context->peer_cred_handle->globusid->host_name : "unknown")); } else { expected_name = ((gss_name_desc*) target_name)->x509n_oneline; actual_name = ((gss_name_desc*) context->peer_cred_handle->globusid)->x509n_oneline; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_AUTHZ_DENIED, (_GGSL("The name of the remote entity (%s), and the expected " "name for the remote entity (%s) do not match"), actual_name, expected_name)); } major_status = GSS_S_UNAUTHORIZED; context->gss_state = GSS_CON_ST_DONE; break; } } context->ret_flags |= GSS_C_MUTUAL_FLAG; context->ret_flags |= GSS_C_PROT_READY_FLAG; context->ret_flags |= GSS_C_INTEG_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_ANON_FLAG | GSS_C_DELEG_FLAG; if (GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type)) { context->ret_flags |= GSS_C_GLOBUS_RECEIVED_LIMITED_PROXY_FLAG; } # if LINK_WITH_INTERNAL_OPENSSL_API context->ret_flags |= GSS_C_TRANS_FLAG; # endif /* * IF we are talking to a real SSL server, * we don't want to do delegation, so we are done */ if (context->req_flags & GSS_C_GLOBUS_SSL_COMPATIBLE) { context->gss_state = GSS_CON_ST_DONE; break; } /* * If we have completed the handshake, but don't * have any more data to send, we can send the flag * now. i.e. fall through without break, * Otherwise, we will wait for the null byte * to get back in sync which we will ignore */ if (output_token->length != 0) { context->gss_state=GSS_CON_ST_FLAGS; break; } case(GSS_CON_ST_FLAGS): if (input_token->length > 0) { BIO_read(context->gss_sslbio, cbuf, 1); } /* send D if we want delegation, 0 otherwise */ if (context->req_flags & GSS_C_DELEG_FLAG) { BIO_write(context->gss_sslbio, "D", 1); context->gss_state = GSS_CON_ST_REQ; } else { BIO_write(context->gss_sslbio, "0", 1); context->gss_state = GSS_CON_ST_DONE; } break; case(GSS_CON_ST_REQ): local_result = globus_gsi_proxy_inquire_req( context->proxy_handle, context->gss_sslbio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_PROXY_NOT_RECEIVED); major_status = GSS_S_FAILURE; context->gss_state = GSS_CON_ST_DONE; goto error_exit; } local_result = globus_gsi_cred_get_cert_type( context->cred_handle->cred_handle, &cert_type); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_CREDENTIAL); major_status = GSS_S_FAILURE; context->gss_state = GSS_CON_ST_DONE; goto error_exit; } local_result = globus_gsi_proxy_handle_set_type( context->proxy_handle, (context->req_flags & GSS_C_GLOBUS_DELEGATE_LIMITED_PROXY_FLAG) ? GLOBUS_GSI_CERT_UTILS_TYPE_LIMITED_PROXY : GLOBUS_GSI_CERT_UTILS_TYPE_IMPERSONATION_PROXY); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->gss_state = GSS_CON_ST_DONE; goto exit; } local_result = globus_gsi_proxy_sign_req( context->proxy_handle, context->cred_handle->cred_handle, context->gss_sslbio); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSI_PROXY); major_status = GSS_S_FAILURE; context->gss_state = GSS_CON_ST_DONE; goto error_exit; } context->gss_state = GSS_CON_ST_DONE; break; case(GSS_CON_ST_CERT): ; case(GSS_CON_ST_DONE): ; } /* end of switch for gss_con_st */ local_major_status = globus_i_gsi_gss_get_token(&local_minor_status, context, NULL, output_token); if(GSS_ERROR(local_major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_TOKEN_FAIL); major_status = GSS_S_FAILURE; context->gss_state = GSS_CON_ST_DONE; goto error_exit; } /* some error occurred during switch */ if(GSS_ERROR(major_status)) { goto error_exit; } if (context->gss_state != GSS_CON_ST_DONE) { major_status |= GSS_S_CONTINUE_NEEDED; } else if(time_rec != NULL) { time_t lifetime; time_t current_time; major_status = globus_i_gsi_gss_get_context_goodtill( &local_minor_status, context, &lifetime); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GSS_CONTEXT); goto exit; } current_time = time(NULL); if(current_time > lifetime) { *time_rec = 0; } else { *time_rec = (OM_uint32) (lifetime - current_time); } } if (ret_flags != NULL) { *ret_flags = context->ret_flags; } GLOBUS_I_GSI_GSSAPI_DEBUG_FPRINTF( 2, (globus_i_gsi_gssapi_debug_fstream, "init_sec_context:major_status:%08x" ":gss_state:%d req_flags=%08x:ret_flags=%08x\n", (unsigned int) major_status, context->gss_state, (unsigned int) req_flags, (unsigned int) context->ret_flags)); goto exit; error_exit: gss_delete_sec_context(&local_minor_status, (gss_ctx_id_t *) &context, output_token); *context_handle_P = (gss_ctx_id_t) context; exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * @brief Inquire Sec Context by OID * @ingroup globus_gsi_gssapi_extensions */ OM_uint32 GSS_CALLCONV gss_inquire_sec_context_by_oid( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_OID desired_object, gss_buffer_set_t * data_set) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 local_minor_status; gss_ctx_id_desc * context = NULL; int found_index; int chain_index; int cert_count; X509_EXTENSION * extension; X509 * cert = NULL; STACK_OF(X509) * cert_chain = NULL; ASN1_OBJECT * asn1_desired_obj = NULL; ASN1_OCTET_STRING * asn1_oct_string; gss_buffer_desc data_set_buffer = GSS_C_EMPTY_BUFFER; globus_result_t local_result = GLOBUS_SUCCESS; unsigned char * tmp_ptr; static char * _function_name_ = "gss_inquire_sec_context_by_oid"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; /* parameter checking goes here */ if(minor_status == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid minor_status (NULL) passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(context_handle == GSS_C_NO_CONTEXT) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid context_handle passed to function"))); major_status = GSS_S_FAILURE; goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; context = (gss_ctx_id_desc *) context_handle; if(desired_object == GSS_C_NO_OID) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid desired_object passed to function"))); major_status = GSS_S_FAILURE; goto exit; } if(data_set == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid data_set (NULL) passed to function"))); major_status = GSS_S_FAILURE; goto exit; } *data_set = NULL; /* lock the context mutex */ globus_mutex_lock(&context->mutex); local_result = globus_gsi_callback_get_cert_depth(context->callback_data, &cert_count); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; goto unlock_exit; } if(cert_count == 0) { goto unlock_exit; } major_status = gss_create_empty_buffer_set(&local_minor_status, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } local_result = globus_gsi_callback_get_cert_chain( context->callback_data, &cert_chain); if(local_result != GLOBUS_SUCCESS) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_result, GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA); major_status = GSS_S_FAILURE; cert_chain = NULL; goto unlock_exit; } if(((gss_OID_desc *)desired_object)->length != gss_ext_x509_cert_chain_oid->length || memcmp(((gss_OID_desc *)desired_object)->elements, gss_ext_x509_cert_chain_oid->elements, gss_ext_x509_cert_chain_oid->length)) { /* figure out what object was asked for */ asn1_desired_obj = ASN1_OBJECT_new(); if(!asn1_desired_obj) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't create ASN1 object"))); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_desired_obj->length = ((gss_OID_desc *)desired_object)->length; asn1_desired_obj->data = ((gss_OID_desc *)desired_object)->elements; found_index = -1; for(chain_index = 0; chain_index < cert_count; chain_index++) { cert = sk_X509_value(cert_chain, chain_index); data_set_buffer.value = NULL; data_set_buffer.length = 0; found_index = X509_get_ext_by_OBJ(cert, asn1_desired_obj, found_index); if(found_index >= 0) { extension = X509_get_ext(cert, found_index); if(!extension) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get extension at index %d " "from cert in credential."), found_index)); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_oct_string = X509_EXTENSION_get_data(extension); if(!asn1_oct_string) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Couldn't get cert extension in the form of an " "ASN1 octet string."))); major_status = GSS_S_FAILURE; goto unlock_exit; } asn1_oct_string = ASN1_OCTET_STRING_dup(asn1_oct_string); if(!asn1_oct_string) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to make copy of extension data"))); major_status = GSS_S_FAILURE; goto unlock_exit; } data_set_buffer.value = asn1_oct_string->data; data_set_buffer.length = asn1_oct_string->length; OPENSSL_free(asn1_oct_string); major_status = gss_add_buffer_set_member( &local_minor_status, &data_set_buffer, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } } } } else { for(chain_index = 0; chain_index < cert_count; chain_index++) { int certlen; cert = sk_X509_value(cert_chain, chain_index); certlen = i2d_X509(cert, NULL); data_set_buffer.length = certlen; if (certlen < 0) { GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to serialize certificate"))); major_status = GSS_S_FAILURE; goto unlock_exit; } tmp_ptr = realloc(data_set_buffer.value, data_set_buffer.length); if(tmp_ptr == NULL) { GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status); major_status = GSS_S_FAILURE; goto unlock_exit; } data_set_buffer.value = tmp_ptr; if(i2d_X509(cert,&tmp_ptr) < 0) { free(data_set_buffer.value); GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL, (_GGSL("Failed to serialize certificate"))); major_status = GSS_S_FAILURE; goto unlock_exit; } major_status = gss_add_buffer_set_member( &local_minor_status, &data_set_buffer, data_set); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER); goto unlock_exit; } } if(data_set_buffer.value != NULL) { free(data_set_buffer.value); } } unlock_exit: /* unlock the context mutex */ globus_mutex_unlock(&context->mutex); exit: if (asn1_desired_obj != NULL) { ASN1_OBJECT_free(asn1_desired_obj); } if(cert_chain != NULL) { sk_X509_pop_free(cert_chain, X509_free); } GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }
/** * Module activation */ static int globus_l_gsi_gssapi_activate(void) { int rc = GLOBUS_SUCCESS; char * tmp_string; char * gsi_conf_data; rc = globus_module_activate(GLOBUS_COMMON_MODULE); if (rc != GLOBUS_SUCCESS) { goto common_activate_fail; } rc = globus_l_gsi_gssapi_read_config(&gsi_conf_data); if (rc != GLOBUS_SUCCESS) { goto read_conf_data_fail; } if (gsi_conf_data == NULL) { gsi_conf_data = strdup(globus_l_gsi_conf_string); if (gsi_conf_data == NULL) { rc = GLOBUS_FAILURE; goto strdup_default_data_fail; } } rc = globus_l_gsi_gssapi_parse_config(gsi_conf_data); if (rc != GLOBUS_SUCCESS) { goto parse_conf_data_fail; } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_DEBUG_LEVEL"); if(tmp_string != GLOBUS_NULL) { globus_i_gsi_gssapi_debug_level = atoi(tmp_string); if(globus_i_gsi_gssapi_debug_level < 0) { globus_i_gsi_gssapi_debug_level = 0; } } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_DEBUG_FILE"); if(tmp_string != GLOBUS_NULL) { globus_i_gsi_gssapi_debug_fstream = fopen(tmp_string, "a"); if(!globus_i_gsi_gssapi_debug_fstream) { rc = GLOBUS_FAILURE; goto debug_open_fail; } } else { globus_i_gsi_gssapi_debug_fstream = stderr; if(!globus_i_gsi_gssapi_debug_fstream) { rc = GLOBUS_FAILURE; goto debug_stderr_fail; } } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_FORCE_TLS"); if(tmp_string != GLOBUS_NULL && (strcasecmp(tmp_string, "true") == 0 || strcasecmp(tmp_string, "yes") == 0 || strcmp(tmp_string, "1") == 0)) { globus_i_gsi_gssapi_force_tls = 1; } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_NAME_COMPATIBILITY"); if(tmp_string != NULL) { if (strcmp(tmp_string, "STRICT_GT2") == 0) { gss_i_name_compatibility_mode = GSS_I_COMPATIBILITY_STRICT_GT2; } else if (strcmp(tmp_string, "STRICT_RFC2818") == 0) { gss_i_name_compatibility_mode = GSS_I_COMPATIBILITY_STRICT_RFC2818; } else if (strcmp(tmp_string, "HYBRID") == 0) { gss_i_name_compatibility_mode = GSS_I_COMPATIBILITY_HYBRID; } else { GLOBUS_I_GSI_GSSAPI_DEBUG_PRINT( 1, (_GGSL("Unknown GLOBUS_GSSAPI_NAME_COMPATIBILITY value: %s\n"), tmp_string)); gss_i_name_compatibility_mode = GSS_I_COMPATIBILITY_HYBRID; } } else { gss_i_name_compatibility_mode = GSS_I_COMPATIBILITY_HYBRID; } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_CIPHERS"); if (tmp_string != NULL) { globus_i_gsi_gssapi_cipher_list = tmp_string; } tmp_string = globus_module_getenv("GLOBUS_GSSAPI_SERVER_CIPHER_ORDER"); if (tmp_string != NULL) { if (strcasecmp(tmp_string, "true") == 0 || strcasecmp(tmp_string, "yes") == 0 || strcmp(tmp_string, "1") == 0) { globus_i_gsi_gssapi_server_cipher_order = GLOBUS_TRUE; } } rc = globus_module_activate(GLOBUS_OPENSSL_MODULE); if (rc != GLOBUS_SUCCESS) { goto activate_openssl_module_fail; } rc = globus_module_activate(GLOBUS_GSI_PROXY_MODULE); if (rc != GLOBUS_SUCCESS) { goto activate_gsi_proxy_fail; } rc = globus_module_activate(GLOBUS_GSI_CALLBACK_MODULE); if (rc != GLOBUS_SUCCESS) { goto activate_gsi_callback_fail; } GLOBUS_I_GSI_GSSAPI_INTERNAL_DEBUG_EXIT; globus_i_gssapi_active = GLOBUS_TRUE; if (rc != GLOBUS_SUCCESS) { activate_gsi_callback_fail: globus_module_deactivate(GLOBUS_GSI_PROXY_MODULE); activate_gsi_proxy_fail: globus_module_deactivate(GLOBUS_OPENSSL_MODULE); activate_openssl_module_fail: if (globus_i_gsi_gssapi_debug_fstream != NULL && globus_i_gsi_gssapi_debug_fstream != stderr) { fclose(globus_i_gsi_gssapi_debug_fstream); globus_i_gsi_gssapi_debug_fstream = NULL; } } debug_stderr_fail: debug_open_fail: parse_conf_data_fail: strdup_default_data_fail: free(gsi_conf_data); read_conf_data_fail: if (rc != GLOBUS_SUCCESS) { globus_module_deactivate(GLOBUS_COMMON_MODULE); } common_activate_fail: return rc; }
/** * Get the proxy group from a GSS name. * * This function will get the proxy group from a GSS name structure. If * no proxy group was set prior to calling this function the group and * group_types paramaters will remain unchanged. * * @param minor_status * The minor status returned by this function. This paramter * will be 0 upon success. * @param name * The GSS name from which the group information is extracted. * @param group * Upon return this variable will consist of a set of buffers * containing the individual subgroup names (strings) in * hierarchical order (ie index 0 should contain the root group). * @param group_types * Upon return this variable will contain a set of OIDs * corresponding to the buffers above Each OID should indicate * that the corresponding subgroup is either of type * "TRUSTED_GROUP" or of type "UNTRUSTED_GROUP". * * @return * GSS_S_COMPLETE upon success * GSS_S_BAD_NAME if the name was found to be faulty * GSS_S_FAILURE upon general failure */ OM_uint32 GSS_CALLCONV gss_get_group( OM_uint32 * minor_status, const gss_name_t name, gss_buffer_set_t * group, gss_OID_set * group_types) { OM_uint32 major_status = GSS_S_COMPLETE; OM_uint32 tmp_minor_status; int i; int num_subgroups; gss_name_desc * internal_name; char * subgroup; gss_buffer_desc buffer; static char * _function_name_ = "gss_get_group"; GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER; internal_name = (gss_name_desc *) name; if(minor_status == NULL) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, major_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("NULL parameter minor_status passed to function: %s"), _function_name_)); goto exit; } *minor_status = (OM_uint32) GLOBUS_SUCCESS; if(name == GSS_C_NO_NAME) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, major_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid group name passed to function: %s"), _function_name_)); goto exit; } if(group == NULL) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, major_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid group passed to function: %s"), _function_name_)); goto exit; } if(group_types == NULL) { major_status = GSS_S_FAILURE; GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, major_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT, (_GGSL("Invalid group types passed to function: %s"), _function_name_)); goto exit; } num_subgroups = sk_num(internal_name->group); if(internal_name->group == NULL || num_subgroups == 0) { goto exit; } if(internal_name->group_types == NULL) { GLOBUS_GSI_GSSAPI_ERROR_RESULT( minor_status, GLOBUS_GSI_GSSAPI_ERROR_BAD_NAME); major_status = GSS_S_BAD_NAME; goto exit; } major_status = gss_create_empty_buffer_set(local_minor_status, group); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP); goto exit; } major_status = gss_create_empty_oid_set(local_minor_status, group_types); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP); goto release_buffer; } for(++index = 0; ++index < num_subgroups; ++index) { subgroup = sk_value(internal_name->group, ++index); buffer.value = (void *) subgroup; buffer.length = strlen(subgroup) + 1; major_status = gss_add_buffer_set_member(&local_minor_status, &buffer, group); if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP); goto release_oid; } if(ASN1_BIT_STRING_get_bit(internal_name->group_types, index)) { major_status = gss_add_oid_set_member( &local_minor_status, (gss_OID) gss_untrusted_group, group_types); } else { major_status = gss_add_oid_set_member( &local_minor_status, (gss_OID) gss_trusted_group, group_types); } if(GSS_ERROR(major_status)) { GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT( minor_status, local_minor_status, GLOBUS_GSI_GSSAPI_ERROR_WITH_GROUP); goto release_oid; } } goto exit; release_oid: gss_release_oid_set(&local_minor_status, group_types); release_buffer: gss_release_buffer_set(&local_minor_status, group); exit: GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT; return major_status; }