static int get_cred(struct kafs_data *data, const char *name, const char *inst, const char *realm, uid_t uid, struct kafs_token *kt) { krb5_error_code ret; krb5_creds in_creds, *out_creds; struct krb5_kafs_data *d = data->data; int invalid; memset(&in_creds, 0, sizeof(in_creds)); ret = krb5_make_principal(d->context, &in_creds.server, realm, name, inst, NULL); if(ret) return ret; ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client); if(ret){ krb5_free_principal(d->context, in_creds.server); return ret; } in_creds.session.keytype = ETYPE_DES_CBC_CRC; /* check if des is disable, and in that case enable it for afs */ invalid = krb5_enctype_valid(d->context, in_creds.session.keytype); if (invalid) krb5_enctype_enable(d->context, in_creds.session.keytype); ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds); if (ret) { in_creds.session.keytype = ETYPE_DES_CBC_MD5; ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds); } if (invalid) krb5_enctype_disable(d->context, in_creds.session.keytype); krb5_free_principal(d->context, in_creds.server); krb5_free_principal(d->context, in_creds.client); if(ret) return ret; ret = v5_convert(d->context, d->id, out_creds, uid, (inst != NULL && inst[0] != '\0') ? inst : realm, kt); krb5_free_creds(d->context, out_creds); return ret; }
static int get_cred(struct kafs_data *data, const char *name, const char *inst, const char *realm, uid_t uid, struct kafs_token *kt) { krb5_error_code ret; krb5_creds in_creds, *out_creds; struct krb5_kafs_data *d = data->data; memset(&in_creds, 0, sizeof(in_creds)); ret = krb5_make_principal(d->context, &in_creds.server, realm, name, inst, NULL); if(ret) return ret; ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client); if(ret){ krb5_free_principal(d->context, in_creds.server); return ret; } in_creds.session.keytype = ETYPE_DES_CBC_CRC; ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds); krb5_free_principal(d->context, in_creds.server); krb5_free_principal(d->context, in_creds.client); if(ret) return ret; ret = v5_convert(d->context, d->id, out_creds, uid, (inst != NULL && inst[0] != '\0') ? inst : realm, kt); krb5_free_creds(d->context, out_creds); return ret; }
static int kvno5(krb5_context ctx, const char *host, int socktype, krb5_principal princ, krb5_principal sprinc, krb5_ccache ccache) { krb5_error_code kerr = 0; krb5_creds increds; krb5_creds *outcreds = NULL; krb5_ticket *ticket = NULL; VERBOSE(1, (stderr, "initiating kvno5/%s ping to %s\n", socktype == SOCK_DGRAM ? "udp" : "tcp", host)); memset(&increds, 0x0, sizeof(increds)); increds.client = princ; increds.server = sprinc; kerr = krb5_get_credentials(ctx, 0, ccache, &increds, &outcreds); if (kerr) goto bail; kerr = krb5_decode_ticket(&outcreds->ticket, &ticket); if (kerr) goto bail; VERBOSE(2, (stderr, "kvno5 says kvno = %d\n", ticket->enc_part.kvno)); bail: if (kerr) fail_msg("kvno5", socktype, host, error_message(kerr)); if (ticket) krb5_free_ticket(ctx, ticket); if (outcreds) krb5_free_creds(ctx, outcreds); return kerr; }
krb5_error_code KRB5_LIB_FUNCTION krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, char *newpw, krb5_principal targprinc, int *result_code, krb5_data *result_code_string, krb5_data *result_string) { krb5_creds creds, *credsp; krb5_error_code ret; krb5_principal principal = NULL; *result_code = KRB5_KPASSWD_MALFORMED; result_code_string->data = result_string->data = NULL; result_code_string->length = result_string->length = 0; memset(&creds, 0, sizeof(creds)); if (targprinc == NULL) { ret = krb5_cc_get_principal(context, ccache, &principal); if (ret) return ret; } else principal = targprinc; ret = krb5_make_principal(context, &creds.server, krb5_principal_get_realm(context, principal), "kadmin", "changepw", NULL); if (ret) goto out; ret = krb5_cc_get_principal(context, ccache, &creds.client); if (ret) { krb5_free_principal(context, creds.server); goto out; } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); krb5_free_principal(context, creds.server); krb5_free_principal(context, creds.client); if (ret) goto out; ret = krb5_set_password(context, credsp, newpw, principal, result_code, result_code_string, result_string); krb5_free_creds(context, credsp); return ret; out: if (targprinc == NULL) krb5_free_principal(context, principal); return ret; }
static krb5_error_code fast_armor_ap_request(krb5_context context, struct krb5int_fast_request_state *state, krb5_ccache ccache, krb5_principal target_principal) { krb5_error_code retval = 0; krb5_creds creds, *out_creds = NULL; krb5_auth_context authcontext = NULL; krb5_data encoded_authenticator; krb5_fast_armor *armor = NULL; krb5_keyblock *subkey = NULL, *armor_key = NULL; encoded_authenticator.data = NULL; memset(&creds, 0, sizeof(creds)); creds.server = target_principal; retval = krb5_cc_get_principal(context, ccache, &creds.client); if (retval == 0) retval = krb5_get_credentials(context, 0, ccache, &creds, &out_creds); if (retval == 0) { TRACE_FAST_ARMOR_CCACHE_KEY(context, &out_creds->keyblock); retval = krb5_mk_req_extended(context, &authcontext, AP_OPTS_USE_SUBKEY, NULL /*data*/, out_creds, &encoded_authenticator); } if (retval == 0) retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey); if (retval == 0) retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", &out_creds->keyblock, "ticketarmor", &armor_key); if (retval == 0) { TRACE_FAST_ARMOR_KEY(context, armor_key); armor = calloc(1, sizeof(krb5_fast_armor)); if (armor == NULL) retval = ENOMEM; } if (retval == 0) { armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST; armor->armor_value = encoded_authenticator; encoded_authenticator.data = NULL; encoded_authenticator.length = 0; state->armor = armor; armor = NULL; state->armor_key = armor_key; armor_key = NULL; } krb5_free_keyblock(context, armor_key); krb5_free_keyblock(context, subkey); if (out_creds) krb5_free_creds(context, out_creds); /* target_principal is owned by caller. */ creds.server = NULL; krb5_free_cred_contents(context, &creds); if (encoded_authenticator.data) krb5_free_data_contents(context, &encoded_authenticator); krb5_auth_con_free(context, authcontext); return retval; }
static OM_uint32 gsskrb5_get_creds( OM_uint32 * minor_status, krb5_ccache ccache, gsskrb5_ctx ctx, krb5_const_principal target_name, OM_uint32 time_req, OM_uint32 * time_rec, krb5_creds ** cred) { OM_uint32 ret; krb5_error_code kret; krb5_creds this_cred; OM_uint32 lifetime_rec; *cred = NULL; memset(&this_cred, 0, sizeof(this_cred)); this_cred.client = ctx->source; this_cred.server = ctx->target; if (time_req && time_req != GSS_C_INDEFINITE) { krb5_timestamp ts; krb5_timeofday (_gsskrb5_context, &ts); this_cred.times.endtime = ts + time_req; } else { this_cred.times.endtime = 0; } this_cred.session.keytype = KEYTYPE_NULL; kret = krb5_get_credentials(_gsskrb5_context, 0, ccache, &this_cred, cred); if (kret) { _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } ctx->lifetime = (*cred)->times.endtime; ret = _gsskrb5_lifetime_left(minor_status, ctx->lifetime, &lifetime_rec); if (ret) return ret; if (lifetime_rec == 0) { *minor_status = 0; return GSS_S_CONTEXT_EXPIRED; } if (time_rec) *time_rec = lifetime_rec; return GSS_S_COMPLETE; }
/* * Determine the starting IAKERB state for a context. If we already * have a ticket, we may not need to do IAKERB at all. */ static krb5_error_code iakerb_get_initial_state(iakerb_ctx_id_t ctx, krb5_gss_cred_id_t cred, krb5_gss_name_t target, OM_uint32 time_req, enum iakerb_state *state) { krb5_creds in_creds, *out_creds = NULL; krb5_error_code code; memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = cred->name->princ; in_creds.server = target->princ; if (cred->name->ad_context != NULL) { code = krb5_authdata_export_authdata(ctx->k5c, cred->name->ad_context, AD_USAGE_TGS_REQ, &in_creds.authdata); if (code != 0) goto cleanup; } if (time_req != 0 && time_req != GSS_C_INDEFINITE) { krb5_timestamp now; code = krb5_timeofday(ctx->k5c, &now); if (code != 0) goto cleanup; in_creds.times.endtime = now + time_req; } /* Make an AS request if we have no creds or it's time to refresh them. */ if (cred->expire == 0 || kg_cred_time_to_refresh(ctx->k5c, cred)) { *state = IAKERB_AS_REQ; code = 0; goto cleanup; } code = krb5_get_credentials(ctx->k5c, KRB5_GC_CACHED, cred->ccache, &in_creds, &out_creds); if (code == KRB5_CC_NOTFOUND || code == KRB5_CC_NOT_KTYPE) { *state = cred->have_tgt ? IAKERB_TGS_REQ : IAKERB_AS_REQ; code = 0; } else if (code == 0) { *state = IAKERB_AP_REQ; krb5_free_creds(ctx->k5c, out_creds); } cleanup: krb5_free_authdata(ctx->k5c, in_creds.authdata); return code; }
/* * Obtain renewed credentials for the given service using the existing * credentials in the provided ticket cache. */ krb5_error_code krb5_get_renewed_creds(krb5_context ctx, krb5_creds *creds, krb5_const_principal client, krb5_ccache ccache, const char *in_tkt_service) { krb5_kdc_flags flags; krb5_creds in, *old = NULL, *out = NULL; krb5_error_code code; flags.i = 0; flags.b.renewable = 1; flags.b.renew = 1; memset(&in, 0, sizeof(in)); code = krb5_copy_principal(ctx, client, &in.client); if (code != 0) goto done; if (in_tkt_service == NULL) { const char *realm; realm = krb5_principal_get_realm(ctx, client); if (realm == NULL) { code = KRB5_CONFIG_NODEFREALM; goto done; } code = krb5_build_principal(ctx, &in.server, strlen(realm), realm, "krbtgt", realm, (const char *) NULL); if (code != 0) goto done; } else { code = krb5_parse_name(ctx, in_tkt_service, &in.server); if (code != 0) goto done; } code = krb5_get_credentials(ctx, 0, ccache, &in, &old); if (code != 0) goto done; flags.b.forwardable = old->flags.b.forwardable; flags.b.proxiable = old->flags.b.proxiable; code = krb5_get_kdc_cred(ctx, ccache, flags, NULL, NULL, old, &out); if (code != 0) goto done; #ifdef HAVE_KRB5_COPY_CREDS_CONTENTS code = krb5_copy_creds_contents(ctx, out, creds); krb5_free_creds(ctx, out); #else /* No good alternative -- hope this works. */ *creds = *out; free(out); #endif done: krb5_free_cred_contents(ctx, &in); if (old != NULL) krb5_free_creds(ctx, old); return code; }
int kssl_tgt_is_available(KSSL_CTX *kssl_ctx) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; krb5_context krb5context = NULL; krb5_ccache krb5ccdef = NULL; krb5_creds krb5creds, *krb5credsp = NULL; int rc = 0; memset((char *)&krb5creds, 0, sizeof(krb5creds)); if (!kssl_ctx) return (0); if (!kssl_ctx->service_host) return (0); if ((krb5rc = krb5_init_context(&krb5context)) != 0) goto err; if ((krb5rc = krb5_sname_to_principal( krb5context, kssl_ctx->service_host, (kssl_ctx->service_name) ? kssl_ctx->service_name : KRB5SVC, KRB5_NT_SRV_HST, &krb5creds.server)) != 0) goto err; if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) goto err; if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, &krb5creds.client)) != 0) goto err; if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, &krb5creds, &krb5credsp)) != 0) goto err; rc = 1; err: #ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx); #endif /* KSSL_DEBUG */ if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); if (krb5context) krb5_free_context(krb5context); return (rc); }
static int get_v5cred(krb5_context context, char *name, char *inst, char *realm, CREDENTIALS *c, krb5_creds **creds) { krb5_creds increds; krb5_error_code r; static krb5_principal client_principal = 0; if (client_principal) { krb5_free_principal(context, client_principal); client_principal = 0; } memset(&increds, 0, sizeof(increds)); if ((r = krb5_build_principal(context, &increds.server, (int)strlen(realm), realm, name, (inst && strlen(inst)) ? inst : 0, 0))) { return((int)r); } if (!_krb425_ccache) { if ((r = krb5_cc_default(context, &_krb425_ccache))) return ((int)r); } if (!client_principal) { if ((r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal))) { krb5_cc_close(context, _krb425_ccache); return ((int)r); } } increds.client = client_principal; increds.times.endtime = 0; /* Ask for DES since that is what V4 understands */ if (c != NULL) increds.session.keytype = ENCTYPE_DES_CBC_CRC; r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds); if (r) { return((int)r); } #ifdef HAVE_KRB4 /* This requires krb524d to be running with the KDC */ if (c != NULL) r = krb5_524_convert_creds(context, *creds, c); #endif return((int)r); }
Krb5Credentials Krb5CCache::getCredentials( const krb5_creds& in_creds, krb5_flags options) { krb5_creds* out_creds; krb5_context ctx = context_.get(); // The krb5 impl doesn't modify in_creds. krb5_error_code code = krb5_get_credentials( ctx, options, ccache_, const_cast<krb5_creds*>(&in_creds), &out_creds); raiseIf(ctx, code, "get credentials"); SCOPE_EXIT { krb5_free_creds(ctx, out_creds); }; return Krb5Credentials(std::move(*out_creds)); }
int ZGetCredsRealm(krb5_creds **creds_out, char *realm) { krb5_creds creds_in; krb5_creds creds_tmp; krb5_ccache ccache; /* XXX make this a global or static?*/ int result; result = krb5_cc_default(Z_krb5_ctx, &ccache); if (result) return result; memset((char *)&creds_in, 0, sizeof(creds_in)); result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, strlen(realm), realm, SERVER_SERVICE, SERVER_INSTANCE, NULL); if (result) { krb5_cc_close(Z_krb5_ctx, ccache); return result; } result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); if (!result) { result = krb5_cc_retrieve_cred(Z_krb5_ctx, ccache, #ifdef KRB5_TC_SUPPORTED_KTYPES KRB5_TC_SUPPORTED_KTYPES, /* MIT */ #else 0, /* Heimdal or other Space KRB5 */ #endif &creds_in, &creds_tmp); if (!result) { *creds_out = malloc(sizeof(creds_tmp)); if (*creds_out == NULL) result = errno; else memcpy(*creds_out, &creds_tmp, sizeof(creds_tmp)); } } if (result == KRB5_CC_NOTFOUND || result == KRB5_CC_END) result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out); krb5_cc_close(Z_krb5_ctx, ccache); krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */ return result; }
krb5_error_code KRB5_LIB_FUNCTION krb5_mk_req_exact(krb5_context context, krb5_auth_context *auth_context, const krb5_flags ap_req_options, const krb5_principal server, krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf) { krb5_error_code ret; krb5_creds this_cred, *cred; memset(&this_cred, 0, sizeof(this_cred)); ret = krb5_cc_get_principal(context, ccache, &this_cred.client); if(ret) return ret; ret = krb5_copy_principal (context, server, &this_cred.server); if (ret) { krb5_free_cred_contents (context, &this_cred); return ret; } this_cred.times.endtime = 0; if (auth_context && *auth_context && (*auth_context)->keytype) this_cred.session.keytype = (*auth_context)->keytype; ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); krb5_free_cred_contents(context, &this_cred); if (ret) return ret; ret = krb5_mk_req_extended (context, auth_context, ap_req_options, in_data, cred, outbuf); krb5_free_creds(context, cred); return ret; }
static time_t ticket_lifetime(krb5_context context, krb5_ccache cache, krb5_principal client, const char *server, time_t *renew) { krb5_creds in_cred, *cred; krb5_error_code ret; time_t timeout; time_t curtime; memset(&in_cred, 0, sizeof(in_cred)); ret = krb5_cc_get_principal(context, cache, &in_cred.client); if (ret) { krb5_warn(context, ret, "krb5_cc_get_principal"); return 0; } ret = get_server(context, in_cred.client, server, &in_cred.server); if (ret) { krb5_free_principal(context, in_cred.client); krb5_warn(context, ret, "get_server"); return 0; } ret = krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in_cred, &cred); krb5_free_principal(context, in_cred.client); krb5_free_principal(context, in_cred.server); if (ret) { krb5_warn(context, ret, "krb5_get_credentials"); return 0; } curtime = time(NULL); timeout = cred->times.endtime - curtime; if (timeout < 0) timeout = 0; if (renew) { *renew = cred->times.renew_till - curtime; if (*renew < 0) *renew = 0; } krb5_free_creds(context, cred); return timeout; }
static krb5_error_code do_524init(krb5_context context, krb5_ccache ccache, krb5_creds *creds, const char *server) { krb5_error_code ret; struct credentials c; krb5_creds in_creds, *real_creds; if(creds != NULL) real_creds = creds; else { krb5_principal client; krb5_cc_get_principal(context, ccache, &client); memset(&in_creds, 0, sizeof(in_creds)); ret = get_server(context, client, server, &in_creds.server); if(ret) { krb5_free_principal(context, client); return ret; } in_creds.client = client; ret = krb5_get_credentials(context, 0, ccache, &in_creds, &real_creds); krb5_free_principal(context, client); krb5_free_principal(context, in_creds.server); if(ret) return ret; } ret = krb524_convert_creds_kdc_ccache(context, ccache, real_creds, &c); if(ret) krb5_warn(context, ret, "converting creds"); else { krb5_error_code tret = _krb5_krb_tf_setup(context, &c, NULL, 0); if(tret) krb5_warn(context, tret, "saving v4 creds"); } if(creds == NULL) krb5_free_creds(context, real_creds); memset(&c, 0, sizeof(c)); return ret; }
static krb5_error_code get_kadm_ticket(krb5_context context, krb5_ccache id, krb5_principal client, const char *server_name) { krb5_error_code ret; krb5_creds in, *out; memset(&in, 0, sizeof(in)); in.client = client; ret = krb5_parse_name(context, server_name, &in.server); if(ret) return ret; ret = krb5_get_credentials(context, 0, id, &in, &out); if(ret == 0) krb5_free_creds(context, out); krb5_free_principal(context, in.server); return ret; }
int main( int argc, char **argv) { krb5_context context; krb5_ccache ccache = NULL; krb5_creds creds, *out_creds = NULL; krb5_error_code retval = 0; test(krb5_init_context(&context)); memset(&creds, 0, sizeof(creds)); creds.authdata = array; test(krb5_cc_default(context, &ccache)); test(krb5_cc_get_principal(context, ccache, &creds.client)); test(krb5_parse_name(context, argv[1], &creds.server)); test(krb5_get_credentials(context, 0, ccache, &creds, &out_creds)); test(krb5_cc_destroy(context, ccache)); test(krb5_cc_default(context, &ccache)); test(krb5_cc_initialize(context, ccache, out_creds->client)); test(krb5_cc_store_cred(context, ccache, out_creds)); test(krb5_cc_close(context,ccache)); return 0; }
krb5_error_code KRB5_CALLCONV krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, char *newpw, krb5_principal change_password_for, int *result_code, krb5_data *result_code_string, krb5_data *result_string ) { krb5_creds creds; krb5_creds *credsp; krb5_error_code code; /* ** get the proper creds for use with krb5_set_password - */ memset (&creds, 0, sizeof(creds)); /* ** first get the principal for the password service - */ code = krb5_cc_get_principal (context, ccache, &creds.client); if (!code) { code = krb5_build_principal(context, &creds.server, change_password_for->realm.length, change_password_for->realm.data, "kadmin", "changepw", NULL); if (!code) { code = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (!code) { code = krb5_set_password(context, credsp, newpw, change_password_for, result_code, result_code_string, result_string); krb5_free_creds(context, credsp); } } krb5_free_cred_contents(context, &creds); } return code; }
krb5_error_code KRB5_CALLCONV krb5_mk_req(krb5_context context, krb5_auth_context *auth_context, krb5_flags ap_req_options, char *service, char *hostname, krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf) { krb5_error_code retval; krb5_principal server; krb5_creds * credsp; krb5_creds creds; retval = krb5_sname_to_principal(context, hostname, service, KRB5_NT_SRV_HST, &server); if (retval) return retval; /* obtain ticket & session key */ memset((char *)&creds, 0, sizeof(creds)); if ((retval = krb5_copy_principal(context, server, &creds.server))) goto cleanup_princ; if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)) != 0) goto cleanup_creds; if ((retval = krb5_get_credentials(context, 0, ccache, &creds, &credsp)) != 0) goto cleanup_creds; retval = krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, credsp, outbuf); krb5_free_creds(context, credsp); cleanup_creds: krb5_free_cred_contents(context, &creds); cleanup_princ: krb5_free_principal(context, server); return retval; }
static krb5_error_code get_credv5(krb5_context context, char *user, char *name, char *inst, char *realm, krb5_creds **creds) { krb5_creds increds; krb5_error_code r; static krb5_principal client_principal = 0; char *str; memset(&increds, 0, sizeof(increds)); /* instance may be ptr to a null string. Pass null then */ if ((r = krb5_build_principal(context, &increds.server, strlen(realm), realm, name, (inst && strlen(inst)) ? inst : (void *) NULL, (void *) NULL))) { return r; } r = krb5_cc_default(context, &_krb425_ccache); if (r) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: krb5_cc_default returns %d", r); return r; } r = krb5_cc_get_principal(context, _krb425_ccache, &client_principal); if (r) { syslog(LOG_AUTH|LOG_ERR, "LAM aklog: krb5_cc_get_principal returns %d", r); return r; } increds.client = client_principal; increds.times.endtime = 0; /* Ask for DES since that is what V4 understands */ get_creds_enctype((&increds)) = ENCTYPE_DES_CBC_CRC; r = krb5_get_credentials(context, 0, _krb425_ccache, &increds, creds); return r; }
krb5_error_code _krb5_get_krbtgt(krb5_context context, krb5_ccache id, krb5_realm realm, krb5_creds **cred) { krb5_error_code ret; krb5_creds tmp_cred; memset(&tmp_cred, 0, sizeof(tmp_cred)); ret = krb5_cc_get_principal(context, id, &tmp_cred.client); if (ret) return ret; ret = krb5_make_principal(context, &tmp_cred.server, realm, KRB5_TGS_NAME, realm, NULL); if(ret) { krb5_free_principal(context, tmp_cred.client); return ret; } ret = krb5_get_credentials(context, KRB5_GC_CACHED, id, &tmp_cred, cred); krb5_free_principal(context, tmp_cred.client); krb5_free_principal(context, tmp_cred.server); if(ret) return ret; return 0; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab, krb5_ccache *ccache, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_data req; krb5_ccache local_ccache = NULL; krb5_creds *new_creds = NULL; krb5_auth_context auth_context = NULL; krb5_principal server = NULL; krb5_keytab keytab = NULL; krb5_data_zero (&req); if (ap_req_server == NULL) { char local_hostname[MAXHOSTNAMELEN]; if (gethostname (local_hostname, sizeof(local_hostname)) < 0) { ret = errno; krb5_set_error_message (context, ret, "gethostname: %s", strerror(ret)); return ret; } ret = krb5_sname_to_principal (context, local_hostname, "host", KRB5_NT_SRV_HST, &server); if (ret) goto cleanup; } else server = ap_req_server; if (ap_req_keytab == NULL) { ret = krb5_kt_default (context, &keytab); if (ret) goto cleanup; } else keytab = ap_req_keytab; if (ccache && *ccache) local_ccache = *ccache; else { ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &local_ccache); if (ret) goto cleanup; ret = krb5_cc_initialize (context, local_ccache, creds->client); if (ret) goto cleanup; ret = krb5_cc_store_cred (context, local_ccache, creds); if (ret) goto cleanup; } if (!krb5_principal_compare (context, server, creds->server)) { krb5_creds match_cred; memset (&match_cred, 0, sizeof(match_cred)); match_cred.client = creds->client; match_cred.server = server; ret = krb5_get_credentials (context, 0, local_ccache, &match_cred, &new_creds); if (ret) { if (fail_verify_is_ok (context, options)) ret = 0; goto cleanup; } creds = new_creds; } ret = krb5_mk_req_extended (context, &auth_context, 0, NULL, creds, &req); krb5_auth_con_free (context, auth_context); auth_context = NULL; if (ret) goto cleanup; ret = krb5_rd_req (context, &auth_context, &req, server, keytab, 0, NULL); if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options)) ret = 0; cleanup: if (auth_context) krb5_auth_con_free (context, auth_context); krb5_data_free (&req); if (new_creds != NULL) krb5_free_creds (context, new_creds); if (ap_req_server == NULL && server) krb5_free_principal (context, server); if (ap_req_keytab == NULL && keytab) krb5_kt_close (context, keytab); if (local_ccache != NULL && (ccache == NULL || (ret != 0 && *ccache == NULL))) krb5_cc_destroy (context, local_ccache); if (ret == 0 && ccache != NULL && *ccache == NULL) *ccache = local_ccache; return ret; }
static int renew_validate(krb5_context context, int renew, int validate, krb5_ccache cache, const char *server, krb5_deltat life) { krb5_error_code ret; krb5_creds in, *out = NULL; krb5_kdc_flags flags; memset(&in, 0, sizeof(in)); ret = krb5_cc_get_principal(context, cache, &in.client); if(ret) { krb5_warn(context, ret, "krb5_cc_get_principal"); return ret; } ret = get_server(context, in.client, server, &in.server); if(ret) { krb5_warn(context, ret, "get_server"); goto out; } if (renew) { /* * no need to check the error here, it's only to be * friendly to the user */ krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); } flags.i = 0; flags.b.renewable = flags.b.renew = renew; flags.b.validate = validate; if (forwardable_flag != -1) flags.b.forwardable = forwardable_flag; else if (out) flags.b.forwardable = out->flags.b.forwardable; if (proxiable_flag != -1) flags.b.proxiable = proxiable_flag; else if (out) flags.b.proxiable = out->flags.b.proxiable; if (anonymous_flag) flags.b.request_anonymous = anonymous_flag; if(life) in.times.endtime = time(NULL) + life; if (out) { krb5_free_creds (context, out); out = NULL; } ret = krb5_get_kdc_cred(context, cache, flags, NULL, NULL, &in, &out); if(ret) { krb5_warn(context, ret, "krb5_get_kdc_cred"); goto out; } ret = krb5_cc_initialize(context, cache, in.client); if(ret) { krb5_free_creds (context, out); krb5_warn(context, ret, "krb5_cc_initialize"); goto out; } ret = krb5_cc_store_cred(context, cache, out); if(ret == 0 && server == NULL) { /* only do this if it's a general renew-my-tgt request */ #ifndef NO_AFS if(do_afslog && k_hasafs()) krb5_afslog(context, cache, NULL, NULL); #endif } krb5_free_creds (context, out); if(ret) { krb5_warn(context, ret, "krb5_cc_store_cred"); goto out; } out: krb5_free_cred_contents(context, &in); return ret; }
/* Get a TGT for use at the remote host */ krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf) /* Should forwarded TGT also be forwardable? */ { krb5_replay_data replaydata; krb5_data * scratch = 0; krb5_address **addrs = NULL; krb5_error_code retval; krb5_creds creds, tgt; krb5_creds *pcreds; krb5_flags kdcoptions; int close_cc = 0; int free_rhost = 0; krb5_enctype enctype = 0; krb5_keyblock *session_key; krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes; memset((char *)&creds, 0, sizeof(creds)); memset((char *)&tgt, 0, sizeof(creds)); if (cc == 0) { if ((retval = krb5int_cc_default(context, &cc))) goto errout; close_cc = 1; } retval = krb5_auth_con_getkey (context, auth_context, &session_key); if (retval) goto errout; if (session_key) { enctype = session_key->enctype; krb5_free_keyblock (context, session_key); session_key = NULL; } else if (server) { /* must server be non-NULL when rhost is given? */ /* Try getting credentials to see what the remote side supports. Not bulletproof, just a heuristic. */ krb5_creds in, *out = 0; memset (&in, 0, sizeof(in)); retval = krb5_copy_principal (context, server, &in.server); if (retval) goto punt; retval = krb5_copy_principal (context, client, &in.client); if (retval) goto punt; retval = krb5_get_credentials (context, 0, cc, &in, &out); if (retval) goto punt; /* Got the credentials. Okay, now record the enctype and throw them away. */ enctype = out->keyblock.enctype; krb5_free_creds (context, out); punt: krb5_free_cred_contents (context, &in); } if ((retval = krb5_copy_principal(context, client, &creds.client))) goto errout; if ((retval = krb5_build_principal_ext(context, &creds.server, client->realm.length, client->realm.data, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, client->realm.length, client->realm.data, 0))) goto errout; /* fetch tgt directly from cache */ context->use_conf_ktypes = 1; retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES, &creds, &tgt); context->use_conf_ktypes = old_use_conf_ktypes; if (retval) goto errout; /* tgt->client must be equal to creds.client */ if (!krb5_principal_compare(context, tgt.client, creds.client)) { /* Solaris Kerberos */ char *r_name = NULL; char *t_name = NULL; krb5_error_code r_err, t_err; t_err = krb5_unparse_name(context, tgt.client, &t_name); r_err = krb5_unparse_name(context, creds.client, &r_name); krb5_set_error_message(context, KRB5_PRINC_NOMATCH, dgettext(TEXT_DOMAIN, "Requested principal and ticket don't match: Requested principal is '%s' and TGT principal is '%s'"), r_err ? "unknown" : r_name, t_err ? "unknown" : t_name); if (r_name) krb5_free_unparsed_name(context, r_name); if (t_name) krb5_free_unparsed_name(context, t_name); retval = KRB5_PRINC_NOMATCH; goto errout; } if (!tgt.ticket.length) { retval = KRB5_NO_TKT_SUPPLIED; goto errout; } if (tgt.addresses && *tgt.addresses) { if (rhost == NULL) { if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) { retval = KRB5_FWD_BAD_PRINCIPAL; goto errout; } if (krb5_princ_size(context, server) < 2){ retval = KRB5_CC_BADNAME; goto errout; } rhost = malloc(server->data[1].length+1); if (!rhost) { retval = ENOMEM; goto errout; } free_rhost = 1; /* Solaris Kerberos */ (void) memcpy(rhost, server->data[1].data, server->data[1].length); rhost[server->data[1].length] = '\0'; } retval = krb5_os_hostaddr(context, rhost, &addrs); if (retval) goto errout; } creds.keyblock.enctype = enctype; creds.times = tgt.times; creds.times.starttime = 0; kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */ kdcoptions &= ~(KDC_OPT_FORWARDABLE); if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) { if (enctype) { creds.keyblock.enctype = 0; if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) goto errout; } else goto errout; } retval = krb5_mk_1cred(context, auth_context, pcreds, &scratch, &replaydata); krb5_free_creds(context, pcreds); /* * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be * more robust. */ if (scratch) { if (retval) krb5_free_data(context, scratch); else { *outbuf = *scratch; krb5_xfree(scratch); } } errout: if (addrs) krb5_free_addresses(context, addrs); /* Solaris Kerberos */ if (close_cc) (void) krb5_cc_close(context, cc); if (free_rhost) free(rhost); krb5_free_cred_contents(context, &creds); krb5_free_cred_contents(context, &tgt); return retval; }
static krb5_error_code renew_validate(krb5_context context, int renew, int validate, krb5_ccache cache, const char *server, krb5_deltat life) { krb5_error_code ret; krb5_ccache tempccache = NULL; krb5_creds in, *out = NULL; krb5_kdc_flags flags; memset(&in, 0, sizeof(in)); ret = krb5_cc_get_principal(context, cache, &in.client); if (ret) { krb5_warn(context, ret, "krb5_cc_get_principal"); return ret; } ret = get_server(context, in.client, server, &in.server); if (ret) { krb5_warn(context, ret, "get_server"); goto out; } if (renew) { /* * no need to check the error here, it's only to be * friendly to the user */ krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out); } flags.i = 0; flags.b.renewable = flags.b.renew = renew; flags.b.validate = validate; if (forwardable_flag != -1) flags.b.forwardable = forwardable_flag; else if (out) flags.b.forwardable = out->flags.b.forwardable; if (proxiable_flag != -1) flags.b.proxiable = proxiable_flag; else if (out) flags.b.proxiable = out->flags.b.proxiable; if (anonymous_flag) flags.b.request_anonymous = anonymous_flag; if (life) in.times.endtime = time(NULL) + life; if (out) { krb5_free_creds(context, out); out = NULL; } ret = krb5_get_kdc_cred(context, cache, flags, NULL, NULL, &in, &out); if (ret) { krb5_warn(context, ret, "krb5_get_kdc_cred"); goto out; } ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, cache), NULL, &tempccache); if (ret) { krb5_warn(context, ret, "krb5_cc_new_unique"); goto out; } ret = krb5_cc_initialize(context, tempccache, in.client); if (ret) { krb5_warn(context, ret, "krb5_cc_initialize"); goto out; } ret = krb5_cc_store_cred(context, tempccache, out); if (ret) { krb5_warn(context, ret, "krb5_cc_store_cred"); goto out; } /* * We want to preserve cc configs as some are security-relevant, and * anyways it's the friendly thing to do. */ ret = copy_configs(context, tempccache, cache, out->server); if (ret) goto out; ret = krb5_cc_move(context, tempccache, cache); if (ret) { krb5_warn(context, ret, "krb5_cc_move"); goto out; } tempccache = NULL; out: if (tempccache) krb5_cc_close(context, tempccache); if (out) krb5_free_creds(context, out); krb5_free_cred_contents(context, &in); return ret; }
int _GetSecurityObject(struct afscp_cell *cell) { int code = ENOENT; #ifdef HAVE_KERBEROS krb5_context context; krb5_creds match; krb5_creds *cred; krb5_ccache cc; char **realms, *realm; struct afsconf_cell celldata; char localcell[MAXCELLCHARS + 1]; struct rx_securityClass *sc; struct ktc_encryptionKey k; int i; rxkad_level l; code = _GetCellInfo(cell->name, &celldata); if (code != 0) { goto try_anon; } if (authas_name[0]) { code = _GetLocalSecurityObject(cell, authas_name, authas_inst); if (code == 0) { return 0; } } code = krb5_init_context(&context); /* see aklog.c main() */ if (code != 0) { goto try_anon; } if (cell->realm == NULL) { realm = NULL; code = krb5_get_host_realm(context, celldata.hostName[0], &realms); if (code == 0) { strlcpy(localcell, realms[0], sizeof(localcell)); krb5_free_host_realm(context, realms); realm = localcell; } else goto try_anon; } else { realm = cell->realm; strlcpy(localcell, realm, MAXCELLCHARS + 1); } if (realm) if (realm == NULL) { for (i = 0; (i < MAXCELLCHARS && cell->name[i]); i++) { if (isalpha(cell->name[i])) localcell[i] = toupper(cell->name[i]); else localcell[i] = cell->name[i]; } localcell[i] = '\0'; realm = localcell; } cc = NULL; code = krb5_cc_default(context, &cc); memset(&match, 0, sizeof(match)); Z_enctype(Z_credskey(&match)) = ENCTYPE_DES_CBC_CRC; if (code == 0) code = krb5_cc_get_principal(context, cc, &match.client); if (code == 0) code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", cell->name, NULL); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_principal(context, match.server); match.server = NULL; code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", NULL); if (code == 0) code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } } if (insecure) l = rxkad_clear; else l = rxkad_crypt; memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8); sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5, cred->ticket.length, cred->ticket.data); krb5_free_creds(context, cred); krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); cell->security = sc; cell->scindex = 2; return 0; try_anon: #endif /* HAVE_KERBEROS */ if (try_anonymous) return _GetNullSecurityObject(cell); else return code; }
krb5_error_code kdc_set_password(krb5_context context, krb5_ccache ccache, char *newpw, char *user, char *domain, int *result_code, char *admin_server) { krb5_data chpw_snd; krb5_data chpw_rcv; krb5_data result_string; krb5_data result_code_string; krb5_address local_kaddr; krb5_address remote_kaddr; char userrealm[256]; char temp[256]; krb5_error_code code; struct sockaddr local_addr; struct sockaddr remote_addr; int i; int addrlen; int cc; int local_result_code; int nfds; krb5_principal targprinc; struct timeval TimeVal; fd_set readfds; krb5_creds *credsp = NULL; struct hostent *hp; SOCKET kdc_socket; struct sockaddr_in kdc_server; krb5_auth_context auth_context = NULL; krb5_creds creds; krb5_data ap_req; char *code_string; memset(&local_addr, 0, sizeof(local_addr)); memset(&local_kaddr, 0, sizeof(local_kaddr)); memset(&result_string, 0, sizeof(result_string)); memset(&remote_kaddr, 0, sizeof(remote_kaddr)); memset(&chpw_snd, 0, sizeof(krb5_data)); memset(&chpw_rcv, 0, sizeof(krb5_data)); memset(userrealm, '\0', sizeof(userrealm)); targprinc = NULL; chpw_rcv.length = 1500; chpw_rcv.data = (char *) malloc(chpw_rcv.length); for (i = 0; i < (int)strlen(domain); i++) userrealm[i] = toupper(domain[i]); sprintf(temp, "%s@%s", user, userrealm); krb5_parse_name(context, temp, &targprinc); if (credsp == NULL) { memset(&creds, 0, sizeof(creds)); memset(&ap_req, 0, sizeof(krb5_data)); memset(&result_string, 0, sizeof(krb5_data)); memset(&result_code_string, 0, sizeof(krb5_data)); sprintf(temp, "%s@%s", "kadmin/changepw", userrealm); if(code = krb5_init_context(&context)) goto cleanup; if(code = krb5_cc_default(context, &ccache)) goto cleanup; if (krb5_parse_name(context, temp, &creds.server)) goto cleanup; if (krb5_cc_get_principal(context, ccache, &creds.client)) goto cleanup; if (krb5_get_credentials(context, 0, ccache, &creds, &credsp)) goto cleanup; } if ((code = krb5_change_set_password(context, credsp, newpw, targprinc, &result_code, &result_code_string, &result_string))) { goto cleanup; } cleanup: if (targprinc != NULL) krb5_free_principal(context, targprinc); return(code); }
krb5_error_code KRB5_CALLCONV krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server_arg, krb5_keytab keytab_arg, krb5_ccache *ccache_arg, krb5_verify_init_creds_opt *options) { krb5_error_code ret; krb5_principal server; krb5_keytab keytab; krb5_ccache ccache; krb5_keytab_entry kte; krb5_creds in_creds, *out_creds; krb5_auth_context authcon; krb5_data ap_req; /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */ server = NULL; keytab = NULL; ccache = NULL; out_creds = NULL; authcon = NULL; ap_req.data = NULL; if (keytab_arg) { keytab = keytab_arg; } else { if ((ret = krb5_kt_default(context, &keytab))) goto cleanup; } if (server_arg) { ret = krb5_copy_principal(context, server_arg, &server); if (ret) goto cleanup; } else { /* Use a principal name from the keytab. */ ret = k5_kt_get_principal(context, keytab, &server); if (ret) { /* There's no keytab, or it's empty, or we can't read it. * Allow this unless configuration demands verification. */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } } /* first, check if the server is in the keytab. If not, there's no reason to continue. rd_req does all this, but there's no way to know that a given error is caused by a missing keytab or key, and not by some other problem. */ if (krb5_is_referral_realm(&server->realm)) { krb5_free_data_contents(context, &server->realm); ret = krb5_get_default_realm(context, &server->realm.data); if (ret) goto cleanup; server->realm.length = strlen(server->realm.data); } if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) { /* this means there is no keying material. This is ok, as long as it is not prohibited by the configuration */ if (!nofail(context, options, creds)) ret = 0; goto cleanup; } krb5_kt_free_entry(context, &kte); /* If the creds are for the server principal, we're set, just do a mk_req. * Otherwise, do a get_credentials first. */ if (krb5_principal_compare(context, server, creds->server)) { /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req))) goto cleanup; } else { /* this is unclean, but it's the easiest way without ripping the library into very small pieces. store the client's initial cred in a memory ccache, then call the library. Later, we'll copy everything except the initial cred into the ccache we return to the user. A clean implementation would involve library internals with a coherent idea of "in" and "out". */ /* insert the initial cred into the ccache */ if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) { ccache = NULL; goto cleanup; } if ((ret = krb5_cc_initialize(context, ccache, creds->client))) goto cleanup; if ((ret = krb5_cc_store_cred(context, ccache, creds))) goto cleanup; /* set up for get_creds */ memset(&in_creds, 0, sizeof(in_creds)); in_creds.client = creds->client; in_creds.server = server; if ((ret = krb5_timeofday(context, &in_creds.times.endtime))) goto cleanup; in_creds.times.endtime += 5*60; if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds))) goto cleanup; /* make an ap_req */ if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds, &ap_req))) goto cleanup; } /* wipe the auth context for mk_req */ if (authcon) { krb5_auth_con_free(context, authcon); authcon = NULL; } /* verify the ap_req */ if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL))) goto cleanup; /* if we get this far, then the verification succeeded. We can still fail if the library stuff here fails, but that's it */ if (ccache_arg && ccache) { if (*ccache_arg == NULL) { krb5_ccache retcc; retcc = NULL; if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) || (ret = krb5_cc_initialize(context, retcc, creds->client)) || (ret = copy_creds_except(context, ccache, retcc, creds->server))) { if (retcc) krb5_cc_destroy(context, retcc); } else { *ccache_arg = retcc; } } else { ret = copy_creds_except(context, ccache, *ccache_arg, server); } } /* if any of the above paths returned an errors, then ret is set accordingly. * Either that, or it's zero, which is fine, too */ cleanup: if ( server) krb5_free_principal(context, server); if (!keytab_arg && keytab) krb5_kt_close(context, keytab); if (ccache) krb5_cc_destroy(context, ccache); if (out_creds) krb5_free_creds(context, out_creds); if (authcon) krb5_auth_con_free(context, authcon); if (ap_req.data) free(ap_req.data); return(ret); }
/* * Request: * NameZ * WhichFields * MatchCreds * * Response: * Creds * */ static krb5_error_code kcm_op_retrieve(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { uint32_t flags; krb5_creds mcreds; krb5_error_code ret; kcm_ccache ccache; char *name; krb5_creds *credp; int free_creds = 0; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = krb5_ret_uint32(request, &flags); if (ret) { free(name); return ret; } ret = krb5_ret_creds_tag(request, &mcreds); if (ret) { free(name); return ret; } if (disallow_getting_krbtgt && mcreds.server->name.name_string.len == 2 && strcmp(mcreds.server->name.name_string.val[0], KRB5_TGS_NAME) == 0) { free(name); krb5_free_cred_contents(context, &mcreds); return KRB5_FCC_PERM; } ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret) { free(name); krb5_free_cred_contents(context, &mcreds); return ret; } ret = kcm_ccache_retrieve_cred(context, ccache, flags, &mcreds, &credp); if (ret && ((flags & KRB5_GC_CACHED) == 0) && !krb5_is_config_principal(context, mcreds.server)) { krb5_ccache_data ccdata; /* try and acquire */ HEIMDAL_MUTEX_lock(&ccache->mutex); /* Fake up an internal ccache */ kcm_internal_ccache(context, ccache, &ccdata); /* glue cc layer will store creds */ ret = krb5_get_credentials(context, 0, &ccdata, &mcreds, &credp); if (ret == 0) free_creds = 1; HEIMDAL_MUTEX_unlock(&ccache->mutex); } if (ret == 0) { ret = krb5_store_creds(response, credp); } free(name); krb5_free_cred_contents(context, &mcreds); kcm_release_ccache(context, ccache); if (free_creds) krb5_free_cred_contents(context, credp); return ret; }
krb5_error_code KRB5_CALLCONV krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) { krb5_octet result; krb5_creds creds; krb5_creds * credsp = NULL; krb5_creds * credspout = NULL; krb5_error_code retval = 0; krb5_data inbuf, outbuf; int len; krb5_ccache use_ccache = 0; if (error) *error = 0; /* * First, send over the length of the sendauth version string; * then, we send over the sendauth version. Next, we send * over the length of the application version strings followed * by the string itself. */ outbuf.length = strlen(sendauth_version) + 1; outbuf.data = (char *) sendauth_version; if ((retval = krb5_write_message(context, fd, &outbuf))) return(retval); outbuf.length = strlen(appl_version) + 1; outbuf.data = appl_version; if ((retval = krb5_write_message(context, fd, &outbuf))) return(retval); /* * Now, read back a byte: 0 means no error, 1 means bad sendauth * version, 2 means bad application version */ len = krb5_net_read(context, *((int *) fd), (char *)&result, 1); if (len != 1) return((len < 0) ? errno : ECONNABORTED); if (result == 1) return(KRB5_SENDAUTH_BADAUTHVERS); else if (result == 2) return(KRB5_SENDAUTH_BADAPPLVERS); else if (result != 0) return(KRB5_SENDAUTH_BADRESPONSE); /* * We're finished with the initial negotiations; let's get and * send over the authentication header. (The AP_REQ message) */ /* * If no credentials were provided, try getting it from the * credentials cache. */ memset((char *)&creds, 0, sizeof(creds)); /* * See if we need to access the credentials cache */ if (!in_creds || !in_creds->ticket.length) { if (ccache) use_ccache = ccache; /* Solaris Kerberos */ else if ((retval = krb5int_cc_default(context, &use_ccache)) != 0) goto error_return; } if (!in_creds) { if ((retval = krb5_copy_principal(context, server, &creds.server))) goto error_return; if (client) retval = krb5_copy_principal(context, client, &creds.client); else retval = krb5_cc_get_principal(context, use_ccache, &creds.client); if (retval) { krb5_free_principal(context, creds.server); goto error_return; } /* creds.times.endtime = 0; -- memset 0 takes care of this zero means "as long as possible" */ /* creds.keyblock.enctype = 0; -- as well as this. zero means no session enctype preference */ in_creds = &creds; } if (!in_creds->ticket.length) { /* Solaris Kerberos */ if ((retval = krb5_get_credentials(context, 0, use_ccache, in_creds, &credsp)) != 0) goto error_return; credspout = credsp; } else { credsp = in_creds; } if (ap_req_options & AP_OPTS_USE_SUBKEY) { /* Provide some more fodder for random number code. This isn't strong cryptographically; the point here is not to guarantee randomness, but to make it less likely that multiple sessions could pick the same subkey. */ char rnd_data[1024]; GETPEERNAME_ARG3_TYPE len2; krb5_data d; d.length = sizeof (rnd_data); d.data = rnd_data; len2 = sizeof (rnd_data); if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data, &len2) == 0) { d.length = len2; /* Solaris Kerberos */ (void) krb5_c_random_seed (context, &d); } len2 = sizeof (rnd_data); if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data, &len2) == 0) { d.length = len2; /* Solaris Kerberos */ (void) krb5_c_random_seed (context, &d); } } /* Solaris Kerberos */ if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, credsp, &outbuf)) != 0) goto error_return; /* * First write the length of the AP_REQ message, then write * the message itself. */ retval = krb5_write_message(context, fd, &outbuf); free(outbuf.data); if (retval) goto error_return; /* * Now, read back a message. If it was a null message (the * length was zero) then there was no error. If not, we the * authentication was rejected, and we need to return the * error structure. */ /* Solaris Kerberos */ if ((retval = krb5_read_message(context, fd, &inbuf)) != 0) goto error_return; if (inbuf.length) { if (error) { /* Solaris Kerberos */ if ((retval = krb5_rd_error(context, &inbuf, error)) != 0) { krb5_xfree(inbuf.data); goto error_return; } } retval = KRB5_SENDAUTH_REJECTED; krb5_xfree(inbuf.data); goto error_return; } /* * If we asked for mutual authentication, we should now get a * length field, followed by a AP_REP message */ if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { krb5_ap_rep_enc_part *repl = 0; /* Solaris Kerberos */ if ((retval = krb5_read_message(context, fd, &inbuf)) != 0) goto error_return; /* Solaris Kerberos */ if ((retval = krb5_rd_rep(context, *auth_context, &inbuf, &repl)) != 0) { if (repl) krb5_free_ap_rep_enc_part(context, repl); krb5_xfree(inbuf.data); goto error_return; } krb5_xfree(inbuf.data); /* * If the user wants to look at the AP_REP message, * copy it for them. */ if (rep_result) *rep_result = repl; else krb5_free_ap_rep_enc_part(context, repl); } retval = 0; /* Normal return */ if (out_creds) { *out_creds = credsp; credspout = NULL; } error_return: krb5_free_cred_contents(context, &creds); if (credspout != NULL) krb5_free_creds(context, credspout); /* Solaris Kerberos */ if (!ccache && use_ccache) (void) krb5_cc_close(context, use_ccache); return(retval); }