static krb5_error_code mspac_get_attribute_types(krb5_context kcontext, krb5_authdata_context context, void *plugin_context, void *request_context, krb5_data **out_attrs) { struct mspac_context *pacctx = (struct mspac_context *)request_context; unsigned int i, j; krb5_data *attrs; krb5_error_code code; if (pacctx->pac == NULL) return ENOENT; attrs = calloc(1 + pacctx->pac->pac->cBuffers + 1, sizeof(krb5_data)); if (attrs == NULL) return ENOMEM; j = 0; /* The entire PAC */ code = krb5int_copy_data_contents(kcontext, &mspac_attribute_types[0].attribute, &attrs[j++]); if (code != 0) { free(attrs); return code; } /* PAC buffers */ for (i = 0; i < pacctx->pac->pac->cBuffers; i++) { krb5_data attr; code = mspac_type2attr(pacctx->pac->pac->Buffers[i].ulType, &attr); if (code == 0) { code = krb5int_copy_data_contents(kcontext, &attr, &attrs[j++]); if (code != 0) { krb5int_free_data_list(kcontext, attrs); return code; } } else { int length; length = asprintf(&attrs[j].data, "urn:mspac:%d", pacctx->pac->pac->Buffers[i].ulType); if (length < 0) { krb5int_free_data_list(kcontext, attrs); return ENOMEM; } attrs[j++].length = length; } } attrs[j].data = NULL; attrs[j].length = 0; *out_attrs = attrs; return 0; }
OM_uint32 KRB5_CALLCONV krb5_gss_inquire_name(OM_uint32 *minor_status, gss_name_t name, int *name_is_MN, gss_OID *MN_mech, gss_buffer_set_t *attrs) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; krb5_data *kattrs = NULL; if (minor_status != NULL) *minor_status = 0; if (attrs != NULL) *attrs = GSS_C_NO_BUFFER_SET; code = krb5_gss_init_context(&context); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } kname = (krb5_gss_name_t)name; code = k5_mutex_lock(&kname->lock); if (code != 0) { *minor_status = code; return GSS_S_FAILURE; } if (kname->ad_context == NULL) { code = krb5_authdata_context_init(context, &kname->ad_context); if (code != 0) goto cleanup; } code = krb5_authdata_get_attribute_types(context, kname->ad_context, &kattrs); if (code != 0) goto cleanup; code = data_list_to_buffer_set(context, kattrs, attrs); kattrs = NULL; if (code != 0) goto cleanup; cleanup: k5_mutex_unlock(&kname->lock); krb5int_free_data_list(context, kattrs); krb5_free_context(context); return kg_map_name_error(minor_status, code); }
void KRB5_CALLCONV krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx) { if (ctx == NULL) return; krb5_free_creds(context, ctx->in_creds); krb5_cc_close(context, ctx->ccache); krb5_free_principal(context, ctx->req_server); krb5_free_authdata(context, ctx->authdata); krb5_free_creds(context, ctx->cur_tgt); krb5int_free_data_list(context, ctx->realms_seen); krb5_free_principal(context, ctx->tgt_princ); krb5_free_keyblock(context, ctx->subkey); krb5_free_data_contents(context, &ctx->previous_request); krb5int_free_data_list(context, ctx->realm_path); krb5_free_creds(context, ctx->reply_creds); free(ctx); }
krb5_error_code KRB5_CALLCONV krb5_authdata_get_attribute_types(krb5_context kcontext, krb5_authdata_context context, krb5_data **out_attrs) { int i; krb5_error_code code = 0; krb5_data *attrs = NULL; unsigned int attrs_len = 0; for (i = 0; i < context->n_modules; i++) { struct _krb5_authdata_context_module *module = &context->modules[i]; krb5_data *attrs2 = NULL; if (module->ftable->get_attribute_types == NULL) continue; if ((*module->ftable->get_attribute_types)(kcontext, context, module->plugin_context, *(module->request_context_pp), &attrs2)) continue; code = k5_merge_data_list(&attrs, attrs2, &attrs_len); if (code != 0) { krb5int_free_data_list(kcontext, attrs2); break; } if (attrs2 != NULL) free(attrs2); } if (code != 0) { krb5int_free_data_list(kcontext, attrs); attrs = NULL; } *out_attrs = attrs; return code; }
/* Owns data on success */ static krb5_error_code data_list_to_buffer_set(krb5_context context, krb5_data *data, gss_buffer_set_t *buffer_set) { gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; OM_uint32 minor_status; int i; krb5_error_code code = 0; if (data == NULL) goto cleanup; if (buffer_set == NULL) goto cleanup; if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status, &set))) { assert(minor_status != 0); code = minor_status; goto cleanup; } for (i = 0; data[i].data != NULL; i++) ; set->count = i; set->elements = gssalloc_calloc(i, sizeof(gss_buffer_desc)); if (set->elements == NULL) { gss_release_buffer_set(&minor_status, &set); code = ENOMEM; goto cleanup; } /* * Copy last element first so data remains properly * NULL-terminated in case of allocation failure * in data_to_gss() on windows. */ for (i = set->count-1; i >= 0; i--) { if (data_to_gss(&data[i], &set->elements[i])) { gss_release_buffer_set(&minor_status, &set); code = ENOMEM; goto cleanup; } } cleanup: krb5int_free_data_list(context, data); if (buffer_set != NULL) *buffer_set = set; return code; }
/* * Begin the referrals request loop. Expects ctx->cur_tgt to be a TGT for * ctx->realm->server. */ static krb5_error_code begin_referrals(krb5_context context, krb5_tkt_creds_context ctx) { ctx->state = STATE_REFERRALS; ctx->referral_count = 1; /* Empty out the realms-seen list for loop checking. */ krb5int_free_data_list(context, ctx->realms_seen); ctx->realms_seen = NULL; /* Generate the first referral request. */ return make_request_for_service(context, ctx, TRUE); }
/* Initialize the realm path fields for getting a TGT for * ctx->server->realm. */ static krb5_error_code init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) { krb5_error_code code; krb5_principal *tgt_princ_list = NULL; krb5_data *realm_path; size_t nrealms, i; /* Construct a list of TGT principals from client to server. We will throw * this away after grabbing the remote realms from each principal. */ code = krb5_walk_realm_tree(context, &ctx->client->realm, &ctx->server->realm, &tgt_princ_list, KRB5_REALM_BRANCH_CHAR); if (code != 0) return code; /* Count the number of principals and allocate the realm path. */ for (nrealms = 0; tgt_princ_list[nrealms]; nrealms++); assert(nrealms > 1); realm_path = k5alloc((nrealms + 1) * sizeof(*realm_path), &code); if (realm_path == NULL) goto cleanup; /* Steal the remote realm field from each TGT principal. */ for (i = 0; i < nrealms; i++) { assert(tgt_princ_list[i]->length == 2); realm_path[i] = tgt_princ_list[i]->data[1]; tgt_princ_list[i]->data[1].data = NULL; } realm_path[nrealms] = empty_data(); /* Initialize the realm path fields in ctx. */ krb5int_free_data_list(context, ctx->realm_path); ctx->realm_path = realm_path; ctx->last_realm = realm_path + nrealms - 1; ctx->cur_realm = realm_path; ctx->next_realm = ctx->last_realm; realm_path = NULL; cleanup: krb5_free_realm_tree(context, tgt_princ_list); return 0; }
krb5_error_code k5_client_realm_path(krb5_context context, const krb5_data *client, const krb5_data *server, krb5_data **rpath_out) { krb5_error_code retval; char **capvals; size_t i; krb5_data *rpath = NULL, d; retval = rtree_capath_vals(context, client, server, &capvals); if (retval) return retval; /* Count capaths (if any) and allocate space. Leave room for the client * realm, server realm, and terminator. */ for (i = 0; capvals != NULL && capvals[i] != NULL; i++); rpath = calloc(i + 3, sizeof(*rpath)); if (rpath == NULL) return ENOMEM; /* Populate rpath with the client realm, capaths, and server realm. */ retval = krb5int_copy_data_contents(context, client, &rpath[0]); if (retval) goto cleanup; for (i = 0; capvals != NULL && capvals[i] != NULL; i++) { d = make_data(capvals[i], strcspn(capvals[i], "\t ")); retval = krb5int_copy_data_contents(context, &d, &rpath[i + 1]); if (retval) goto cleanup; } retval = krb5int_copy_data_contents(context, server, &rpath[i + 1]); if (retval) goto cleanup; /* Terminate rpath and return it. */ rpath[i + 2] = empty_data(); *rpath_out = rpath; rpath = NULL; cleanup: krb5int_free_data_list(context, rpath); return retval; }
/* * Begin the process of getting a foreign TGT, either for the explicitly * specified server realm or for the fallback realm. Expects that * ctx->server->realm is the realm of the desired TGT, and that * ctx->getting_tgt_for is the state we should advance to after we have the * desired TGT. */ static krb5_error_code begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) { krb5_error_code code; krb5_creds *cached_tgt; ctx->state = STATE_GET_TGT; /* See if we have a cached TGT for the server realm. */ code = get_cached_tgt(context, ctx, &ctx->server->realm, &cached_tgt); if (code != 0) return code; if (cached_tgt != NULL) { TRACE_TKT_CREDS_CACHED_SERVICE_TGT(context, cached_tgt); krb5_free_creds(context, ctx->cur_tgt); ctx->cur_tgt = cached_tgt; return end_get_tgt(context, ctx); } /* Start with the local tgt. */ krb5_free_creds(context, ctx->cur_tgt); ctx->cur_tgt = NULL; code = get_cached_tgt(context, ctx, &ctx->client->realm, &ctx->cur_tgt); if (code != 0) return code; if (ctx->cur_tgt == NULL) return ctx->cache_code; TRACE_TKT_CREDS_LOCAL_TGT(context, ctx->cur_tgt); /* Initialize the realm path. */ code = init_realm_path(context, ctx); if (code != 0) return code; /* Empty out the realms-seen list for loop checking. */ krb5int_free_data_list(context, ctx->realms_seen); ctx->realms_seen = NULL; /* Generate the first request. */ return get_tgt_request(context, ctx); }
/* Initialize the realm path fields for getting a TGT for * ctx->server->realm. */ static krb5_error_code init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) { krb5_error_code code; krb5_data *realm_path; size_t nrealms; /* Get the client realm path and count its length. */ code = k5_client_realm_path(context, &ctx->client->realm, &ctx->server->realm, &realm_path); if (code != 0) return code; for (nrealms = 0; realm_path[nrealms].data != NULL; nrealms++); assert(nrealms > 1); /* Initialize the realm path fields in ctx. */ krb5int_free_data_list(context, ctx->realm_path); ctx->realm_path = realm_path; ctx->last_realm = realm_path + nrealms - 1; ctx->cur_realm = realm_path; ctx->next_realm = ctx->last_realm; return 0; }