krb5_error_code smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx, struct tevent_context *ev, struct loadparm_context *lp_ctx, krb5_context *_krb5_context) { krb5_error_code ret; char **config_files; const char *config_file, *realm; krb5_context krb5_ctx; initialize_krb5_error_table(); ret = krb5_init_context(&krb5_ctx); if (ret) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ret; } config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf"); if (!config_file) { krb5_free_context(krb5_ctx); return ENOMEM; } /* Use our local krb5.conf file by default */ ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files); if (ret) { DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } ret = krb5_set_config_files(krb5_ctx, config_files); krb5_free_config_files(config_files); if (ret) { DEBUG(1,("krb5_set_config_files failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } realm = lp_realm(lp_ctx); if (realm != NULL) { ret = krb5_set_default_realm(krb5_ctx, realm); if (ret) { DEBUG(1,("krb5_set_default_realm failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } } *_krb5_context = krb5_ctx; return 0; }
static int net_lookup_kdc(struct net_context *c, int argc, const char **argv) { #ifdef HAVE_KRB5 krb5_error_code rc; krb5_context ctx; struct ip_service *kdcs; const char *realm; int num_kdcs = 0; int i; NTSTATUS status; initialize_krb5_error_table(); rc = krb5_init_context(&ctx); if (rc) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(rc))); return -1; } if (argc > 0) { realm = argv[0]; } else if (lp_realm() && *lp_realm()) { realm = lp_realm(); } else { char **realms; rc = krb5_get_host_realm(ctx, NULL, &realms); if (rc) { DEBUG(1,("krb5_gethost_realm failed (%s)\n", error_message(rc))); return -1; } realm = (const char *) *realms; } status = get_kdc_list(realm, NULL, &kdcs, &num_kdcs); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("get_kdc_list failed (%s)\n", nt_errstr(status))); return -1; } for (i = 0; i < num_kdcs; i++) { char addr[INET6_ADDRSTRLEN]; print_sockaddr(addr, sizeof(addr), &kdcs[i].ss); d_printf("%s:%u\n", addr, kdcs[i].port); } return 0; #endif DEBUG(1, ("No kerberos support\n")); return -1; }
static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out) { krb5_context context = NULL; krb5_error_code kerr = 0; krb5_data reply; krb5_principal host_princ = NULL; char *host_princ_s = NULL; BOOL ret = False; *pblob_out = data_blob(NULL,0); initialize_krb5_error_table(); kerr = krb5_init_context(&context); if (kerr) { return False; } /* Create server principal. */ asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm()); if (!host_princ_s) { goto out; } strlower_m(host_princ_s); kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ); if (kerr) { DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n", host_princ_s, error_message(kerr) )); goto out; } kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply); if (kerr) { DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n", error_message(kerr) )); goto out; } *pblob_out = data_blob(reply.data, reply.length); kerberos_free_data_contents(context,&reply); ret = True; out: if (host_princ_s) { SAFE_FREE(host_princ_s); } if (host_princ) { krb5_free_principal(context, host_princ); } krb5_free_context(context); return ret; }
krb5_error_code libnet_keytab_init(TALLOC_CTX *mem_ctx, const char *keytab_name, struct libnet_keytab_context **ctx) { krb5_error_code ret = 0; krb5_context context = NULL; krb5_keytab keytab = NULL; const char *keytab_string = NULL; struct libnet_keytab_context *r; r = talloc_zero(mem_ctx, struct libnet_keytab_context); if (!r) { return ENOMEM; } talloc_set_destructor(r, keytab_close); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("keytab_init: could not krb5_init_context: %s\n", error_message(ret))); return ret; } ret = smb_krb5_open_keytab(context, keytab_name, true, &keytab); if (ret) { DEBUG(1,("keytab_init: smb_krb5_open_keytab failed (%s)\n", error_message(ret))); krb5_free_context(context); return ret; } ret = smb_krb5_keytab_name(mem_ctx, context, keytab, &keytab_string); if (ret) { krb5_kt_close(context, keytab); krb5_free_context(context); return ret; } r->context = context; r->keytab = keytab; r->keytab_name = keytab_string; r->clean_old_entries = false; *ctx = r; return 0; }
void initkrb5(void) { PyObject *module, *dict; #if !defined(__APPLE__) || !defined(__MACH__) initialize_krb5_error_table(); #endif module = Py_InitModule("krb5", k5_methods); dict = PyModule_GetDict(module); k5_error = PyErr_NewException("freeadi.protocol.krb5.Error", NULL, NULL); PyDict_SetItemString(dict, "Error", k5_error); }
void krb5_init_ets (krb5_context context) { static int inited = 0; if (inited == 0) { initialize_krb5_error_table(); initialize_k5e1_error_table(); initialize_kv5m_error_table(); initialize_kdb5_error_table(); initialize_asn1_error_table(); initialize_k524_error_table(); inited++; } }
static int net_lookup_kdc(struct net_context *c, int argc, const char **argv) { #ifdef HAVE_KRB5 krb5_error_code rc; krb5_context ctx; struct sockaddr_in *addrs; int num_kdcs,i; krb5_data realm; char **realms; initialize_krb5_error_table(); rc = krb5_init_context(&ctx); if (rc) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(rc))); return -1; } if (argc>0) { realm.data = discard_const_p(char, argv[0]); realm.length = strlen(argv[0]); } else if (lp_realm() && *lp_realm()) {
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, /* FILE:/tmp/krb5cc_0 */ const char *client_string, /* [email protected] */ const char *service_string, /* krbtgt/[email protected] */ time_t *expire_time) { krb5_error_code ret; krb5_context context = NULL; krb5_ccache ccache = NULL; krb5_principal client = NULL; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { goto done; } if (!ccache_string) { ccache_string = krb5_cc_default_name(context); } DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string)); /* FIXME: we should not fall back to defaults */ ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache); if (ret) { goto done; } #ifdef HAVE_KRB5_GET_RENEWED_CREDS /* MIT */ { krb5_creds creds; if (client_string) { ret = smb_krb5_parse_name(context, client_string, &client); if (ret) { goto done; } } else { ret = krb5_cc_get_principal(context, ccache, &client); if (ret) { goto done; } } ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string)); if (ret) { DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret))); goto done; } /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */ ret = krb5_cc_initialize(context, ccache, client); if (ret) { goto done; } ret = krb5_cc_store_cred(context, ccache, &creds); if (expire_time) { *expire_time = (time_t) creds.times.endtime; } krb5_free_cred_contents(context, &creds); } #elif defined(HAVE_KRB5_GET_KDC_CRED) /* Heimdal */ { krb5_kdc_flags flags; krb5_creds creds_in; krb5_realm *client_realm; krb5_creds *creds; memset(&creds_in, 0, sizeof(creds_in)); if (client_string) { ret = smb_krb5_parse_name(context, client_string, &creds_in.client); if (ret) { goto done; } } else { ret = krb5_cc_get_principal(context, ccache, &creds_in.client); if (ret) { goto done; } } if (service_string) { ret = smb_krb5_parse_name(context, service_string, &creds_in.server); if (ret) { goto done; } } else { /* build tgt service by default */ client_realm = krb5_princ_realm(context, creds_in.client); if (!client_realm) { ret = ENOMEM; goto done; } ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL); if (ret) { goto done; } } flags.i = 0; flags.b.renewable = flags.b.renew = True; ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds); if (ret) { DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret))); goto done; } /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */ ret = krb5_cc_initialize(context, ccache, creds_in.client); if (ret) { goto done; } ret = krb5_cc_store_cred(context, ccache, creds); if (expire_time) { *expire_time = (time_t) creds->times.endtime; } krb5_free_cred_contents(context, &creds_in); krb5_free_creds(context, creds); } #else #error No suitable krb5 ticket renew function available #endif done: if (client) { krb5_free_principal(context, client); } if (context) { krb5_free_context(context); } if (ccache) { krb5_cc_close(context, ccache); } return ret; }
static ADS_STATUS ads_krb5_chg_password(const char *kdc_host, const char *principal, const char *oldpw, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret; krb5_context context = NULL; krb5_principal princ; krb5_get_init_creds_opt opts; krb5_creds creds; char *chpw_princ = NULL, *password; const char *realm = NULL; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if ((ret = smb_krb5_parse_name(context, principal, &princ))) { krb5_free_context(context); DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret))); return ADS_ERROR_KRB5(ret); } krb5_get_init_creds_opt_init(&opts); krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); krb5_get_init_creds_opt_set_renew_life(&opts, 0); krb5_get_init_creds_opt_set_forwardable(&opts, 0); krb5_get_init_creds_opt_set_proxiable(&opts, 0); realm = smb_krb5_principal_get_realm(context, princ); /* We have to obtain an INITIAL changepw ticket for changing password */ if (asprintf(&chpw_princ, "kadmin/changepw@%s", realm) == -1) { krb5_free_context(context); DEBUG(1,("ads_krb5_chg_password: asprintf fail\n")); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } password = SMB_STRDUP(oldpw); ret = krb5_get_init_creds_password(context, &creds, princ, password, kerb_prompter, NULL, 0, chpw_princ, &opts); SAFE_FREE(chpw_princ); SAFE_FREE(password); if (ret) { if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) DEBUG(1,("Password incorrect while getting initial ticket")); else DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret))); krb5_free_principal(context, princ); krb5_free_context(context); return ADS_ERROR_KRB5(ret); } aret = do_krb5_kpasswd_request(context, kdc_host, KRB5_KPASSWD_VERS_CHANGEPW, &creds, principal, newpw); krb5_free_principal(context, princ); krb5_free_context(context); return aret; }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; const char *realm = NULL; unsigned int realm_len = 0; krb5_creds creds, *credsp = NULL; krb5_ccache ccache = NULL; ZERO_STRUCT(creds); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_cc_get_principal(context, ccache, &creds.client); if (ret) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to get principal from ccache (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } realm = smb_krb5_principal_get_realm(context, creds.client); realm_len = strlen(realm); ret = krb5_build_principal(context, &creds.server, realm_len, realm, "kadmin", "changepw", NULL); ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("krb5_build_prinipal_ext (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* we might have to call krb5_free_creds(...) from now on ... */ aret = do_krb5_kpasswd_request(context, kdc_host, KRB5_KPASSWD_VERS_SETPW, credsp, princ, newpw); krb5_free_creds(context, credsp); krb5_free_principal(context, creds.client); krb5_free_principal(context, creds.server); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, const char *realm, time_t time_offset, const DATA_BLOB *ticket, char **principal, struct PAC_DATA **pac_data, DATA_BLOB *ap_rep, DATA_BLOB *session_key, bool use_replay_cache) { NTSTATUS sret = NT_STATUS_LOGON_FAILURE; NTSTATUS pac_ret; DATA_BLOB auth_data; krb5_context context = NULL; krb5_auth_context auth_context = NULL; krb5_data packet; krb5_ticket *tkt = NULL; krb5_rcache rcache = NULL; krb5_keyblock *keyblock = NULL; time_t authtime; krb5_error_code ret = 0; int flags = 0; krb5_principal host_princ = NULL; krb5_const_principal client_principal = NULL; char *host_princ_s = NULL; bool auth_ok = False; bool got_auth_data = False; struct named_mutex *mutex = NULL; ZERO_STRUCT(packet); ZERO_STRUCT(auth_data); *principal = NULL; *pac_data = NULL; *ap_rep = data_blob_null; *session_key = data_blob_null; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret))); return NT_STATUS_LOGON_FAILURE; } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_set_default_realm(context, realm); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret))); goto out; } /* This whole process is far more complex than I would like. We have to go through all this to allow us to store the secret internally, instead of using /etc/krb5.keytab */ ret = krb5_auth_con_init(context, &auth_context); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret))); goto out; } krb5_auth_con_getflags( context, auth_context, &flags ); if ( !use_replay_cache ) { /* Disable default use of a replay cache */ flags &= ~KRB5_AUTH_CONTEXT_DO_TIME; krb5_auth_con_setflags( context, auth_context, flags ); } if (asprintf(&host_princ_s, "%s$", global_myname()) == -1) { goto out; } strlower_m(host_princ_s); ret = smb_krb5_parse_name(context, host_princ_s, &host_princ); if (ret) { DEBUG(1,("ads_verify_ticket: smb_krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); goto out; } if ( use_replay_cache ) { /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5 code surrounding the replay cache... */ mutex = grab_named_mutex(talloc_tos(), "replay cache mutex", 10); if (mutex == NULL) { DEBUG(1,("ads_verify_ticket: unable to protect " "replay cache with mutex.\n")); ret = KRB5_CC_IO; goto out; } /* JRA. We must set the rcache here. This will prevent replay attacks. */ ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache " "failed (%s)\n", error_message(ret))); goto out; } ret = krb5_auth_con_setrcache(context, auth_context, rcache); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache " "failed (%s)\n", error_message(ret))); goto out; } } /* Try secrets.tdb first and fallback to the krb5.keytab if necessary */ auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ, ticket, &tkt, &keyblock, &ret); if (!auth_ok && (ret == KRB5KRB_AP_ERR_TKT_NYV || ret == KRB5KRB_AP_ERR_TKT_EXPIRED || ret == KRB5KRB_AP_ERR_SKEW)) { goto auth_failed; } if (!auth_ok && lp_use_kerberos_keytab()) { auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &tkt, &keyblock, &ret); } if ( use_replay_cache ) { TALLOC_FREE(mutex); #if 0 /* Heimdal leaks here, if we fix the leak, MIT crashes */ if (rcache) { krb5_rc_close(context, rcache); } #endif } auth_failed: if (!auth_ok) { DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", error_message(ret))); /* Try map the error return in case it's something like * a clock skew error. */ sret = krb5_to_nt_status(ret); if (NT_STATUS_IS_OK(sret) || NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) { sret = NT_STATUS_LOGON_FAILURE; } DEBUG(10,("ads_verify_ticket: returning error %s\n", nt_errstr(sret) )); goto out; } authtime = get_authtime_from_tkt(tkt); client_principal = get_principal_from_tkt(tkt); ret = krb5_mk_rep(context, auth_context, &packet); if (ret) { DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n", error_message(ret))); goto out; } *ap_rep = data_blob(packet.data, packet.length); if (packet.data) { kerberos_free_data_contents(context, &packet); ZERO_STRUCT(packet); } get_krb5_smb_session_key(context, auth_context, session_key, True); dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length); #if 0 file_save("/tmp/ticket.dat", ticket->data, ticket->length); #endif /* continue when no PAC is retrieved or we couldn't decode the PAC (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set, or Kerberos tickets encrypted using a DES key) - Guenther */ got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt); if (!got_auth_data) { DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n")); } if (got_auth_data) { pac_ret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data); if (!NT_STATUS_IS_OK(pac_ret)) { DEBUG(3,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(pac_ret))); *pac_data = NULL; } data_blob_free(&auth_data); } #if 0 #if defined(HAVE_KRB5_TKT_ENC_PART2) /* MIT */ if (tkt->enc_part2) { file_save("/tmp/authdata.dat", tkt->enc_part2->authorization_data[0]->contents, tkt->enc_part2->authorization_data[0]->length); } #else /* Heimdal */ if (tkt->ticket.authorization_data) { file_save("/tmp/authdata.dat", tkt->ticket.authorization_data->val->ad_data.data, tkt->ticket.authorization_data->val->ad_data.length); } #endif #endif if ((ret = smb_krb5_unparse_name(context, client_principal, principal))) { DEBUG(3,("ads_verify_ticket: smb_krb5_unparse_name failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } sret = NT_STATUS_OK; out: TALLOC_FREE(mutex); if (!NT_STATUS_IS_OK(sret)) { data_blob_free(&auth_data); } if (!NT_STATUS_IS_OK(sret)) { data_blob_free(ap_rep); } if (host_princ) { krb5_free_principal(context, host_princ); } if (keyblock) { krb5_free_keyblock(context, keyblock); } if (tkt != NULL) { krb5_free_ticket(context, tkt); } SAFE_FREE(host_princ_s); if (auth_context) { krb5_auth_con_free(context, auth_context); } if (context) { krb5_free_context(context); } return sret; }
krb5_error_code smb_krb5_init_context(void *parent_ctx, struct loadparm_context *lp_ctx, struct smb_krb5_context **smb_krb5_context) { krb5_error_code ret; TALLOC_CTX *tmp_ctx; krb5_context kctx; #ifdef SAMBA4_USES_HEIMDAL krb5_log_facility *logf; #endif initialize_krb5_error_table(); tmp_ctx = talloc_new(parent_ctx); *smb_krb5_context = talloc_zero(tmp_ctx, struct smb_krb5_context); if (!*smb_krb5_context || !tmp_ctx) { talloc_free(tmp_ctx); return ENOMEM; } ret = smb_krb5_init_context_basic(tmp_ctx, lp_ctx, &kctx); if (ret) { DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n", error_message(ret))); talloc_free(tmp_ctx); return ret; } (*smb_krb5_context)->krb5_context = kctx; talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy); #ifdef SAMBA4_USES_HEIMDAL /* TODO: Should we have a different name here? */ ret = krb5_initlog(kctx, "Samba", &logf); if (ret) { DEBUG(1,("krb5_initlog failed (%s)\n", smb_get_krb5_error_message(kctx, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } (*smb_krb5_context)->pvt_log_data = logf; ret = krb5_addlog_func(kctx, logf, 0 /* min */, -1 /* max */, smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); if (ret) { DEBUG(1,("krb5_addlog_func failed (%s)\n", smb_get_krb5_error_message(kctx, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } krb5_set_warn_dest(kctx, logf); /* Set options in kerberos */ krb5_set_dns_canonicalize_hostname(kctx, lpcfg_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false)); #endif talloc_steal(parent_ctx, *smb_krb5_context); talloc_free(tmp_ctx); return 0; }
static ADS_STATUS ads_krb5_chg_password(const char *kdc_host, const char *principal, const char *oldpw, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret; krb5_context context = NULL; krb5_principal princ; krb5_get_init_creds_opt opts; krb5_creds creds; char *chpw_princ = NULL, *password; char *realm = NULL; int result_code; krb5_data result_code_string = { 0 }; krb5_data result_string = { 0 }; smb_krb5_addresses *addr = NULL; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if ((ret = smb_krb5_parse_name(context, principal, &princ))) { krb5_free_context(context); DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret))); return ADS_ERROR_KRB5(ret); } krb5_get_init_creds_opt_init(&opts); krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); krb5_get_init_creds_opt_set_renew_life(&opts, 0); krb5_get_init_creds_opt_set_forwardable(&opts, 0); krb5_get_init_creds_opt_set_proxiable(&opts, 0); /* note that heimdal will fill in the local addresses if the addresses * in the creds_init_opt are all empty and then later fail with invalid * address, sending our local netbios krb5 address - just like windows * - avoids this - gd */ ret = smb_krb5_gen_netbios_krb5_address(&addr, lp_netbios_name()); if (ret) { krb5_free_principal(context, princ); krb5_free_context(context); return ADS_ERROR_KRB5(ret); } krb5_get_init_creds_opt_set_address_list(&opts, addr->addrs); realm = smb_krb5_principal_get_realm(context, princ); /* We have to obtain an INITIAL changepw ticket for changing password */ if (asprintf(&chpw_princ, "kadmin/changepw@%s", realm) == -1) { krb5_free_context(context); free(realm); DEBUG(1,("ads_krb5_chg_password: asprintf fail\n")); return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } free(realm); password = SMB_STRDUP(oldpw); ret = krb5_get_init_creds_password(context, &creds, princ, password, kerb_prompter, NULL, 0, chpw_princ, &opts); SAFE_FREE(chpw_princ); SAFE_FREE(password); if (ret) { if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) DEBUG(1,("Password incorrect while getting initial ticket")); else DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret))); krb5_free_principal(context, princ); krb5_free_context(context); return ADS_ERROR_KRB5(ret); } ret = krb5_change_password(context, &creds, discard_const_p(char, newpw), &result_code, &result_code_string, &result_string); if (ret) { DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } if (result_code != KRB5_KPASSWD_SUCCESS) { ret = kpasswd_err_to_krb5_err(result_code); DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } aret = ADS_SUCCESS; done: kerberos_free_data_contents(context, &result_code_string); kerberos_free_data_contents(context, &result_string); krb5_free_principal(context, princ); krb5_free_context(context); return aret; }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; krb5_principal principal = NULL; char *princ_name = NULL; char *realm = NULL; krb5_creds creds, *credsp = NULL; #if KRB5_PRINC_REALM_RETURNS_REALM krb5_realm orig_realm; #else krb5_data orig_realm; #endif krb5_ccache ccache = NULL; ZERO_STRUCT(creds); initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } realm = strchr_m(princ, '@'); if (!realm) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to get realm\n")); return ADS_ERROR_KRB5(-1); } realm++; asprintf(&princ_name, "kadmin/changepw@%s", realm); ret = smb_krb5_parse_name(context, princ_name, &creds.server); if (ret) { krb5_cc_close(context, ccache); krb5_free_context(context); DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* parse the principal we got as a function argument */ ret = smb_krb5_parse_name(context, princ, &principal); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.server); krb5_free_context(context); DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret))); free(princ_name); return ADS_ERROR_KRB5(ret); } free(princ_name); /* The creds.server principal takes ownership of this memory. Remember to set back to original value before freeing. */ orig_realm = *krb5_princ_realm(context, creds.server); krb5_princ_set_realm(context, creds.server, krb5_princ_realm(context, principal)); ret = krb5_cc_get_principal(context, ccache, &creds.client); if (ret) { krb5_cc_close(context, ccache); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_free_context(context); DEBUG(1,("Failed to get principal from ccache (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); if (ret) { krb5_cc_close(context, ccache); krb5_free_principal(context, creds.client); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_free_context(context); DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } /* we might have to call krb5_free_creds(...) from now on ... */ aret = do_krb5_kpasswd_request(context, kdc_host, KRB5_KPASSWD_VERS_SETPW, credsp, princ, newpw); krb5_free_creds(context, credsp); krb5_free_principal(context, creds.client); krb5_princ_set_realm(context, creds.server, &orig_realm); krb5_free_principal(context, creds.server); krb5_free_principal(context, principal); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
/* this performs a SASL/gssapi bind we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl is very dependent on correctly configured DNS whereas this routine is much less fragile see RFC2078 and RFC2222 for details */ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) { uint32 minor_status; gss_name_t serv_name; gss_buffer_desc input_name; gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; gss_OID mech_type = GSS_C_NULL_OID; gss_buffer_desc output_token, input_token; uint32 ret_flags, conf_state; struct berval cred; struct berval *scred = NULL; int i=0; int gss_rc, rc; uint8 *p; uint32 max_msg_size = 0; char *sname = NULL; ADS_STATUS status; krb5_principal principal = NULL; krb5_context ctx = NULL; krb5_enctype enc_types[] = { #ifdef ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC, #endif ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL}; gss_OID_desc nt_principal = {10, CONST_DISCARD(char *, "\052\206\110\206\367\022\001\002\002\002")}; /* we need to fetch a service ticket as the ldap user in the servers realm, regardless of our realm */ asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm); initialize_krb5_error_table(); status = ADS_ERROR_KRB5(krb5_init_context(&ctx)); if (!ADS_ERR_OK(status)) { SAFE_FREE(sname); return status; } status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types)); if (!ADS_ERR_OK(status)) { SAFE_FREE(sname); krb5_free_context(ctx); return status; } status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal)); if (!ADS_ERR_OK(status)) { SAFE_FREE(sname); krb5_free_context(ctx); return status; } input_name.value = &principal; input_name.length = sizeof(principal); gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name); /* * The MIT libraries have a *HORRIBLE* bug - input_value.value needs * to point to the *address* of the krb5_principal, and the gss libraries * to a shallow copy of the krb5_principal pointer - so we need to keep * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* ! * Just one more way in which MIT engineers screwed me over.... JRA. */ SAFE_FREE(sname); if (gss_rc) { krb5_free_principal(ctx, principal); krb5_free_context(ctx); return ADS_ERROR_GSS(gss_rc, minor_status); } input_token.value = NULL; input_token.length = 0; for (i=0; i < MAX_GSS_PASSES; i++) { gss_rc = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &context_handle, serv_name, mech_type, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, 0, NULL, &input_token, NULL, &output_token, &ret_flags, NULL); if (input_token.value) { gss_release_buffer(&minor_status, &input_token); } if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } cred.bv_val = (char *)output_token.value; cred.bv_len = output_token.length; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, &scred); if (rc != LDAP_SASL_BIND_IN_PROGRESS) { status = ADS_ERROR(rc); goto failed; } if (output_token.value) { gss_release_buffer(&minor_status, &output_token); } if (scred) { input_token.value = scred->bv_val; input_token.length = scred->bv_len; } else { input_token.value = NULL; input_token.length = 0; } if (gss_rc == 0) break; } gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token, (int *)&conf_state,NULL); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } gss_release_buffer(&minor_status, &input_token); p = (uint8 *)output_token.value; #if 0 file_save("sasl_gssapi.dat", output_token.value, output_token.length); #endif if (p) { max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3]; } gss_release_buffer(&minor_status, &output_token); output_token.value = SMB_MALLOC(strlen(ads->config.bind_path) + 8); p = (uint8 *)output_token.value; *p++ = 1; /* no sign & seal selection */ /* choose the same size as the server gave us */ *p++ = max_msg_size>>16; *p++ = max_msg_size>>8; *p++ = max_msg_size; snprintf((char *)p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path); p += strlen((const char *)p); output_token.length = PTR_DIFF(p, output_token.value); gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT, &output_token, (int *)&conf_state, &input_token); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; } free(output_token.value); cred.bv_val = (char *)input_token.value; cred.bv_len = input_token.length; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, &scred); status = ADS_ERROR(rc); gss_release_buffer(&minor_status, &input_token); failed: gss_release_name(&minor_status, &serv_name); if (context_handle != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); krb5_free_principal(ctx, principal); krb5_free_context(ctx); if(scred) ber_bvfree(scred); return status; }
krb5_error_code smb_krb5_init_context(void *parent_ctx, struct tevent_context *ev, struct loadparm_context *lp_ctx, struct smb_krb5_context **smb_krb5_context) { krb5_error_code ret; TALLOC_CTX *tmp_ctx; initialize_krb5_error_table(); tmp_ctx = talloc_new(parent_ctx); *smb_krb5_context = talloc(tmp_ctx, struct smb_krb5_context); if (!*smb_krb5_context || !tmp_ctx) { talloc_free(tmp_ctx); return ENOMEM; } ret = smb_krb5_init_context_basic(tmp_ctx, ev, lp_ctx, &(*smb_krb5_context)->krb5_context); if (ret) { DEBUG(1,("smb_krb5_context_init_basic failed (%s)\n", error_message(ret))); talloc_free(tmp_ctx); return ret; } /* TODO: Should we have a different name here? */ ret = krb5_initlog((*smb_krb5_context)->krb5_context, "Samba", &(*smb_krb5_context)->logf); if (ret) { DEBUG(1,("krb5_initlog failed (%s)\n", smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); krb5_free_context((*smb_krb5_context)->krb5_context); talloc_free(tmp_ctx); return ret; } talloc_set_destructor(*smb_krb5_context, smb_krb5_context_destroy); ret = krb5_addlog_func((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf, 0 /* min */, -1 /* max */, smb_krb5_debug_wrapper, smb_krb5_debug_close, NULL); if (ret) { DEBUG(1,("krb5_addlog_func failed (%s)\n", smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } krb5_set_warn_dest((*smb_krb5_context)->krb5_context, (*smb_krb5_context)->logf); /* Set use of our socket lib */ ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, smb_krb5_send_and_recv_func, ev); if (ret) { DEBUG(1,("krb5_set_send_recv_func failed (%s)\n", smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); talloc_free(tmp_ctx); return ret; } talloc_steal(parent_ctx, *smb_krb5_context); talloc_free(tmp_ctx); /* Set options in kerberos */ krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context, lp_parm_bool(lp_ctx, NULL, "krb5", "set_dns_canonicalize", false)); return 0; }
/* get a kerberos5 ticket for the given service */ int cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname, time_t *tgs_expire) { krb5_error_code retval; krb5_data packet; krb5_context context = NULL; krb5_ccache ccdef = NULL; krb5_auth_context auth_context = NULL; krb5_enctype enc_types[] = { #ifdef ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC, #endif ENCTYPE_DES_CBC_MD5, ENCTYPE_DES_CBC_CRC, ENCTYPE_NULL}; initialize_krb5_error_table(); retval = krb5_init_context(&context); if (retval) { DEBUG(1,("cli_krb5_get_ticket: krb5_init_context failed (%s)\n", error_message(retval))); goto failed; } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } if ((retval = krb5_cc_resolve(context, ccname ? ccname : krb5_cc_default_name(context), &ccdef))) { DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n", error_message(retval))); goto failed; } if ((retval = krb5_set_default_tgs_ktypes(context, enc_types))) { DEBUG(1,("cli_krb5_get_ticket: krb5_set_default_tgs_ktypes failed (%s)\n", error_message(retval))); goto failed; } if ((retval = ads_krb5_mk_req(context, &auth_context, AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts, principal, ccdef, &packet, tgs_expire))) { goto failed; } get_krb5_smb_session_key(context, auth_context, session_key_krb5, False); *ticket = data_blob(packet.data, packet.length); kerberos_free_data_contents(context, &packet); failed: if ( context ) { if (ccdef) krb5_cc_close(context, ccdef); if (auth_context) krb5_auth_con_free(context, auth_context); krb5_free_context(context); } return retval; }
int main (int argc, char **argv) { TALLOC_CTX *mem_ctx = talloc_init("ktutil"); krb5_context context; krb5_keytab keytab; krb5_kt_cursor cursor; krb5_keytab_entry entry; krb5_error_code ret; char *keytab_name = NULL; if (mem_ctx == NULL) { printf("talloc_init() failed\n"); exit(1); } if (argc != 2) { printf("Usage: %s KEYTAB\n", argv[0]); exit(1); } keytab_name = argv[1]; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_context"); } ret = smb_krb5_open_keytab_relative(context, keytab_name, false, &keytab); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "open keytab"); } ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_start_seq_get"); } for (ret = krb5_kt_next_entry(context, keytab, &entry, &cursor); ret == 0; ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) { char *principal = NULL; char *enctype_str = NULL; krb5_enctype enctype = smb_get_enctype_from_kt_entry(&entry); ret = smb_krb5_unparse_name(mem_ctx, context, entry.principal, &principal); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_enctype_to_string"); } ret = smb_krb5_enctype_to_string(context, enctype, &enctype_str); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_enctype_to_string"); } printf("%s (%s)\n", principal, enctype_str); TALLOC_FREE(principal); SAFE_FREE(enctype_str); smb_krb5_kt_free_entry(context, &entry); } ret = krb5_kt_end_seq_get(context, keytab, &cursor); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_end_seq_get"); } ret = krb5_kt_close(context, keytab); if (ret) { smb_krb5_err(mem_ctx, context, 1, ret, "krb5_kt_close"); } krb5_free_context(context); talloc_free(mem_ctx); return 0; }
ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *principal, const char *newpw, int time_offset) { ADS_STATUS aret; krb5_error_code ret = 0; krb5_context context = NULL; krb5_principal princ = NULL; krb5_ccache ccache = NULL; int result_code; krb5_data result_code_string = { 0 }; krb5_data result_string = { 0 }; initialize_krb5_error_table(); ret = krb5_init_context(&context); if (ret) { DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } if (principal) { ret = smb_krb5_parse_name(context, principal, &princ); if (ret) { krb5_free_context(context); DEBUG(1, ("Failed to parse %s (%s)\n", principal, error_message(ret))); return ADS_ERROR_KRB5(ret); } } if (time_offset != 0) { krb5_set_real_time(context, time(NULL) + time_offset, 0); } ret = krb5_cc_default(context, &ccache); if (ret) { krb5_free_principal(context, princ); krb5_free_context(context); DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); return ADS_ERROR_KRB5(ret); } ret = krb5_set_password_using_ccache(context, ccache, discard_const_p(char, newpw), princ, &result_code, &result_code_string, &result_string); if (ret) { DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } if (result_code != KRB5_KPASSWD_SUCCESS) { ret = kpasswd_err_to_krb5_err(result_code); DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); aret = ADS_ERROR_KRB5(ret); goto done; } aret = ADS_SUCCESS; done: kerberos_free_data_contents(context, &result_code_string); kerberos_free_data_contents(context, &result_string); krb5_free_principal(context, princ); krb5_cc_close(context, ccache); krb5_free_context(context); return aret; }
/* startup the kdc task */ static void kdc_task_init(struct task_server *task) { struct kdc_server *kdc; krb5_kdc_configuration *kdc_config = NULL; NTSTATUS status; krb5_error_code ret; struct interface *ifaces; int ldb_ret; switch (lpcfg_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "kdc: no KDC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "kdc: no KDC required in member server configuration", false); return; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: task_server_terminate(task, "Cannot start KDC as a 'classic Samba' DC", true); return; case ROLE_ACTIVE_DIRECTORY_DC: /* Yes, we want a KDC */ break; } load_interface_list(task, task->lp_ctx, &ifaces); if (iface_list_count(ifaces) == 0) { task_server_terminate(task, "kdc: no network interfaces configured", false); return; } task_server_set_title(task, "task[kdc]"); kdc = talloc_zero(task, struct kdc_server); if (kdc == NULL) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->task = task; /* get a samdb connection */ kdc->samdb = samdb_connect(kdc, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(kdc->task->lp_ctx), NULL, 0); if (!kdc->samdb) { DEBUG(1,("kdc_task_init: unable to connect to samdb\n")); task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true); return; } ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc); if (ldb_ret != LDB_SUCCESS) { DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n", ldb_errstring(kdc->samdb))); task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true); return; } kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5); initialize_krb5_error_table(); ret = smb_krb5_init_context(kdc, task->lp_ctx, &kdc->smb_krb5_context); if (ret) { DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", error_message(ret))); task_server_terminate(task, "kdc: krb5_init_context failed", true); return; } krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r); ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, &kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to get KDC configuration", true); return; } kdc_config->logf = (krb5_log_facility *)kdc->smb_krb5_context->pvt_log_data; kdc_config->db = talloc(kdc, struct HDB *); if (!kdc_config->db) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc_config->num_db = 1; /* * This restores the behavior before * commit 255e3e18e00f717d99f3bc57c8a8895ff624f3c3 * s4:heimdal: import lorikeet-heimdal-201107150856 * (commit 48936803fae4a2fb362c79365d31f420c917b85b) * * as_use_strongest_session_key,preauth_use_strongest_session_key * and tgs_use_strongest_session_key are input to the * _kdc_find_etype() function. The old bahavior is in * the use_strongest_session_key=FALSE code path. * (The only remaining difference in _kdc_find_etype() * is the is_preauth parameter.) * * The old behavior in the _kdc_get_preferred_key() * function is use_strongest_server_key=TRUE. */ kdc_config->as_use_strongest_session_key = false; kdc_config->preauth_use_strongest_session_key = false; kdc_config->tgs_use_strongest_session_key = false; kdc_config->use_strongest_server_key = true; kdc_config->autodetect_referrals = false; /* Register hdb-samba4 hooks for use as a keytab */ kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context); if (!kdc->base_ctx) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->base_ctx->ev_ctx = task->event_ctx; kdc->base_ctx->lp_ctx = task->lp_ctx; kdc->base_ctx->msg_ctx = task->msg_ctx; status = hdb_samba4_create_kdc(kdc->base_ctx, kdc->smb_krb5_context->krb5_context, &kdc_config->db[0]); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true); return; } ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "hdb", &hdb_samba4_interface); if(ret) { task_server_terminate(task, "kdc: failed to register hdb plugin", true); return; } ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { task_server_terminate(task, "kdc: failed to register keytab plugin", true); return; } kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); if (kdc->keytab_name == NULL) { task_server_terminate(task, "kdc: Failed to set keytab name", true); return; } /* Register WinDC hooks */ ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "windc", &windc_plugin_table); if(ret) { task_server_terminate(task, "kdc: failed to register windc plugin", true); return; } ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context); if(ret) { task_server_terminate(task, "kdc: failed to init windc plugin", true); return; } ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true); return; } kdc->private_data = kdc_config; /* start listening on the configured network interfaces */ status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces, task->model_ops); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup interfaces", true); return; } status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, kdc_check_generic_kerberos, kdc); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup monitoring", true); return; } irpc_add_name(task->msg_ctx, "kdc_server"); }
krb5_error_code smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx, struct loadparm_context *lp_ctx, krb5_context *_krb5_context) { krb5_error_code ret; #ifdef SAMBA4_USES_HEIMDAL char **config_files; const char *config_file, *realm; #endif krb5_context krb5_ctx; initialize_krb5_error_table(); ret = krb5_init_context(&krb5_ctx); if (ret) { DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); return ret; } /* The MIT Kerberos build relies on using the system krb5.conf file. * If you really want to use another file please set KRB5_CONFIG * accordingly. */ #ifdef SAMBA4_USES_HEIMDAL config_file = lpcfg_config_path(tmp_ctx, lp_ctx, "krb5.conf"); if (!config_file) { krb5_free_context(krb5_ctx); return ENOMEM; } /* Use our local krb5.conf file by default */ ret = krb5_prepend_config_files_default(config_file, &config_files); if (ret) { DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } ret = krb5_set_config_files(krb5_ctx, config_files); krb5_free_config_files(config_files); if (ret) { DEBUG(1,("krb5_set_config_files failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } realm = lpcfg_realm(lp_ctx); if (realm != NULL) { ret = krb5_set_default_realm(krb5_ctx, realm); if (ret) { DEBUG(1,("krb5_set_default_realm failed (%s)\n", smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx))); krb5_free_context(krb5_ctx); return ret; } } #endif *_krb5_context = krb5_ctx; return 0; }