OM_uint32 ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) { gss_buffer_desc gssbuf; gss_name_t gssname; OM_uint32 status; gss_OID_set oidset; gssbuf.value = (void *) name; gssbuf.length = strlen(gssbuf.value); gss_create_empty_oid_set(&status, &oidset); gss_add_oid_set_member(&status, ctx->oid, &oidset); ctx->major = gss_import_name(&ctx->minor, &gssbuf, GSS_C_NT_USER_NAME, &gssname); if (!ctx->major) ctx->major = gss_acquire_cred(&ctx->minor, gssname, 0, oidset, GSS_C_INITIATE, &ctx->client_creds, NULL, NULL); gss_release_name(&status, &gssname); gss_release_oid_set(&status, &oidset); if (ctx->major) ssh_gssapi_error(ctx); return(ctx->major); }
static void acquire_release_loop(gss_name_t name, int counter, gss_cred_usage_t usage) { OM_uint32 maj_stat, min_stat; gss_cred_id_t cred; int i; for (i = 0; i < counter; i++) { maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, usage, &cred, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "aquire %d %d != GSS_S_COMPLETE", i, (int)maj_stat); maj_stat = gss_release_cred(&min_stat, &cred); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "release %d %d != GSS_S_COMPLETE", i, (int)maj_stat); } }
/* Privileged (called from ssh_gssapi_server_ctx) */ static OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx) { OM_uint32 status; char lname[NI_MAXHOST]; gss_OID_set oidset; gss_create_empty_oid_set(&status, &oidset); gss_add_oid_set_member(&status, ctx->oid, &oidset); if (gethostname(lname, sizeof(lname))) { gss_release_oid_set(&status, &oidset); return (-1); } if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { gss_release_oid_set(&status, &oidset); return (ctx->major); } if ((ctx->major = gss_acquire_cred(&ctx->minor, ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) ssh_gssapi_error(ctx); gss_release_oid_set(&status, &oidset); return (ctx->major); }
static void copy_cred(void) { OM_uint32 major_status, minor_status; gss_cred_id_t cred_handle; OM_uint32 time_rec; major_status = gss_acquire_cred(&minor_status, GSS_C_NO_NAME, 0, NULL, GSS_C_INITIATE, &cred_handle, NULL, &time_rec); if (GSS_ERROR(major_status)) errx(1, "acquire_cred failed"); print_time(time_rec); test_add(cred_handle); test_add(cred_handle); test_add(cred_handle); major_status = gss_release_cred(&minor_status, &cred_handle); if (GSS_ERROR(major_status)) errx(1, "release_cred failed"); }
static int server_acquire_creds(char *service_name, gss_cred_id_t *server_creds) { gss_buffer_desc name_buf; gss_name_t server_name; OM_uint32 maj_stat, min_stat; name_buf.value = service_name; name_buf.length = strlen(name_buf.value) + 1; maj_stat = gss_import_name(&min_stat, &name_buf, (gss_OID) gss_nt_service_name, &server_name); if (maj_stat != GSS_S_COMPLETE) { display_status("importing name", maj_stat, min_stat); return -1; } maj_stat = gss_acquire_cred(&min_stat, server_name, 0, GSS_C_NO_OID_SET, GSS_C_ACCEPT, server_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { display_status("acquiring credentials", maj_stat, min_stat); return -1; } (void) gss_release_name(&min_stat, &server_name); return 0; }
int main() { OM_uint32 minor_status; OM_uint32 major_status; gss_cred_id_t cred; char * error_str; int rc = EXIT_SUCCESS; printf("1..1\n"); globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE); globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE); major_status = gss_acquire_cred( &minor_status, NULL, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_BOTH, &cred, NULL, NULL); if(GSS_ERROR(major_status)) { globus_gss_assist_display_status_str(&error_str, NULL, major_status, minor_status, 0); fprintf(stderr, "\nLINE %d ERROR: %s\n", __LINE__, error_str); free(error_str); rc = EXIT_FAILURE; goto fail; } major_status = gss_release_cred( &minor_status, &cred); if(GSS_ERROR(major_status)) { globus_gss_assist_display_status_str(&error_str, NULL, major_status, minor_status, 0); fprintf(stderr, "\nLINE %d ERROR: %s\n", __LINE__, error_str); free(error_str); rc = EXIT_FAILURE; goto fail; } fail: printf("%s gssapi_acquire_test\n", (rc == EXIT_SUCCESS) ? "ok" : "not ok"); globus_module_deactivate_all(); return rc; }
int gsslib_acquire_client_credentials(gss_cred_id_t *client_creds) { gss_name_t client_name = NULL; OM_uint32 maj_stat, min_stat; int cc=0; gsslib_reset_error(); /* * get credentials for the service */ maj_stat = gss_acquire_cred(&min_stat, client_name, 0, GSS_C_NULL_OID_SET, GSS_C_INITIATE, client_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { gsslib_display_status(MSG_GSS_DISPLAYSTATUS_ACQUIRINGCREDENTIALS , maj_stat, min_stat); return -1; } if (client_name) (void) gss_release_name(&min_stat, &client_name); return cc; }
static bool mag_acquire_creds(request_rec *req, struct mag_config *cfg, gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t *creds, gss_OID_set *actual_mechs) { uint32_t maj, min; #ifdef HAVE_CRED_STORE gss_const_key_value_set_t store = cfg->cred_store; maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE, desired_mechs, cred_usage, store, creds, actual_mechs, NULL); #else maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE, desired_mechs, cred_usage, creds, actual_mechs, NULL); #endif if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, "%s", mag_error(req, "gss_acquire_cred[_from]() " "failed to get server creds", maj, min)); return false; } return true; }
/*-------------*/ static int acquire_credentials (gss_name_t *server_name, gss_cred_id_t *server_creds) { OM_uint32 major_status = 0, minor_status = 0; char *envp; if ((envp = getenv("KRB5_KTNAME"))) LOG(log_debug, logtype_uams, "acquire credentials: acquiring credentials (uid = %d, keytab = %s)", (int)geteuid(), envp); else LOG(log_debug, logtype_uams, "acquire credentials: acquiring credentials (uid = %d) - $KRB5_KTNAME not found in env", (int)geteuid()); /* * Acquire credentials usable for accepting context negotiations. * Credentials are for server_name, have an indefinite lifetime, * have no specific mechanisms, are to be used for accepting context * negotiations and are to be placed in server_creds. * We don't care about the mechanisms or about the time for which they are valid. */ major_status = gss_acquire_cred( &minor_status, *server_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, server_creds, NULL, NULL ); if (major_status != GSS_S_COMPLETE) { log_status( "acquire_cred", major_status, minor_status ); return 1; } return 0; }
int zmq::gssapi_mechanism_base_t::acquire_credentials (char * service_name_, gss_cred_id_t * cred_) { OM_uint32 maj_stat; OM_uint32 min_stat; gss_name_t server_name; gss_buffer_desc name_buf; name_buf.value = service_name_; name_buf.length = strlen ((char *) name_buf.value) + 1; maj_stat = gss_import_name (&min_stat, &name_buf, GSS_C_NT_HOSTBASED_SERVICE, &server_name); if (maj_stat != GSS_S_COMPLETE) return -1; maj_stat = gss_acquire_cred (&min_stat, server_name, 0, GSS_C_NO_OID_SET, GSS_C_ACCEPT, cred_, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) return -1; gss_release_name(&min_stat, &server_name); return 0; }
/* Privileged (called from ssh_gssapi_server_ctx) */ static OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx) { OM_uint32 status; char lname[NI_MAXHOST]; gss_OID_set oidset; if (options.gss_strict_acceptor) { gss_create_empty_oid_set(&status, &oidset); gss_add_oid_set_member(&status, ctx->oid, &oidset); if (gethostname(lname, MAXHOSTNAMELEN)) { gss_release_oid_set(&status, &oidset); return (-1); } if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { gss_release_oid_set(&status, &oidset); return (ctx->major); } if ((ctx->major = gss_acquire_cred(&ctx->minor, ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) ssh_gssapi_error(ctx); gss_release_oid_set(&status, &oidset); return (ctx->major); } else { ctx->name = GSS_C_NO_NAME; ctx->creds = GSS_C_NO_CREDENTIAL; } return GSS_S_COMPLETE; }
static void acquire_add_release_add(gss_name_t name, gss_cred_usage_t usage) { OM_uint32 maj_stat, min_stat; gss_cred_id_t cred, cred2, cred3; maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, usage, &cred, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "aquire %d != GSS_S_COMPLETE", (int)maj_stat); maj_stat = gss_add_cred(&min_stat, cred, GSS_C_NO_NAME, GSS_KRB5_MECHANISM, usage, GSS_C_INDEFINITE, GSS_C_INDEFINITE, &cred2, NULL, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat); maj_stat = gss_release_cred(&min_stat, &cred); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "release %d != GSS_S_COMPLETE", (int)maj_stat); maj_stat = gss_add_cred(&min_stat, cred2, GSS_C_NO_NAME, GSS_KRB5_MECHANISM, GSS_C_BOTH, GSS_C_INDEFINITE, GSS_C_INDEFINITE, &cred3, NULL, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "add_cred 2 %d != GSS_S_COMPLETE", (int)maj_stat); maj_stat = gss_release_cred(&min_stat, &cred2); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat); maj_stat = gss_release_cred(&min_stat, &cred3); if (maj_stat != GSS_S_COMPLETE) gss_err(1, min_stat, "release 3 %d != GSS_S_COMPLETE", (int)maj_stat); }
int authenticate_gss_server_init(const char *service, gss_server_state *state) { OM_uint32 maj_stat; OM_uint32 min_stat; size_t service_len; gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER; int ret = AUTH_GSS_COMPLETE; state->context = GSS_C_NO_CONTEXT; state->server_name = GSS_C_NO_NAME; state->client_name = GSS_C_NO_NAME; state->server_creds = GSS_C_NO_CREDENTIAL; state->client_creds = GSS_C_NO_CREDENTIAL; state->username = NULL; state->targetname = NULL; state->response = NULL; state->gss_flags = 0; // Server name may be empty which means we aren't going to create our own creds service_len = strlen(service); if (service_len != 0) { // Import server name first name_token.length = strlen(service); name_token.value = (char *)service; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &state->server_name); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } // Get credentials maj_stat = gss_acquire_cred(&min_stat, state->server_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &state->server_creds, NULL, NULL); if (GSS_ERROR(maj_stat)) { set_gss_error(maj_stat, min_stat); ret = AUTH_GSS_ERROR; goto end; } } end: return ret; }
bool_t Svcauth_gss_acquire_cred(void) { OM_uint32 maj_stat, min_stat; maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &svcauth_gss_creds, NULL, NULL); if(maj_stat != GSS_S_COMPLETE) { return (FALSE); } return (TRUE); }
static gss_cred_id_t acquire_cred_service(const char *service, gss_OID nametype, gss_OID_set oidset, int flags) { OM_uint32 major_status, minor_status; gss_cred_id_t cred_handle; OM_uint32 time_rec; gss_buffer_desc name_buffer; gss_name_t name = GSS_C_NO_NAME; if (service) { name_buffer.value = rk_UNCONST(service); name_buffer.length = strlen(service); major_status = gss_import_name(&minor_status, &name_buffer, nametype, &name); if (GSS_ERROR(major_status)) errx(1, "import_name failed"); } major_status = gss_acquire_cred(&minor_status, name, 0, oidset, flags, &cred_handle, NULL, &time_rec); if (GSS_ERROR(major_status)) { warnx("acquire_cred failed: %s", gssapi_err(major_status, minor_status, GSS_C_NO_OID)); } else { print_time(time_rec); gss_release_cred(&minor_status, &cred_handle); } if (name != GSS_C_NO_NAME) gss_release_name(&minor_status, &name); if (GSS_ERROR(major_status)) exit(1); return cred_handle; }
static OM_uint32 acceptor_approved(void *userptr, gss_name_t target_name, const gss_cred_id_t cred_handle, gss_OID mech) { OM_uint32 junk, ret; gss_OID_set oidset; if (cred_handle) { int present = 0; ret = gss_inquire_cred(&junk, cred_handle, NULL, NULL, NULL, &oidset); if (ret != GSS_S_COMPLETE) return ret; ret = gss_test_oid_set_member(&junk, mech, oidset, &present); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE || present == 0) return GSS_S_FAILURE; } else { gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; if (target_name == GSS_C_NO_NAME) return GSS_S_COMPLETE; gss_create_empty_oid_set(&junk, &oidset); gss_add_oid_set_member(&junk, mech, &oidset); ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, GSS_C_ACCEPT, &cred, NULL, NULL); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE) return ret; gss_release_cred(&junk, &cred); } return GSS_S_COMPLETE; }
static bool_t svcauth_gss_acquire_cred(void) { OM_uint32 maj_stat, min_stat; log_debug("in svcauth_gss_acquire_cred()"); maj_stat = gss_acquire_cred(&min_stat, _svcauth_gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &_svcauth_gss_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_acquire_cred", maj_stat, min_stat); return (FALSE); } return (TRUE); }
int gssd_acquire_cred(char *server_name, const gss_OID oid) { gss_buffer_desc name; gss_name_t target_name; u_int32_t maj_stat, min_stat; u_int32_t ignore_maj_stat, ignore_min_stat; gss_buffer_desc pbuf; /* If server_name is NULL, get cred for GSS_C_NO_NAME */ if (server_name == NULL) { target_name = GSS_C_NO_NAME; } else { name.value = (void *)server_name; name.length = strlen(server_name); maj_stat = gss_import_name(&min_stat, &name, oid, &target_name); if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); return (FALSE); } } maj_stat = gss_acquire_cred(&min_stat, target_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &gssd_creds, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid); ignore_maj_stat = gss_display_name(&ignore_min_stat, target_name, &pbuf, NULL); if (ignore_maj_stat == GSS_S_COMPLETE) { printerr(1, "Unable to obtain credentials for '%.*s'\n", pbuf.length, pbuf.value); ignore_maj_stat = gss_release_buffer(&ignore_min_stat, &pbuf); } } ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name); return (maj_stat == GSS_S_COMPLETE); }
bool svcauth_gss_acquire_cred(void) { OM_uint32 maj_stat, min_stat; int64_t now; OM_uint32 timerec; gss_cred_id_t old_creds, ancient_creds; now = get_time_fast(); if (svcauth_gss_creds && (!svcauth_gss_creds_expires || svcauth_gss_creds_expires > now)) return (true); mutex_lock(&svcauth_gss_creds_lock); if (svcauth_gss_creds && (!svcauth_gss_creds_expires || svcauth_gss_creds_expires > now)) { maj_stat = GSS_S_COMPLETE; } else { ancient_creds = svcauth_prev_gss_creds; old_creds = svcauth_gss_creds; timerec = 0; now = get_time_fast(); maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &svcauth_gss_creds, NULL, &timerec); if (maj_stat == GSS_S_COMPLETE) { if (timerec == GSS_C_INDEFINITE) svcauth_gss_creds_expires = 0; else svcauth_gss_creds_expires = now + timerec; if (old_creds) { svcauth_prev_gss_creds = old_creds; } if (ancient_creds) { (void) gss_release_cred(&min_stat, &ancient_creds); } } } mutex_unlock(&svcauth_gss_creds_lock); if (maj_stat != GSS_S_COMPLETE) return (false); return (true); }
uint32_t sapgss_acquire_cred( uint32_t *minor_status, gss_name_t desired_name, uint32_t time_req, sapgss_OID_set desired_mechs, gss_cred_usage_t cred_usage, gss_cred_id_t *output_cred_handle, sapgss_OID_set *actual_mechs, uint32_t *time_rec) { gss_OID_set desired_mechs_loc; gss_OID_set actual_mechs_loc; uint32_t major_status, dummy; int ret; memset(&desired_mechs_loc, 0, sizeof(desired_mechs_loc)); memset(&actual_mechs_loc, 0, sizeof(actual_mechs_loc)); ret = gss_OID_set_sap_to_loc(desired_mechs, &desired_mechs_loc); if (ret != 0) { *minor_status = ret; return GSS_S_FAILURE; } major_status = gss_acquire_cred(minor_status, desired_name, time_req, desired_mechs_loc, cred_usage, output_cred_handle, &actual_mechs_loc, time_rec); /* Meet the gss_OID_set_sap_to_loc contract and free desired_mechs_loc */ gss_OID_set_loc_release(&desired_mechs_loc); /* Must inquire_cred to force resolution for the krb5 mech */ if (major_status != 0) return major_status; (void)gss_inquire_cred(&dummy, *output_cred_handle, NULL, NULL, NULL, &actual_mechs_loc); ret = gss_OID_set_loc_to_sap(actual_mechs_loc, actual_mechs); if (ret != 0) { *minor_status = ret; return GSS_S_FAILURE; } return major_status; }
static OM_uint32 acceptor_approved(gss_name_t target_name, gss_OID mech) { gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; gss_OID_set oidset; OM_uint32 junk, ret; if (target_name == GSS_C_NO_NAME) return GSS_S_COMPLETE; gss_create_empty_oid_set(&junk, &oidset); gss_add_oid_set_member(&junk, mech, &oidset); ret = gss_acquire_cred(&junk, target_name, GSS_C_INDEFINITE, oidset, GSS_C_ACCEPT, &cred, NULL, NULL); gss_release_oid_set(&junk, &oidset); if (ret != GSS_S_COMPLETE) return ret; gss_release_cred(&junk, &cred); return GSS_S_COMPLETE; }
int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid) { u_int maj_stat, min_stat; gss_cred_id_t credh; gss_OID_set_desc desired_mechs; krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_MD4 }; int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]); /* We only care about getting a krb5 cred */ desired_mechs.count = 1; desired_mechs.elements = &krb5oid; maj_stat = gss_acquire_cred(&min_stat, NULL, 0, &desired_mechs, GSS_C_INITIATE, &credh, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { if (get_verbosity() > 0) pgsserr("gss_acquire_cred", maj_stat, min_stat, &krb5oid); return -1; } maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid, num_enctypes, &enctypes); if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_set_allowable_enctypes", maj_stat, min_stat, &krb5oid); gss_release_cred(&min_stat, &credh); return -1; } sec->cred = credh; return 0; }
/* * Given a service name, imports it and acquires credentials for it, storing * them in the second argument. Returns true on success and false on failure, * logging an error message. * * Normally, you don't want to do this; instead, normally you want to allow * the underlying GSS-API library choose the appropriate credentials from a * keytab for each incoming connection. */ static bool acquire_creds(char *service, gss_cred_id_t *creds) { gss_buffer_desc buffer; gss_name_t name; OM_uint32 major, minor; buffer.value = service; buffer.length = strlen(buffer.value) + 1; major = gss_import_name(&minor, &buffer, GSS_C_NT_USER_NAME, &name); if (major != GSS_S_COMPLETE) { warn_gssapi("while importing name", major, minor); return false; } major = gss_acquire_cred(&minor, name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, creds, NULL, NULL); if (major != GSS_S_COMPLETE) { warn_gssapi("while acquiring credentials", major, minor); return false; } gss_release_name(&minor, &name); return true; }
isc_result_t dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate, gss_cred_id_t *cred) { #ifdef GSSAPI isc_buffer_t namebuf; gss_name_t gname; gss_buffer_desc gnamebuf; unsigned char array[DNS_NAME_MAXTEXT + 1]; OM_uint32 gret, minor; gss_OID_set mechs; OM_uint32 lifetime; gss_cred_usage_t usage; char buf[1024]; REQUIRE(cred != NULL && *cred == NULL); /* * XXXSRA In theory we could use GSS_C_NT_HOSTBASED_SERVICE * here when we're in the acceptor role, which would let us * default the hostname and use a compiled in default service * name of "DNS", giving one less thing to configure in * named.conf. Unfortunately, this creates a circular * dependency due to DNS-based realm lookup in at least one * GSSAPI implementation (Heimdal). Oh well. */ if (name != NULL) { isc_buffer_init(&namebuf, array, sizeof(array)); name_to_gbuffer(name, &namebuf, &gnamebuf); gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname); if (gret != GSS_S_COMPLETE) { check_config((char *)array); gss_log(3, "failed gss_import_name: %s", gss_error_tostring(gret, minor, buf, sizeof(buf))); return (ISC_R_FAILURE); } } else gname = NULL; /* Get the credentials. */ if (gname != NULL) gss_log(3, "acquiring credentials for %s", (char *)gnamebuf.value); else { /* XXXDCL does this even make any sense? */ gss_log(3, "acquiring credentials for ?"); } if (initiate) usage = GSS_C_INITIATE; else usage = GSS_C_ACCEPT; gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE, &mech_oid_set, usage, cred, &mechs, &lifetime); if (gret != GSS_S_COMPLETE) { gss_log(3, "failed to acquire %s credentials for %s: %s", initiate ? "initiate" : "accept", (char *)gnamebuf.value, gss_error_tostring(gret, minor, buf, sizeof(buf))); check_config((char *)array); return (ISC_R_FAILURE); } gss_log(4, "acquired %s credentials for %s", initiate ? "initiate" : "accept", (char *)gnamebuf.value); log_cred(*cred); return (ISC_R_SUCCESS); #else UNUSED(name); UNUSED(initiate); UNUSED(cred); return (ISC_R_NOTIMPLEMENTED); #endif }
int main(int argc, char **argv) { int i, s, done, print_body, gssapi_done, gssapi_started, optidx = 0; const char *host, *page; struct http_req req; char *headers[99]; /* XXX */ int num_headers; krb5_storage *sp; gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL; gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT; gss_name_t server = GSS_C_NO_NAME; gss_OID mech_oid, cred_mech_oid; OM_uint32 flags; OM_uint32 maj_stat, min_stat; setprogname(argv[0]); if(getarg(http_args, num_http_args, argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; mech_oid = select_mech(mech); if (cred_mech_str) cred_mech_oid = select_mech(cred_mech_str); else cred_mech_oid = mech_oid; if (argc != 1 && argc != 2) errx(1, "usage: %s host [page]", getprogname()); host = argv[0]; if (argc == 2) page = argv[1]; else page = "/"; flags = 0; if (delegate_flag) flags |= GSS_C_DELEG_FLAG; if (policy_flag) flags |= GSS_C_DELEG_POLICY_FLAG; if (mutual_flag) flags |= GSS_C_MUTUAL_FLAG; done = 0; num_headers = 0; gssapi_done = 0; gssapi_started = 0; if (client_str) { gss_buffer_desc name_buffer; gss_name_t name; gss_OID_set mechset = GSS_C_NO_OID_SET; name_buffer.value = client_str; name_buffer.length = strlen(client_str); maj_stat = gss_import_name(&min_stat, &name_buffer, GSS_C_NT_USER_NAME, &name); if (maj_stat) errx(1, "failed to import name"); if (cred_mech_oid) { gss_create_empty_oid_set(&min_stat, &mechset); gss_add_oid_set_member(&min_stat, cred_mech_oid, &mechset); } maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, mechset, GSS_C_INITIATE, &client_cred, NULL, NULL); gss_release_name(&min_stat, &name); gss_release_oid_set(&min_stat, &mechset); if (maj_stat) errx(1, "failed to find cred of name %s", client_str); } { gss_buffer_desc name_token; char *name; asprintf(&name, "%s@%s", gss_service, host); name_token.length = strlen(name); name_token.value = name; maj_stat = gss_import_name(&min_stat, &name_token, GSS_C_NT_HOSTBASED_SERVICE, &server); if (GSS_ERROR(maj_stat)) gss_err (1, min_stat, "gss_inport_name: %s", name); free(name); } s = do_connect(host, port_str); if (s < 0) errx(1, "connection failed"); sp = krb5_storage_from_fd(s); if (sp == NULL) errx(1, "krb5_storage_from_fd"); do { print_body = 0; http_query(sp, host, page, headers, num_headers, &req); for (i = 0 ; i < num_headers; i++) free(headers[i]); num_headers = 0; if (strstr(req.response, " 200 ") != NULL) { print_body = 1; done = 1; } else if (strstr(req.response, " 401 ") != NULL) { if (http_find_header(&req, "WWW-Authenticate:") == NULL) errx(1, "Got %s but missed `WWW-Authenticate'", req.response); } if (!gssapi_done) { const char *h = http_find_header(&req, "WWW-Authenticate:"); if (h == NULL) errx(1, "Got %s but missed `WWW-Authenticate'", req.response); if (strncasecmp(h, "Negotiate", 9) == 0) { gss_buffer_desc input_token, output_token; if (verbose_flag) printf("Negotiate found\n"); i = 9; while(h[i] && isspace((unsigned char)h[i])) i++; if (h[i] != '\0') { size_t len = strlen(&h[i]); int slen; if (len == 0) errx(1, "invalid Negotiate token"); input_token.value = emalloc(len); slen = base64_decode(&h[i], input_token.value); if (slen < 0) errx(1, "invalid base64 Negotiate token %s", &h[i]); input_token.length = slen; } else { if (gssapi_started) errx(1, "Negotiate already started"); gssapi_started = 1; input_token.length = 0; input_token.value = NULL; } if (strstr(req.response, " 200 ") != NULL) sleep(1); maj_stat = gss_init_sec_context(&min_stat, client_cred, &context_hdl, server, mech_oid, flags, 0, GSS_C_NO_CHANNEL_BINDINGS, &input_token, NULL, &output_token, NULL, NULL); if (maj_stat == GSS_S_CONTINUE_NEEDED) { } else if (maj_stat == GSS_S_COMPLETE) { gss_name_t targ_name, src_name; gss_buffer_desc name_buffer; gss_OID mech_type; gssapi_done = 1; maj_stat = gss_inquire_context(&min_stat, context_hdl, &src_name, &targ_name, NULL, &mech_type, NULL, NULL, NULL); if (GSS_ERROR(maj_stat)) gss_err (1, min_stat, "gss_inquire_context"); printf("Negotiate done: %s\n", mech); maj_stat = gss_display_name(&min_stat, src_name, &name_buffer, NULL); if (GSS_ERROR(maj_stat)) gss_print_errors(min_stat); else printf("Source: %.*s\n", (int)name_buffer.length, (char *)name_buffer.value); gss_release_buffer(&min_stat, &name_buffer); maj_stat = gss_display_name(&min_stat, targ_name, &name_buffer, NULL); if (GSS_ERROR(maj_stat)) gss_print_errors(min_stat); else printf("Target: %.*s\n", (int)name_buffer.length, (char *)name_buffer.value); gss_release_name(&min_stat, &targ_name); gss_release_buffer(&min_stat, &name_buffer); } else { gss_err (1, min_stat, "gss_init_sec_context"); } if (output_token.length) { char *neg_token; base64_encode(output_token.value, (int)output_token.length, &neg_token); asprintf(&headers[0], "Authorization: Negotiate %s", neg_token); num_headers = 1; free(neg_token); gss_release_buffer(&min_stat, &output_token); } if (input_token.length) free(input_token.value); } else done = 1; } else done = 1; if (print_body || verbose_flag) printf("%.*s\n", (int)req.body_size, (char *)req.body); http_req_free(&req); } while (!done); if (gssapi_done == 0) errx(1, "gssapi not done but http dance done"); krb5_storage_free(sp); close(s); return 0; }
static int gssapi_init(struct ph1handle *iph1) { struct gssapi_ph1_state *gps; gss_buffer_desc id_token, cred_token; gss_buffer_t cred = &cred_token; gss_name_t princ, canon_princ; OM_uint32 maj_stat, min_stat; gps = racoon_calloc(1, sizeof (struct gssapi_ph1_state)); if (gps == NULL) { plog(LLV_ERROR, LOCATION, NULL, "racoon_calloc failed\n"); return -1; } gps->gss_context = GSS_C_NO_CONTEXT; gps->gss_cred = GSS_C_NO_CREDENTIAL; gssapi_set_state(iph1, gps); if (iph1->rmconf->proposal->gssid != NULL) { id_token.length = iph1->rmconf->proposal->gssid->l; id_token.value = iph1->rmconf->proposal->gssid->v; maj_stat = gss_import_name(&min_stat, &id_token, GSS_C_NO_OID, &princ); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "import name\n"); gssapi_free_state(iph1); return -1; } } else gssapi_get_default_name(iph1, 0, &princ); maj_stat = gss_canonicalize_name(&min_stat, princ, GSS_C_NO_OID, &canon_princ); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "canonicalize name\n"); maj_stat = gss_release_name(&min_stat, &princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release princ\n"); gssapi_free_state(iph1); return -1; } maj_stat = gss_release_name(&min_stat, &princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release princ\n"); maj_stat = gss_export_name(&min_stat, canon_princ, cred); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "export name\n"); maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); gssapi_free_state(iph1); return -1; } #if 0 /* * XXXJRT Did this debug message ever work? This is a GSS name * blob at this point. */ plog(LLV_DEBUG, LOCATION, NULL, "will try to acquire '%.*s' creds\n", cred->length, cred->value); #endif maj_stat = gss_release_buffer(&min_stat, cred); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release cred buffer\n"); maj_stat = gss_acquire_cred(&min_stat, canon_princ, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_BOTH, &gps->gss_cred, NULL, NULL); if (GSS_ERROR(maj_stat)) { gssapi_error(min_stat, LOCATION, "acquire cred\n"); maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); gssapi_free_state(iph1); return -1; } maj_stat = gss_release_name(&min_stat, &canon_princ); if (GSS_ERROR(maj_stat)) gssapi_error(min_stat, LOCATION, "release canon_princ\n"); return 0; }
/* * Negotiate a krb5 gss context from the server end. */ static int gss_server( struct tcp_conn *rc) { OM_uint32 maj_stat, min_stat, ret_flags; gss_buffer_desc send_tok, recv_tok, AA; gss_OID doid; gss_name_t gss_name; gss_cred_id_t gss_creds; char *p, *realm, *msg; int rval = -1; int rvalue; char errbuf[256]; char *errmsg = NULL; auth_debug(1, "gss_server\n"); assert(rc != NULL); /* * We need to be root while in gss_acquire_cred() to read the host key * out of the default keytab. We also need to be root in * gss_accept_context() thanks to the replay cache code. */ if (!set_root_privs(0)) { g_snprintf(errbuf, SIZEOF(errbuf), _("can't take root privileges to read krb5 host key: %s"), strerror(errno)); goto out; } rc->gss_context = GSS_C_NO_CONTEXT; send_tok.value = vstralloc("host/", myhostname, NULL); send_tok.length = strlen(send_tok.value) + 1; for (p = send_tok.value; *p != '\0'; p++) { if (isupper((int)*p)) *p = tolower(*p); } maj_stat = gss_import_name(&min_stat, &send_tok, GSS_C_NULL_OID, &gss_name); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { set_root_privs(0); g_snprintf(errbuf, SIZEOF(errbuf), _("can't import name %s: %s"), (char *)send_tok.value, gss_error(maj_stat, min_stat)); amfree(send_tok.value); goto out; } amfree(send_tok.value); maj_stat = gss_display_name(&min_stat, gss_name, &AA, &doid); dbprintf(_("gss_name %s\n"), (char *)AA.value); maj_stat = gss_acquire_cred(&min_stat, gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &gss_creds, NULL, NULL); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { g_snprintf(errbuf, SIZEOF(errbuf), _("can't acquire creds for host key host/%s: %s"), myhostname, gss_error(maj_stat, min_stat)); gss_release_name(&min_stat, &gss_name); set_root_privs(0); goto out; } gss_release_name(&min_stat, &gss_name); for (recv_tok.length = 0;;) { recv_tok.value = NULL; rvalue = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, /* (void *) is to avoid type-punning warning */ (char **)(void *)&recv_tok.value, (ssize_t *)&recv_tok.length, 60); if (rvalue <= 0) { if (rvalue < 0) { g_snprintf(errbuf, SIZEOF(errbuf), _("recv error in gss loop: %s"), rc->errmsg); amfree(rc->errmsg); } else g_snprintf(errbuf, SIZEOF(errbuf), _("EOF in gss loop")); goto out; } maj_stat = gss_accept_sec_context(&min_stat, &rc->gss_context, gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gss_name, &doid, &send_tok, &ret_flags, NULL, NULL); if (maj_stat != (OM_uint32)GSS_S_COMPLETE && maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) { g_snprintf(errbuf, SIZEOF(errbuf), _("error accepting context: %s"), gss_error(maj_stat, min_stat)); amfree(recv_tok.value); goto out; } amfree(recv_tok.value); if (send_tok.length != 0 && tcpm_send_token(rc, rc->write, 0, &errmsg, send_tok.value, send_tok.length) < 0) { strncpy(errbuf, rc->errmsg, SIZEOF(errbuf) - 1); errbuf[SIZEOF(errbuf) - 1] = '\0'; amfree(rc->errmsg); gss_release_buffer(&min_stat, &send_tok); goto out; } gss_release_buffer(&min_stat, &send_tok); /* * If we need to get more from the client, then register for * more packets. */ if (maj_stat != (OM_uint32)GSS_S_CONTINUE_NEEDED) break; } maj_stat = gss_display_name(&min_stat, gss_name, &send_tok, &doid); if (maj_stat != (OM_uint32)GSS_S_COMPLETE) { g_snprintf(errbuf, SIZEOF(errbuf), _("can't display gss name: %s"), gss_error(maj_stat, min_stat)); gss_release_name(&min_stat, &gss_name); goto out; } gss_release_name(&min_stat, &gss_name); /* get rid of the realm */ if ((p = strchr(send_tok.value, '@')) == NULL) { g_snprintf(errbuf, SIZEOF(errbuf), _("malformed gss name: %s"), (char *)send_tok.value); amfree(send_tok.value); goto out; } *p = '\0'; realm = ++p; /* * If the principal doesn't match, complain */ if ((msg = krb5_checkuser(rc->hostname, send_tok.value, realm)) != NULL) { g_snprintf(errbuf, SIZEOF(errbuf), _("access not allowed from %s: %s"), (char *)send_tok.value, msg); amfree(send_tok.value); goto out; } amfree(send_tok.value); rval = 0; out: set_root_privs(0); if (rval != 0) { rc->errmsg = stralloc(errbuf); } else { rc->auth = 1; } auth_debug(1, _("gss_server returning %d\n"), rval); return (rval); }
static int tunnel(struct gt_service *svc, int fd, struct sockaddr *cliaddr) { AUTOCLEAN(char *tmbuf, autofreestr) = NULL; AUTOCLEAN(struct addrinfo *addr, autofreeaddrinfo) = NULL; AUTOCLEAN(int sd, autofreesocket) = -1; AUTOCLEAN(int efd, autofreesocket) = -1; AUTOCLEAN(gss_name_t name, autofreegssname) = GSS_C_NO_NAME; AUTOCLEAN(gss_name_t srcname, autofreegssname) = GSS_C_NO_NAME; AUTOCLEAN(gss_cred_id_t cred, autofreegsscred) = GSS_C_NO_CREDENTIAL; AUTOCLEAN(gss_ctx_id_t ctx, autofreegssctx) = GSS_C_NO_CONTEXT; AUTOCLEAN(gss_buffer_desc output, autofreegssbuf) = GSS_C_EMPTY_BUFFER; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc namebuf; OM_uint32 maj, min; OM_uint32 ignore; struct epoll_event events[MAX_EVENTS]; size_t tmlen; int pfd; /* plain text fd */ int cfd; /* cipher text fd */ int ret; /* We allocate a 1 MiB buffer for messages, that's also the maximum msg * size */ tmbuf = malloc(MAX_MSG_SIZE); if (!tmbuf) return ENOMEM; if (svc->exec) { fprintf(stderr, "[%s] EXEC option not supported yet, sorry!\n", svc->name); return ENOTSUP; } ret = string_to_addrinfo(svc->connect, &addr); if (ret) return ret; errno = 0; sd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sd == -1) return errno; ret = connect(sd, addr->ai_addr, addr->ai_addrlen); if (ret != 0) { ret = errno; fprintf(stderr, "[%s] Failed to connect to server '%s': %s\n", svc->name, svc->connect, strerror(ret)); return ret; } if (svc->target_name) { namebuf.length = strlen(svc->target_name); namebuf.value = svc->target_name; maj = gss_import_name(&min, &namebuf, GSS_C_NT_HOSTBASED_SERVICE, &name); if (maj != GSS_S_COMPLETE) { fprintf(stderr, "[%s] Failed to import name: '%s' (%d/%d)\n", svc->name, svc->target_name, (int)maj, (int)min); return EINVAL; } } if (svc->client) { pfd = fd; cfd = sd; do { maj = gss_init_sec_context(&min, cred, &ctx, name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, 0, GSS_C_NO_CHANNEL_BINDINGS, &input, NULL, &output, NULL, NULL); if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EBADE; } if (output.length > MAX_MSG_SIZE) return ENOSPC; if (output.length > 0) { memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); ret = send_msg(cfd, tmbuf, tmlen, true); if (ret) return ret; } if (maj == GSS_S_CONTINUE_NEEDED) { tmlen = MAX_MSG_SIZE; ret = recv_msg(cfd, tmbuf, &tmlen, true); if (ret) return ret; input.value = tmbuf; input.length = tmlen; } } while (maj == GSS_S_CONTINUE_NEEDED); } else { pfd = sd; cfd = fd; if (name != GSS_C_NO_NAME) { maj = gss_acquire_cred(&min, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cred, NULL, NULL); if (maj != GSS_S_COMPLETE) { fprintf(stderr, "[%s] Failed to acquire creds for '%s' (%d/%d)\n", svc->name, svc->target_name?svc->target_name:"", (int)maj, (int)min); return EIO; } } do { tmlen = MAX_MSG_SIZE; ret = recv_msg(cfd, tmbuf, &tmlen, true); if (ret) return ret; input.value = tmbuf; input.length = tmlen; maj = gss_accept_sec_context(&min, &ctx, cred, &input, GSS_C_NO_CHANNEL_BINDINGS, &srcname, NULL, &output, NULL, NULL, NULL); if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EBADE; } if (output.length > MAX_MSG_SIZE) return ENOSPC; if (output.length > 0) { memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); ret = send_msg(cfd, tmbuf, tmlen, true); if (ret) return ret; } } while (maj == GSS_S_CONTINUE_NEEDED); } /* negotiation completed, now handle traffic */ ret = init_epoll(cfd, pfd, &efd); if (ret) return ret; while (efd != -1) { struct epoll_event *ev; int n; n = epoll_wait(efd, events, MAX_EVENTS, -1); if (n == -1) { ret = errno; if (ret == EINTR) continue; return ret; } for (int i = 0; i < n; i++) { ev = &events[i]; if (ev->events & (EPOLLERR|EPOLLHUP)) { /* one of the peers gave up */ return ENOLINK; } /* RECEIVE */ tmlen = MAX_MSG_SIZE; ret = recv_msg(ev->data.fd, tmbuf, &tmlen, (ev->data.fd == cfd)); if (ret) return ret; if (ev->data.fd == cfd) { /* sender encrypts */ input.value = tmbuf; input.length = tmlen; maj = gss_unwrap(&min, ctx, &input, &output, NULL, NULL); if (maj != GSS_S_COMPLETE) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EIO; } if (output.length > MAX_MSG_SIZE) return ENOSPC; memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); } /* RESEND */ if (ev->data.fd == pfd) { /* receiver encrypts */ input.value = tmbuf; input.length = tmlen; maj = gss_wrap(&min, ctx, 1, 0, &input, NULL, &output); if (maj != GSS_S_COMPLETE) { gt_gss_error(svc->name, GSS_C_NO_OID, maj, min); return EIO; } if (output.length > MAX_MSG_SIZE) return ENOSPC; memcpy(tmbuf, output.value, output.length); tmlen = output.length; (void)gss_release_buffer(&ignore, &output); } /* send to the other fd, add header only if we encrypted */ ret = send_msg((ev->data.fd == pfd)?cfd:pfd, tmbuf, tmlen, (ev->data.fd == pfd)); if (ret) return ret; } } return 0; }
int main() { OM_uint32 init_maj_stat; OM_uint32 accept_maj_stat; OM_uint32 maj_stat; OM_uint32 min_stat; OM_uint32 ret_flags; OM_uint32 req_flags = 0; OM_uint32 time_rec; gss_buffer_desc send_tok; gss_buffer_desc recv_tok; gss_buffer_desc * token_ptr; gss_OID mech_type; gss_name_t target_name; gss_ctx_id_t init_context; gss_ctx_id_t accept_context; gss_ctx_id_t del_init_context; gss_ctx_id_t del_accept_context; gss_cred_id_t delegated_cred; gss_cred_id_t imported_cred; gss_cred_id_t cred_handle; char * error_str; globus_result_t result; globus_gsi_cert_utils_cert_type_t cert_type; int rc = EXIT_SUCCESS; printf("1..1\n"); /* Activate Modules */ globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE); /* Initialize variables */ token_ptr = GSS_C_NO_BUFFER; init_context = GSS_C_NO_CONTEXT; accept_context = GSS_C_NO_CONTEXT; del_init_context = GSS_C_NO_CONTEXT; del_accept_context = GSS_C_NO_CONTEXT; delegated_cred = GSS_C_NO_CREDENTIAL; accept_maj_stat = GSS_S_CONTINUE_NEEDED; ret_flags = 0; req_flags |= GSS_C_GLOBUS_LIMITED_DELEG_PROXY_FLAG; /* acquire the credential */ maj_stat = gss_acquire_cred(&min_stat, NULL, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_BOTH, &cred_handle, NULL, NULL); if(maj_stat != GSS_S_COMPLETE) { globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } /* get the subject name */ maj_stat = gss_inquire_cred(&min_stat, cred_handle, &target_name, NULL, NULL, NULL); if(maj_stat != GSS_S_COMPLETE) { globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } /* set up the first security context */ init_maj_stat = gss_init_sec_context(&min_stat, cred_handle, &init_context, target_name, GSS_C_NULL_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, token_ptr, NULL, &send_tok, NULL, NULL); if(init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } while(1) { accept_maj_stat=gss_accept_sec_context(&min_stat, &accept_context, GSS_C_NO_CREDENTIAL, &send_tok, GSS_C_NO_CHANNEL_BINDINGS, NULL, &mech_type, &recv_tok, &ret_flags, /* ignore time_rec */ NULL, NULL); if(accept_maj_stat != GSS_S_COMPLETE && accept_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } else if(accept_maj_stat == GSS_S_COMPLETE) { break; } init_maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &init_context, target_name, GSS_C_NULL_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, &recv_tok, NULL, &send_tok, NULL, NULL); if(init_maj_stat != GSS_S_COMPLETE && init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } } printf("# %s:%d: Successfully established initial security context\n", __FILE__, __LINE__); /* delegate our credential over the initial security context and * insert a restriction extension into the delegated credential. * This is a post GT 2.0 feature. */ init_maj_stat = gss_init_delegation(&min_stat, init_context, cred_handle, GSS_C_NO_OID, GSS_C_NO_OID_SET, GSS_C_NO_BUFFER_SET, token_ptr, req_flags, 0, &send_tok); if(init_maj_stat != GSS_S_COMPLETE && init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } while(1) { accept_maj_stat=gss_accept_delegation(&min_stat, accept_context, GSS_C_NO_OID_SET, GSS_C_NO_BUFFER_SET, &send_tok, req_flags, 0, &time_rec, &delegated_cred, &mech_type, &recv_tok); if(accept_maj_stat != GSS_S_COMPLETE && accept_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } else if(accept_maj_stat == GSS_S_COMPLETE) { break; } init_maj_stat = gss_init_delegation(&min_stat, init_context, cred_handle, GSS_C_NO_OID, GSS_C_NO_OID_SET, GSS_C_NO_BUFFER_SET, &recv_tok, req_flags, 0, &send_tok); if(init_maj_stat != GSS_S_COMPLETE && init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } } printf("# %s:%d: Successfully delegated credential\n", __FILE__, __LINE__); /* export and import the delegated credential */ /* this can be done both to a buffer and to a file */ /* New in GT 2.0 */ maj_stat = gss_export_cred(&min_stat, delegated_cred, GSS_C_NO_OID, 0, &send_tok); if(maj_stat != GSS_S_COMPLETE) { globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } maj_stat = gss_import_cred(&min_stat, &imported_cred, GSS_C_NO_OID, 0, &send_tok, 0, &time_rec); if(maj_stat != GSS_S_COMPLETE) { globus_gsi_gssapi_test_print_error(stderr, maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } printf("# %s:%d: Successfully exported/imported the delegated credential\n", __FILE__, __LINE__); /* set up another security context using the delegated credential */ init_maj_stat = gss_init_sec_context(&min_stat, imported_cred, &del_init_context, target_name, GSS_C_NULL_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, token_ptr, NULL, &send_tok, NULL, NULL); if(init_maj_stat != GSS_S_COMPLETE && init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } while(1) { accept_maj_stat=gss_accept_sec_context(&min_stat, &del_accept_context, imported_cred, &send_tok, GSS_C_NO_CHANNEL_BINDINGS, NULL, &mech_type, &recv_tok, &ret_flags, /* ignore time_rec */ NULL, NULL); if(accept_maj_stat != GSS_S_COMPLETE && accept_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, accept_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } else if(accept_maj_stat == GSS_S_COMPLETE) { break; } init_maj_stat = gss_init_sec_context(&min_stat, imported_cred, &del_init_context, target_name, GSS_C_NULL_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS, &recv_tok, NULL, &send_tok, NULL, NULL); if(init_maj_stat != GSS_S_COMPLETE && init_maj_stat != GSS_S_CONTINUE_NEEDED) { globus_gsi_gssapi_test_print_error(stderr, init_maj_stat, min_stat); rc = EXIT_FAILURE; goto fail; } } /* got sec context based on delegated cred now */ printf("# %s:%d: Successfully established security context with delegated credential\n", __FILE__, __LINE__); /* Verify that the delegated credential is a limited proxy */ result = globus_gsi_cred_get_cert_type( ((gss_cred_id_desc *)imported_cred)->cred_handle, &cert_type); if(result != GLOBUS_SUCCESS) { char * error_str; globus_object_t * error_obj; error_obj = globus_error_get(result); error_str = globus_error_print_chain(error_obj); fprintf(stderr, "%s", error_str); globus_libc_free(error_str); globus_object_free(error_obj); rc = EXIT_FAILURE; goto fail; } if (! GLOBUS_GSI_CERT_UTILS_IS_LIMITED_PROXY(cert_type)) { fprintf(stderr, "Invalid certificate type. Expected a limited proxy, got %d\n", (int) cert_type); rc = EXIT_FAILURE; goto fail; } fail: printf("%s gssapi_limited_delegation_test\n", (rc==EXIT_SUCCESS) ? "ok" : "not ok"); globus_module_deactivate_all(); exit(rc); }
/* Acquire GSSAPI credentials and set up RPC auth flavor. */ static kadm5_ret_t setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, krb5_principal client, krb5_principal server) { OM_uint32 gssstat, minor_stat; gss_buffer_desc buf; gss_name_t gss_client; gss_name_t gss_target; gss_cred_id_t gss_client_creds; const char *c_ccname_orig; char *ccname_orig; gss_client_creds = GSS_C_NO_CREDENTIAL; ccname_orig = NULL; gss_client = gss_target = GSS_C_NO_NAME; /* Temporarily use the kadm5 cache. */ gssstat = gss_krb5_ccache_name(&minor_stat, handle->cache_name, &c_ccname_orig); if (gssstat != GSS_S_COMPLETE) goto error; if (c_ccname_orig) ccname_orig = strdup(c_ccname_orig); else ccname_orig = 0; buf.value = &server; buf.length = sizeof(server); gssstat = gss_import_name(&minor_stat, &buf, (gss_OID)gss_nt_krb5_principal, &gss_target); if (gssstat != GSS_S_COMPLETE) goto error; if (client != NULL) { buf.value = &client; buf.length = sizeof(client); gssstat = gss_import_name(&minor_stat, &buf, (gss_OID)gss_nt_krb5_principal, &gss_client); } else gss_client = GSS_C_NO_NAME; if (gssstat != GSS_S_COMPLETE) goto error; gssstat = gss_acquire_cred(&minor_stat, gss_client, 0, GSS_C_NULL_OID_SET, GSS_C_INITIATE, &gss_client_creds, NULL, NULL); if (gssstat != GSS_S_COMPLETE) { #if 0 /* for debugging only */ { OM_uint32 maj_status, min_status, message_context = 0; gss_buffer_desc status_string; do { maj_status = gss_display_status(&min_status, gssstat, GSS_C_GSS_CODE, GSS_C_NO_OID, &message_context, &status_string); if (maj_status == GSS_S_COMPLETE) { fprintf(stderr, "MAJ: %.*s\n", (int) status_string.length, (char *)status_string.value); gss_release_buffer(&min_status, &status_string); } else { fprintf(stderr, "MAJ? gss_display_status returns 0x%lx?!\n", (unsigned long) maj_status); message_context = 0; } } while (message_context != 0); do { maj_status = gss_display_status(&min_status, minor_stat, GSS_C_MECH_CODE, GSS_C_NO_OID, &message_context, &status_string); if (maj_status == GSS_S_COMPLETE) { fprintf(stderr, "MIN: %.*s\n", (int) status_string.length, (char *)status_string.value); gss_release_buffer(&min_status, &status_string); } else { fprintf(stderr, "MIN? gss_display_status returns 0x%lx?!\n", (unsigned long) maj_status); message_context = 0; } } while (message_context != 0); } #endif goto error; } /* * Do actual creation of RPC auth handle. Implements auth flavor * fallback. */ rpc_auth(handle, params_in, gss_client_creds, gss_target); error: if (gss_client_creds != GSS_C_NO_CREDENTIAL) (void) gss_release_cred(&minor_stat, &gss_client_creds); if (gss_client) gss_release_name(&minor_stat, &gss_client); if (gss_target) gss_release_name(&minor_stat, &gss_target); /* Revert to prior gss_krb5 ccache. */ if (ccname_orig) { gssstat = gss_krb5_ccache_name(&minor_stat, ccname_orig, NULL); if (gssstat) { return KADM5_GSS_ERROR; } free(ccname_orig); } else { gssstat = gss_krb5_ccache_name(&minor_stat, NULL, NULL); if (gssstat) { return KADM5_GSS_ERROR; } } if (handle->clnt->cl_auth == NULL) { return KADM5_GSS_ERROR; } return 0; }