int main(int argc, char **argv) { krb5_context ctx, ctx2; krb5_plugin_initvt_fn *mods; const krb5_enctype etypes1[] = { ENCTYPE_DES3_CBC_SHA1, 0 }; const krb5_enctype etypes2[] = { ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }; krb5_prompt_type ptypes[] = { KRB5_PROMPT_TYPE_PASSWORD }; /* Copy a default context and verify the result. */ check(krb5_init_context(&ctx) == 0); check(krb5_copy_context(ctx, &ctx2) == 0); check_context(ctx2, ctx); krb5_free_context(ctx2); /* Set non-default values for all of the propagated fields in ctx. */ ctx->allow_weak_crypto = TRUE; check(krb5_set_default_in_tkt_ktypes(ctx, etypes1) == 0); check(krb5_set_default_tgs_enctypes(ctx, etypes2) == 0); check(krb5_set_debugging_time(ctx, 1234, 5678) == 0); check(krb5_cc_set_default_name(ctx, "defccname") == 0); check(krb5_set_default_realm(ctx, "defrealm") == 0); ctx->clockskew = 18; ctx->kdc_req_sumtype = CKSUMTYPE_NIST_SHA; ctx->default_ap_req_sumtype = CKSUMTYPE_HMAC_SHA1_96_AES128; ctx->default_safe_sumtype = CKSUMTYPE_HMAC_SHA1_96_AES256; ctx->kdc_default_options = KDC_OPT_FORWARDABLE; ctx->library_options = 0; ctx->profile_secure = TRUE; ctx->udp_pref_limit = 2345; ctx->use_conf_ktypes = TRUE; ctx->ignore_acceptor_hostname = TRUE; ctx->dns_canonicalize_hostname = CANONHOST_FALSE; free(ctx->plugin_base_dir); check((ctx->plugin_base_dir = strdup("/a/b/c/d")) != NULL); /* Also set some of the non-propagated fields. */ ctx->prompt_types = ptypes; check(k5_plugin_load_all(ctx, PLUGIN_INTERFACE_PWQUAL, &mods) == 0); k5_plugin_free_modules(ctx, mods); k5_setmsg(ctx, ENOMEM, "nooooooooo"); krb5_set_trace_callback(ctx, trace, ctx); /* Copy the intentionally messy context and verify the result. */ check(krb5_copy_context(ctx, &ctx2) == 0); check_context(ctx2, ctx); krb5_free_context(ctx2); krb5_free_context(ctx); return 0; }
kim_error kim_identity_copy (kim_identity *out_identity, kim_identity in_identity) { kim_error err = KIM_NO_ERROR; kim_identity identity = KIM_IDENTITY_ANY; if (!err && !out_identity) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && in_identity != KIM_IDENTITY_ANY) { err = kim_identity_allocate (&identity); if (!err) { err = krb5_error (in_identity->context, krb5_copy_context (in_identity->context, &identity->context)); } if (!err) { err = krb5_error (identity->context, krb5_copy_principal (identity->context, in_identity->principal, &identity->principal)); } } if (!err) { *out_identity = identity; identity = NULL; } kim_identity_free (&identity); return check_error (err); }
kim_error kim_identity_create_from_krb5_principal (kim_identity *out_identity, krb5_context in_krb5_context, krb5_principal in_krb5_principal) { kim_error err = KIM_NO_ERROR; kim_identity identity = NULL; if (!err && !out_identity ) { err = check_error (KIM_NULL_PARAMETER_ERR); } if (!err && !in_krb5_principal) { err = check_error (KIM_NULL_PARAMETER_ERR); } /* KLCreatePrincipalFromKerberos5Principal passes NULL in_krb5_context */ if (!err) { err = kim_identity_allocate (&identity); } if (!err) { if (in_krb5_context) { err = krb5_error (in_krb5_context, krb5_copy_context (in_krb5_context, &identity->context)); } else { err = krb5_error (NULL, krb5_init_context (&identity->context)); } } if (!err) { err = krb5_error (identity->context, krb5_copy_principal (identity->context, in_krb5_principal, &identity->principal)); } if (!err) { *out_identity = identity; identity = NULL; } kim_identity_free (&identity); return check_error (err); }
/* * Validate user/pass (Heimdal) */ static rlm_rcode_t krb5_auth(void *instance, REQUEST *request) { rlm_krb5_t *inst = instance; rlm_rcode_t rcode; krb5_error_code ret; krb5_principal client; krb5_ccache ccache; krb5_keytab keytab; krb5_verify_opt options; krb5_context *context = NULL; /* * See above in MIT krb5_auth */ ret = krb5_copy_context(*(inst->context), context); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s", inst->xlat_name, error_message(ret)); return RLM_MODULE_FAIL; } /* * Setup krb5_verify_user options * * Not entirely sure this is necessary, but as we use context * to get the cache handle, we probably do have to do this with * the cloned context. */ krb5_cc_default(*context, &ccache); krb5_verify_opt_init(&options); krb5_verify_opt_set_ccache(&options, ccache); memset(&keytab, 0, sizeof(keytab)); ret = inst->keytabname ? krb5_kt_resolve(*context, inst->keytabname, &keytab) : krb5_kt_default(*context, &keytab); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s", inst->xlat_name, error_message(ret)); goto cleanup; } krb5_verify_opt_set_keytab(&options, keytab); krb5_verify_opt_set_secure(&options, TRUE); if (inst->service) { krb5_verify_opt_set_service(&options, inst->service); } rcode = krb5_parse_user(inst, request, &client); if (rcode != RLM_MODULE_OK) goto cleanup; /* * Verify the user, using the options we set in instantiate */ ret = krb5_verify_user_opt(*context, client, request->password->vp_strvalue, &options); if (ret) { switch (ret) { case KRB5_LIBOS_BADPWDMATCH: case KRB5KRB_AP_ERR_BAD_INTEGRITY: RDEBUG("Provided password was incorrect: %s", error_message(ret)); rcode = RLM_MODULE_REJECT; break; case KRB5KDC_ERR_KEY_EXP: case KRB5KDC_ERR_CLIENT_REVOKED: case KRB5KDC_ERR_SERVICE_REVOKED: RDEBUG("Account has been locked out: %s", error_message(ret)); rcode = RLM_MODULE_USERLOCK; break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: RDEBUG("User not found: %s", error_message(ret)); rcode = RLM_MODULE_NOTFOUND; default: radlog(L_ERR, "rlm_krb5 (%s): Verifying user failed: " "%s", inst->xlat_name, error_message(ret)); rcode = RLM_MODULE_FAIL; break; } goto cleanup; } cleanup: krb5_free_context(*context); krb5_kt_close(*context, keytab); return rcode; }
/* * Validate userid/passwd (MIT) */ static rlm_rcode_t krb5_auth(void *instance, REQUEST *request) { rlm_krb5_t *inst = instance; rlm_rcode_t rcode; krb5_error_code ret; krb5_principal client; krb5_creds init_creds; krb5_keytab keytab; krb5_context *context = NULL; /* * All the snippets on threadsafety say that individual threads * must each use their own copy of context. * * As we don't have any per thread instantiation, we either have * to clone inst->context on every request, or use the connection * API. * * @todo Use the connection API (3.0 only). */ ret = krb5_copy_context(*(inst->context), context); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Error cloning krb5 context: %s", inst->xlat_name, error_message(ret)); return RLM_MODULE_FAIL; } /* * Check we have all the required VPs, and convert the username * into a principal. */ rcode = krb5_parse_user(inst, request, &client); if (rcode != RLM_MODULE_OK) goto cleanup; /* * Retrieve the TGT from the TGS/KDC and check we can decrypt it. */ memset(&init_creds, 0, sizeof(init_creds)); ret = krb5_get_init_creds_password(*context, &init_creds, client, request->password->vp_strvalue, NULL, NULL, 0, NULL, inst->gic_options); if (ret) { error: switch (ret) { case KRB5_LIBOS_BADPWDMATCH: case KRB5KRB_AP_ERR_BAD_INTEGRITY: RDEBUG("Provided password was incorrect: %s", error_message(ret)); rcode = RLM_MODULE_REJECT; break; case KRB5KDC_ERR_KEY_EXP: case KRB5KDC_ERR_CLIENT_REVOKED: case KRB5KDC_ERR_SERVICE_REVOKED: RDEBUG("Account has been locked out: %s", error_message(ret)); rcode = RLM_MODULE_USERLOCK; break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: RDEBUG("User not found: %s", error_message(ret)); rcode = RLM_MODULE_NOTFOUND; default: radlog(L_ERR, "rlm_krb5 (%s): Failed getting/verifying " "credentials: %s", inst->xlat_name, error_message(ret)); rcode = RLM_MODULE_FAIL; break; } goto cleanup; } RDEBUG("Successfully retrieved and decrypted TGT"); memset(&keytab, 0, sizeof(keytab)); ret = inst->keytabname ? krb5_kt_resolve(*context, inst->keytabname, &keytab) : krb5_kt_default(*context, &keytab); if (ret) { radlog(L_ERR, "rlm_krb5 (%s): Resolving keytab failed: %s", inst->xlat_name, error_message(ret)); goto cleanup; } ret = krb5_verify_init_creds(*context, &init_creds, inst->server, keytab, NULL, inst->vic_options); if (ret) goto error; cleanup: krb5_free_cred_contents(*context, &init_creds); krb5_free_context(*context); krb5_kt_close(*context, keytab); return rcode; }