static krb5_error_code get_cred_kdc_capath(krb5_context context, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, krb5_principal impersonate_principal, Ticket *second_ticket, krb5_creds **out_creds, krb5_creds ***ret_tgts) { krb5_error_code ret; krb5_const_realm client_realm, server_realm, try_realm; client_realm = krb5_principal_get_realm(context, in_creds->client); server_realm = krb5_principal_get_realm(context, in_creds->server); try_realm = client_realm; ret = get_cred_kdc_capath_worker(context, flags, ccache, in_creds, try_realm, impersonate_principal, second_ticket, out_creds, ret_tgts); if (ret == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { try_realm = krb5_config_get_string(context, NULL, "capaths", client_realm, server_realm, NULL); if (try_realm != NULL && strcmp(try_realm, client_realm)) { ret = get_cred_kdc_capath_worker(context, flags, ccache, in_creds, try_realm, impersonate_principal, second_ticket, out_creds, ret_tgts); } } return ret; }
static int seed_something(void) { #ifndef NO_RANDFILE char buf[1024], seedfile[256]; /* If there is a seed file, load it. But such a file cannot be trusted, so use 0 for the entropy estimate */ if (RAND_file_name(seedfile, sizeof(seedfile))) { int fd; fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); if (fd >= 0) { ssize_t ret; rk_cloexec(fd); ret = read(fd, buf, sizeof(buf)); if (ret > 0) RAND_add(buf, ret, 0.0); close(fd); } else seedfile[0] = '\0'; } else seedfile[0] = '\0'; #endif /* Calling RAND_status() will try to use /dev/urandom if it exists so we do not have to deal with it. */ if (RAND_status() != 1) { #if defined(HAVE_RAND_EGD) krb5_context context; const char *p; #ifndef OPENSSL_NO_EGD /* Try using egd */ if (!krb5_init_context(&context)) { p = krb5_config_get_string(context, NULL, "libdefaults", "egd_socket", NULL); if (p != NULL) RAND_egd_bytes(p, ENTROPY_NEEDED); krb5_free_context(context); } #endif #else /* TODO: Once a Windows CryptoAPI RAND method is defined, we can use that and failover to another method. */ #endif } if (RAND_status() == 1) { #ifndef NO_RANDFILE /* Update the seed file */ if (seedfile[0]) RAND_write_file(seedfile); #endif return 0; } else return -1; }
static const char * find_rpath(krb5_context context, Realm crealm, Realm srealm) { const char *new_realm = krb5_config_get_string(context, NULL, "capaths", crealm, srealm, NULL); return new_realm; }
const char * hdb_db_dir(krb5_context context) { const char *p; p = krb5_config_get_string(context, NULL, "hdb", "db-dir", NULL); if (p) return p; return HDB_DB_DIR; }
static int get_dbinfo(krb5_context context, const krb5_config_binding *db_binding, const char *label, struct hdb_dbinfo **db) { struct hdb_dbinfo *di; const char *p; *db = NULL; p = krb5_config_get_string(context, db_binding, "dbname", NULL); if(p == NULL) return 0; di = calloc(1, sizeof(*di)); if (di == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } di->label = strdup(label); di->dbname = strdup(p); p = krb5_config_get_string(context, db_binding, "realm", NULL); if(p) di->realm = strdup(p); p = krb5_config_get_string(context, db_binding, "mkey_file", NULL); if(p) di->mkey_file = strdup(p); p = krb5_config_get_string(context, db_binding, "acl_file", NULL); if(p) di->acl_file = strdup(p); p = krb5_config_get_string(context, db_binding, "log_file", NULL); if(p) di->log_file = strdup(p); di->binding = db_binding; *db = di; return 0; }
static const char* get_name_conversion(krb5_context context, const char *realm, const char *name) { struct v4_name_convert *q; const char *p; p = krb5_config_get_string(context, NULL, "realms", realm, "v4_name_convert", "host", name, NULL); if(p == NULL) p = krb5_config_get_string(context, NULL, "libdefaults", "v4_name_convert", "host", name, NULL); if(p) return p; /* XXX should be possible to override default list */ p = krb5_config_get_string(context, NULL, "realms", realm, "v4_name_convert", "plain", name, NULL); if(p) return NULL; p = krb5_config_get_string(context, NULL, "libdefaults", "v4_name_convert", "plain", name, NULL); if(p) return NULL; for(q = default_v4_name_convert; q->from; q++) if(strcmp(q->from, name) == 0) return q->to; return NULL; }
static void init_stats_names(krb5_context context) { const char *fn = NULL; char *buf = NULL; if (slave_stats_file) fn = slave_stats_file; else if ((fn = krb5_config_get_string(context, NULL, "kdc", "iprop-stats", NULL)) == NULL) { if (asprintf(&buf, "%s/slaves-stats", hdb_db_dir(context)) != -1 && buf != NULL) fn = buf; buf = NULL; } if (fn != NULL) { slave_stats_file = fn; if (asprintf(&buf, "%s.tmp", fn) != -1 && buf != NULL) slave_stats_temp_file = buf; } }
static krb5_error_code get_cred_from_kdc_flags(krb5_context context, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds, krb5_creds ***ret_tgts) { krb5_error_code ret; krb5_creds *tgt, tmp_creds; krb5_const_realm client_realm, server_realm, try_realm; *out_creds = NULL; client_realm = krb5_principal_get_realm(context, in_creds->client); server_realm = krb5_principal_get_realm(context, in_creds->server); memset(&tmp_creds, 0, sizeof(tmp_creds)); ret = krb5_copy_principal(context, in_creds->client, &tmp_creds.client); if(ret) return ret; try_realm = krb5_config_get_string(context, NULL, "capaths", client_realm, server_realm, NULL); #if 1 /* XXX remove in future release */ if(try_realm == NULL) try_realm = krb5_config_get_string(context, NULL, "libdefaults", "capath", server_realm, NULL); #endif if (try_realm == NULL) try_realm = client_realm; ret = krb5_make_principal(context, &tmp_creds.server, try_realm, KRB5_TGS_NAME, server_realm, NULL); if(ret){ krb5_free_principal(context, tmp_creds.client); return ret; } { krb5_creds tgts; /* XXX try krb5_cc_retrieve_cred first? */ ret = find_cred(context, ccache, tmp_creds.server, *ret_tgts, &tgts); if(ret == 0){ *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; } else { krb5_boolean noaddr; krb5_appdefault_boolean(context, NULL, tgts.server->realm, "no-addresses", FALSE, &noaddr); if (noaddr) ret = get_cred_kdc(context, ccache, flags, NULL, in_creds, &tgts, *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, in_creds, &tgts, *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; } } krb5_free_cred_contents(context, &tgts); krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } } if(krb5_realm_compare(context, in_creds->client, in_creds->server)) { krb5_clear_error_string (context); return KRB5_CC_NOTFOUND; } /* XXX this can loop forever */ while(1){ heim_general_string tgt_inst; ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, &tgt, ret_tgts); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } ret = add_cred(context, ret_tgts, tgt); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } tgt_inst = tgt->server->name.name_string.val[1]; if(strcmp(tgt_inst, server_realm) == 0) break; krb5_free_principal(context, tmp_creds.server); ret = krb5_make_principal(context, &tmp_creds.server, tgt_inst, KRB5_TGS_NAME, server_realm, NULL); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } ret = krb5_free_creds(context, tgt); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } } krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; } else { krb5_boolean noaddr; krb5_appdefault_boolean(context, NULL, tgt->server->realm, "no-addresses", FALSE, &noaddr); if (noaddr) ret = get_cred_kdc (context, ccache, flags, NULL, in_creds, tgt, *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, in_creds, tgt, *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; } } krb5_free_creds(context, tgt); return ret; }
KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL _krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser, krb5_boolean an2ln_ok) { static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT; krb5_error_code ret; struct plctx ctx; char **rules; /* * XXX we should have a struct with a krb5_context field and a * krb5_error_code fied and pass the address of that as the ctx * argument of heim_base_once_f(). For now we use a static to * communicate failures. Actually, we ignore failures anyways, * since we can't return them. */ heim_base_once_f(®_def_plugins, context, reg_def_plugins_once); ctx.flags = 0; ctx.luser = luser; ctx.principal = principal; ctx.result = FALSE; ctx.k5login_dir = krb5_config_get_string(context, NULL, "libdefaults", "k5login_directory", NULL); if (an2ln_ok) ctx.flags |= KUSEROK_ANAME_TO_LNAME_OK; if (krb5_config_get_bool_default(context, NULL, FALSE, "libdefaults", "k5login_authoritative", NULL)) ctx.flags |= KUSEROK_K5LOGIN_IS_AUTHORITATIVE; if ((ctx.flags & KUSEROK_K5LOGIN_IS_AUTHORITATIVE) && plugin_reg_ret) return plugin_reg_ret; /* fail safe */ rules = krb5_config_get_strings(context, NULL, "libdefaults", "kuserok", NULL); if (rules == NULL) { /* Default: check ~/.k5login */ ctx.rule = "USER-K5LOGIN"; ret = plcallback(context, &kuserok_user_k5login_plug, NULL, &ctx); if (ret == 0) goto out; ctx.rule = "SIMPLE"; ret = plcallback(context, &kuserok_simple_plug, NULL, &ctx); if (ret == 0) goto out; ctx.result = FALSE; } else { size_t n; for (n = 0; rules[n]; n++) { ctx.rule = rules[n]; ret = _krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_KUSEROK, KRB5_PLUGIN_KUSEROK_VERSION_0, 0, &ctx, plcallback); if (ret != KRB5_PLUGIN_NO_HANDLE) goto out; } } out: krb5_config_free_strings(rules); return ctx.result; }
krb5_kdc_configuration * configure(krb5_context context, int argc, char **argv, int *optidx) { krb5_kdc_configuration *config; krb5_error_code ret; const char *p; *optidx = 0; while(getarg(args, num_args, argc, argv, optidx)) warnx("error at argument `%s'", argv[*optidx]); if(help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } if (builtin_hdb_flag) { char *list; ret = hdb_list_builtin(context, &list); if (ret) krb5_err(context, 1, ret, "listing builtin hdb backends"); printf("builtin hdb backends: %s\n", list); free(list); exit(0); } { char **files; int aret; if (config_file == NULL) { aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (aret == -1 || config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if(ret) krb5_err(context, 1, ret, "reading configuration files"); } ret = krb5_kdc_get_config(context, &config); if (ret) krb5_err(context, 1, ret, "krb5_kdc_default_config"); kdc_openlog(context, "kdc", config); ret = krb5_kdc_set_dbinfo(context, config); if (ret) krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo"); if(max_request_str) max_request_tcp = max_request_udp = parse_bytes(max_request_str, NULL); if(max_request_tcp == 0){ p = krb5_config_get_string (context, NULL, "kdc", "max-request", NULL); if(p) max_request_tcp = max_request_udp = parse_bytes(p, NULL); } if(require_preauth != -1) config->require_preauth = require_preauth; if(port_str == NULL){ p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL); if (p != NULL) port_str = strdup(p); } explicit_addresses.len = 0; if (addresses_str.num_strings) { int i; for (i = 0; i < addresses_str.num_strings; ++i) add_one_address (context, addresses_str.strings[i], i == 0); free_getarg_strings (&addresses_str); } else { char **foo = krb5_config_get_strings (context, NULL, "kdc", "addresses", NULL); if (foo != NULL) { add_one_address (context, *foo++, TRUE); while (*foo) add_one_address (context, *foo++, FALSE); } } if(enable_http == -1) enable_http = krb5_config_get_bool(context, NULL, "kdc", "enable-http", NULL); if(request_log == NULL) request_log = krb5_config_get_string(context, NULL, "kdc", "kdc-request-log", NULL); if (krb5_config_get_string(context, NULL, "kdc", "enforce-transited-policy", NULL)) krb5_errx(context, 1, "enforce-transited-policy deprecated, " "use [kdc]transited-policy instead"); #ifdef SUPPORT_DETACH if(detach_from_console == -1) detach_from_console = krb5_config_get_bool_default(context, NULL, DETACH_IS_DEFAULT, "kdc", "detach", NULL); #endif /* SUPPORT_DETACH */ if(max_request_tcp == 0) max_request_tcp = 64 * 1024; if(max_request_udp == 0) max_request_udp = 64 * 1024; if (port_str == NULL) port_str = "+"; if(disable_des == -1) disable_des = krb5_config_get_bool_default(context, NULL, FALSE, "kdc", "disable-des", NULL); if(disable_des) { krb5_enctype_disable(context, ETYPE_DES_CBC_CRC); krb5_enctype_disable(context, ETYPE_DES_CBC_MD4); krb5_enctype_disable(context, ETYPE_DES_CBC_MD5); krb5_enctype_disable(context, ETYPE_DES_CBC_NONE); krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE); krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE); } krb5_kdc_windc_init(context); krb5_kdc_pkinit_config(context, config); return config; }
static krb5_error_code init_ccapi(krb5_context context) { const char *lib = NULL; HEIMDAL_MUTEX_lock(&acc_mutex); if (init_func) { HEIMDAL_MUTEX_unlock(&acc_mutex); if (context) krb5_clear_error_message(context); return 0; } if (context) lib = krb5_config_get_string(context, NULL, "libdefaults", "ccapi_library", NULL); if (lib == NULL) { #ifdef __APPLE__ lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos"; #elif defined(KRB5_USE_PATH_TOKENS) && defined(_WIN32) lib = "%{LIBDIR}/libkrb5_cc.dll"; #else lib = "/usr/lib/libkrb5_cc.so"; #endif } #ifdef HAVE_DLOPEN #ifndef RTLD_LAZY #define RTLD_LAZY 0 #endif #ifndef RTLD_LOCAL #define RTLD_LOCAL 0 #endif #ifdef KRB5_USE_PATH_TOKENS { char * explib = NULL; if (_krb5_expand_path_tokens(context, lib, &explib) == 0) { cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL); free(explib); } } #else cc_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL); #endif if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); if (context) krb5_set_error_message(context, KRB5_CC_NOSUPP, N_("Failed to load API cache module %s", "file"), lib); return KRB5_CC_NOSUPP; } init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); set_target_uid = (void (KRB5_CALLCONV *)(uid_t)) dlsym(cc_handle, "krb5_ipc_client_set_target_uid"); clear_target = (void (KRB5_CALLCONV *)(void)) dlsym(cc_handle, "krb5_ipc_client_clear_target"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { if (context) krb5_set_error_message(context, KRB5_CC_NOSUPP, N_("Failed to find cc_initialize" "in %s: %s", "file, error"), lib, dlerror()); dlclose(cc_handle); return KRB5_CC_NOSUPP; } return 0; #else HEIMDAL_MUTEX_unlock(&acc_mutex); if (context) krb5_set_error_message(context, KRB5_CC_NOSUPP, N_("no support for shared object", "")); return KRB5_CC_NOSUPP; #endif }
krb5_error_code krb5_kdc_pk_initialize(krb5_context context, krb5_kdc_configuration *config, const char *user_id, const char *anchors, char **pool, char **revoke_list) { const char *file; char *fn = NULL; krb5_error_code ret; file = krb5_config_get_string(context, NULL, "libdefaults", "moduli", NULL); ret = _krb5_parse_moduli(context, file, &moduli); if (ret) krb5_err(context, 1, ret, "PKINIT: failed to load modidi file"); principal_mappings.len = 0; principal_mappings.val = NULL; ret = _krb5_pk_load_id(context, &kdc_identity, user_id, anchors, pool, revoke_list, NULL, NULL, NULL); if (ret) { krb5_warn(context, ret, "PKINIT: "); config->enable_pkinit = 0; return ret; } { hx509_query *q; hx509_cert cert; ret = hx509_query_alloc(context->hx509ctx, &q); if (ret) { krb5_warnx(context, "PKINIT: out of memory"); return ENOMEM; } hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); if (config->pkinit_kdc_friendly_name) hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name); ret = hx509_certs_find(context->hx509ctx, kdc_identity->certs, q, &cert); hx509_query_free(context->hx509ctx, q); if (ret == 0) { if (hx509_cert_check_eku(context->hx509ctx, cert, &asn1_oid_id_pkkdcekuoid, 0)) { hx509_name name; char *str; ret = hx509_cert_get_subject(cert, &name); if (ret == 0) { hx509_name_to_string(name, &str); krb5_warnx(context, "WARNING Found KDC certificate (%s)" "is missing the PK-INIT KDC EKU, this is bad for " "interoperability.", str); hx509_name_free(&name); free(str); } } hx509_cert_free(cert); } else krb5_warnx(context, "PKINIT: failed to find a signing " "certifiate with a public key"); } if (krb5_config_get_bool_default(context, NULL, FALSE, "kdc", "pkinit_allow_proxy_certificate", NULL)) config->pkinit_allow_proxy_certs = 1; file = krb5_config_get_string(context, NULL, "kdc", "pkinit_mappings_file", NULL); if (file == NULL) { int aret; aret = asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context)); if (aret == -1) { krb5_warnx(context, "PKINIT: out of memory"); return ENOMEM; } file = fn; } load_mappings(context, file); if (fn) free(fn); return 0; }
void kcm_configure(int argc, char **argv) { krb5_error_code ret; int optind = 0; const char *p; while(getarg(args, num_args, argc, argv, &optind)) warnx("error at argument `%s'", argv[optind]); if(help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } argc -= optind; argv += optind; if (argc != 0) usage(1); { char **files; if(config_file == NULL) config_file = _PATH_KCM_CONF; ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(kcm_context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(kcm_context, files); krb5_free_config_files(files); if(ret) krb5_err(kcm_context, 1, ret, "reading configuration files"); } if(max_request_str) max_request = parse_bytes(max_request_str, NULL); if(max_request == 0){ p = krb5_config_get_string (kcm_context, NULL, "kcm", "max-request", NULL); if(p) max_request = parse_bytes(p, NULL); } if (system_principal == NULL) { system_principal = kcm_system_config_get_string("principal"); } if (system_principal != NULL) { ret = ccache_init_system(); if (ret) krb5_err(kcm_context, 1, ret, "initializing system ccache"); } #ifdef SUPPORT_DETACH if(detach_from_console == -1) detach_from_console = krb5_config_get_bool_default(kcm_context, NULL, DETACH_IS_DEFAULT, "kcm", "detach", NULL); #endif kcm_openlog(); if(max_request == 0) max_request = 64 * 1024; }
static const char * kcm_system_config_get_string(const char *string) { return krb5_config_get_string(kcm_context, NULL, "kcm", "system_ccache", string, NULL); }
void kadm5_setup_passwd_quality_check(krb5_context context, const char *check_library, const char *check_function) { #ifdef HAVE_DLOPEN void *handle; void *sym; int *version; const char *tmp; if(check_library == NULL) { tmp = krb5_config_get_string(context, NULL, "password_quality", "check_library", NULL); if(tmp != NULL) check_library = tmp; } if(check_function == NULL) { tmp = krb5_config_get_string(context, NULL, "password_quality", "check_function", NULL); if(tmp != NULL) check_function = tmp; } if(check_library != NULL && check_function == NULL) check_function = "passwd_check"; if(check_library == NULL) return; handle = dlopen(check_library, RTLD_NOW); if(handle == NULL) { krb5_warnx(context, "failed to open `%s'", check_library); return; } version = (int *) dlsym(handle, "version"); if(version == NULL) { krb5_warnx(context, "didn't find `version' symbol in `%s'", check_library); dlclose(handle); return; } if(*version != KADM5_PASSWD_VERSION_V0) { krb5_warnx(context, "version of loaded library is %d (expected %d)", *version, KADM5_PASSWD_VERSION_V0); dlclose(handle); return; } sym = dlsym(handle, check_function); if(sym == NULL) { krb5_warnx(context, "didn't find `%s' symbol in `%s'", check_function, check_library); dlclose(handle); return; } passwd_quality_check = (kadm5_passwd_quality_check_func_v0) sym; #endif /* HAVE_DLOPEN */ }
static int external_passwd_quality (krb5_context context, krb5_principal principal, krb5_data *pwd, const char *opaque, char *message, size_t length) { krb5_error_code ret; const char *program; char *p; pid_t child; int status; char reply[1024]; FILE *in = NULL, *out = NULL, *error = NULL; if (memchr(pwd->data, '\n', pwd->length) != NULL) { snprintf(message, length, "password contains newline, " "not valid for external test"); return 1; } program = krb5_config_get_string(context, NULL, "password_quality", "external_program", NULL); if (program == NULL) { snprintf(message, length, "external password quality " "program not configured"); return 1; } ret = krb5_unparse_name(context, principal, &p); if (ret) { strlcpy(message, "out of memory", length); return 1; } child = pipe_execv(&in, &out, &error, program, program, p, NULL); if (child < 0) { snprintf(message, length, "external password quality " "program failed to execute for principal %s", p); free(p); return 1; } fprintf(in, "principal: %s\n" "new-password: %.*s\n" "end\n", p, (int)pwd->length, (char *)pwd->data); fclose(in); if (fgets(reply, sizeof(reply), out) == NULL) { if (fgets(reply, sizeof(reply), error) == NULL) { snprintf(message, length, "external password quality " "program failed without error"); } else { reply[strcspn(reply, "\n")] = '\0'; snprintf(message, length, "External password quality " "program failed: %s", reply); } fclose(out); fclose(error); wait_for_process(child); return 1; } reply[strcspn(reply, "\n")] = '\0'; fclose(out); fclose(error); status = wait_for_process(child); if (SE_IS_ERROR(status) || SE_PROCSTATUS(status) != 0) { snprintf(message, length, "external program failed: %s", reply); free(p); return 1; } if (strcmp(reply, "APPROVED") != 0) { snprintf(message, length, "%s", reply); free(p); return 1; } free(p); return 0; }
krb5_kdc_configuration * configure(krb5_context context, int argc, char **argv) { krb5_kdc_configuration *config; krb5_error_code ret; int optidx = 0; const char *p; while(getarg(args, num_args, argc, argv, &optidx)) warnx("error at argument `%s'", argv[optidx]); if(help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } if (builtin_hdb_flag) { char *list; ret = hdb_list_builtin(context, &list); if (ret) krb5_err(context, 1, ret, "listing builtin hdb backends"); printf("builtin hdb backends: %s\n", list); free(list); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage(1); { char **files; if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if(ret) krb5_err(context, 1, ret, "reading configuration files"); } ret = krb5_kdc_get_config(context, &config); if (ret) krb5_err(context, 1, ret, "krb5_kdc_default_config"); kdc_openlog(context, "kdc", config); ret = krb5_kdc_set_dbinfo(context, config); if (ret) krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo"); if(max_request_str) max_request_tcp = max_request_udp = parse_bytes(max_request_str, NULL); if(max_request_tcp == 0){ p = krb5_config_get_string (context, NULL, "kdc", "max-request", NULL); if(p) max_request_tcp = max_request_udp = parse_bytes(p, NULL); } if(require_preauth != -1) config->require_preauth = require_preauth; if(port_str == NULL){ p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL); if (p != NULL) port_str = strdup(p); } explicit_addresses.len = 0; if (addresses_str.num_strings) { int i; for (i = 0; i < addresses_str.num_strings; ++i) add_one_address (context, addresses_str.strings[i], i == 0); free_getarg_strings (&addresses_str); } else { char **foo = krb5_config_get_strings (context, NULL, "kdc", "addresses", NULL); if (foo != NULL) { add_one_address (context, *foo++, TRUE); while (*foo) add_one_address (context, *foo++, FALSE); } } if(enable_v4 != -1) config->enable_v4 = enable_v4; if(enable_v4_cross_realm != -1) config->enable_v4_cross_realm = enable_v4_cross_realm; if(enable_524 != -1) config->enable_524 = enable_524; if(enable_http == -1) enable_http = krb5_config_get_bool(context, NULL, "kdc", "enable-http", NULL); if(request_log == NULL) request_log = krb5_config_get_string(context, NULL, "kdc", "kdc-request-log", NULL); if (krb5_config_get_string(context, NULL, "kdc", "enforce-transited-policy", NULL)) krb5_errx(context, 1, "enforce-transited-policy deprecated, " "use [kdc]transited-policy instead"); if (enable_kaserver != -1) config->enable_kaserver = enable_kaserver; #ifdef SUPPORT_DETACH if(detach_from_console == -1) detach_from_console = krb5_config_get_bool_default(context, NULL, DETACH_IS_DEFAULT, "kdc", "detach", NULL); #endif /* SUPPORT_DETACH */ if(max_request_tcp == 0) max_request_tcp = 64 * 1024; if(max_request_udp == 0) max_request_udp = 64 * 1024; if (port_str == NULL) port_str = "+"; if (v4_realm) config->v4_realm = v4_realm; if(config->v4_realm == NULL && (config->enable_kaserver || config->enable_v4)) krb5_errx(context, 1, "Kerberos 4 enabled but no realm configured"); if(disable_des == -1) disable_des = krb5_config_get_bool_default(context, NULL, FALSE, "kdc", "disable-des", NULL); if(disable_des) { krb5_enctype_disable(context, ETYPE_DES_CBC_CRC); krb5_enctype_disable(context, ETYPE_DES_CBC_MD4); krb5_enctype_disable(context, ETYPE_DES_CBC_MD5); krb5_enctype_disable(context, ETYPE_DES_CBC_NONE); krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE); krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE); kdc_log(context, config, 0, "DES was disabled, turned off Kerberos V4, 524 " "and kaserver"); config->enable_v4 = 0; config->enable_524 = 0; config->enable_kaserver = 0; } krb5_kdc_windc_init(context); #ifdef PKINIT #ifdef __APPLE__ config->enable_pkinit = 1; if (config->pkinit_kdc_identity == NULL) { if (config->pkinit_kdc_friendly_name == NULL) config->pkinit_kdc_friendly_name = strdup("O=System Identity,CN=com.apple.kerberos.kdc"); config->pkinit_kdc_identity = strdup("KEYCHAIN:"); } if (config->pkinit_kdc_anchors == NULL) config->pkinit_kdc_anchors = strdup("KEYCHAIN:"); #endif /* __APPLE__ */ if (config->enable_pkinit) { if (config->pkinit_kdc_identity == NULL) krb5_errx(context, 1, "pkinit enabled but no identity"); if (config->pkinit_kdc_anchors == NULL) krb5_errx(context, 1, "pkinit enabled but no X509 anchors"); krb5_kdc_pk_initialize(context, config, config->pkinit_kdc_identity, config->pkinit_kdc_anchors, config->pkinit_kdc_cert_pool, config->pkinit_kdc_revoke); } #endif /* PKINIT */ return config; }
krb5_error_code KRB5_LIB_FUNCTION krb5_425_conv_principal_ext2(krb5_context context, const char *name, const char *instance, const char *realm, krb5_boolean (*func)(krb5_context, void *, krb5_principal), void *funcctx, krb5_boolean resolve, krb5_principal *princ) { const char *p; krb5_error_code ret; krb5_principal pr; char host[MAXHOSTNAMELEN]; char local_hostname[MAXHOSTNAMELEN]; /* do the following: if the name is found in the `v4_name_convert:host' part, is is assumed to be a `host' type principal, and the instance is looked up in the `v4_instance_convert' part. if not found there the name is (optionally) looked up as a hostname, and if that doesn't yield anything, the `default_domain' is appended to the instance */ if(instance == NULL) goto no_host; if(instance[0] == 0){ instance = NULL; goto no_host; } p = get_name_conversion(context, realm, name); if(p == NULL) goto no_host; name = p; p = krb5_config_get_string(context, NULL, "realms", realm, "v4_instance_convert", instance, NULL); if(p){ instance = p; ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); if(func == NULL || (*func)(context, funcctx, pr)){ *princ = pr; return 0; } krb5_free_principal(context, pr); *princ = NULL; krb5_clear_error_string (context); return HEIM_ERR_V4_PRINC_NO_CONV; } if(resolve){ krb5_boolean passed = FALSE; char *inst = NULL; #ifdef USE_RESOLVER struct dns_reply *r; r = dns_lookup(instance, "aaaa"); if (r) { if (r->head && r->head->type == T_AAAA) { inst = strdup(r->head->domain); passed = TRUE; } dns_free_data(r); } else { r = dns_lookup(instance, "a"); if (r) { if(r->head && r->head->type == T_A) { inst = strdup(r->head->domain); passed = TRUE; } dns_free_data(r); } } #else struct addrinfo hints, *ai; memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; ret = getaddrinfo(instance, NULL, &hints, &ai); if (ret == 0) { const struct addrinfo *a; for (a = ai; a != NULL; a = a->ai_next) { if (a->ai_canonname != NULL) { inst = strdup (a->ai_canonname); passed = TRUE; break; } } freeaddrinfo (ai); } #endif if (passed) { if (inst == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } strlwr(inst); ret = krb5_make_principal(context, &pr, realm, name, inst, NULL); free (inst); if(ret == 0) { if(func == NULL || (*func)(context, funcctx, pr)){ *princ = pr; return 0; } krb5_free_principal(context, pr); } } } if(func != NULL) { snprintf(host, sizeof(host), "%s.%s", instance, realm); strlwr(host); ret = krb5_make_principal(context, &pr, realm, name, host, NULL); if((*func)(context, funcctx, pr)){ *princ = pr; return 0; } krb5_free_principal(context, pr); } /* * if the instance is the first component of the local hostname, * the converted host should be the long hostname. */ if (func == NULL && gethostname (local_hostname, sizeof(local_hostname)) == 0 && strncmp(instance, local_hostname, strlen(instance)) == 0 && local_hostname[strlen(instance)] == '.') { strlcpy(host, local_hostname, sizeof(host)); goto local_host; } { char **domains, **d; domains = krb5_config_get_strings(context, NULL, "realms", realm, "v4_domains", NULL); for(d = domains; d && *d; d++){ snprintf(host, sizeof(host), "%s.%s", instance, *d); ret = krb5_make_principal(context, &pr, realm, name, host, NULL); if(func == NULL || (*func)(context, funcctx, pr)){ *princ = pr; krb5_config_free_strings(domains); return 0; } krb5_free_principal(context, pr); } krb5_config_free_strings(domains); } p = krb5_config_get_string(context, NULL, "realms", realm, "default_domain", NULL); if(p == NULL){ /* this should be an error, just faking a name is not good */ krb5_clear_error_string (context); return HEIM_ERR_V4_PRINC_NO_CONV; } if (*p == '.') ++p; snprintf(host, sizeof(host), "%s.%s", instance, p); local_host: ret = krb5_make_principal(context, &pr, realm, name, host, NULL); if(func == NULL || (*func)(context, funcctx, pr)){ *princ = pr; return 0; } krb5_free_principal(context, pr); krb5_clear_error_string (context); return HEIM_ERR_V4_PRINC_NO_CONV; no_host: p = krb5_config_get_string(context, NULL, "realms", realm, "v4_name_convert", "plain", name, NULL); if(p == NULL) p = krb5_config_get_string(context, NULL, "libdefaults", "v4_name_convert", "plain", name, NULL); if(p) name = p; ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); if(func == NULL || (*func)(context, funcctx, pr)){ *princ = pr; return 0; } krb5_free_principal(context, pr); krb5_clear_error_string (context); return HEIM_ERR_V4_PRINC_NO_CONV; }
krb5_error_code hdb_ldap_create(krb5_context context, HDB ** db, const char *arg) { struct hdbldapdb *h; const char *create_base = NULL; if (arg == NULL && arg[0] == '\0') { krb5_set_error_string(context, "ldap search base not configured"); return ENOMEM; /* XXX */ } if (structural_object == NULL) { const char *p; p = krb5_config_get_string(context, NULL, "kdc", "hdb-ldap-structural-object", NULL); if (p == NULL) p = default_structural_object; structural_object = strdup(p); if (structural_object == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } } samba_forwardable = krb5_config_get_bool_default(context, NULL, TRUE, "kdc", "hdb-samba-forwardable", NULL); *db = malloc(sizeof(**db)); if (*db == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } memset(*db, 0, sizeof(**db)); h = malloc(sizeof(*h)); if (h == NULL) { krb5_set_error_string(context, "malloc: out of memory"); free(*db); *db = NULL; return ENOMEM; } memset(h, 0, sizeof(*h)); asprintf(&(*db)->hdb_name, "ldap:%s", arg); (*db)->hdb_db = h; h->h_base = strdup(arg); if (h->h_base == NULL) { LDAP_destroy(context, *db); krb5_set_error_string(context, "strdup: out of memory"); *db = NULL; return ENOMEM; } create_base = krb5_config_get_string(context, NULL, "kdc", "hdb-ldap-create-base", NULL); if (create_base == NULL) create_base = h->h_base; h->h_createbase = strdup(create_base); if (h->h_createbase == NULL) { LDAP_destroy(context, *db); krb5_set_error_string(context, "strdup: out of memory"); *db = NULL; return ENOMEM; } (*db)->hdb_master_key_set = 0; (*db)->hdb_openp = 0; (*db)->hdb_open = LDAP_open; (*db)->hdb_close = LDAP_close; (*db)->hdb_fetch = LDAP_fetch; (*db)->hdb_store = LDAP_store; (*db)->hdb_remove = LDAP_remove; (*db)->hdb_firstkey = LDAP_firstkey; (*db)->hdb_nextkey = LDAP_nextkey; (*db)->hdb_lock = LDAP_lock; (*db)->hdb_unlock = LDAP_unlock; (*db)->hdb_rename = LDAP_rename; (*db)->hdb__get = NULL; (*db)->hdb__put = NULL; (*db)->hdb__del = NULL; (*db)->hdb_destroy = LDAP_destroy; return 0; }
static krb5_error_code init_context_from_config_file(krb5_context context) { krb5_error_code ret; const char * tmp; char **s; krb5_enctype *tmptypes; INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); INIT_FIELD(context, time, kdc_timeout, 30, "kdc_timeout"); INIT_FIELD(context, time, host_timeout, 3, "host_timeout"); INIT_FIELD(context, int, max_retries, 3, "max_retries"); INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); ret = krb5_config_get_bool_default(context, NULL, FALSE, "libdefaults", "allow_weak_crypto", NULL); if (ret) { krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); } ret = set_etypes (context, "default_etypes", &tmptypes); if(ret) return ret; free(context->etypes); context->etypes = tmptypes; ret = set_etypes (context, "default_etypes_des", &tmptypes); if(ret) return ret; free(context->etypes_des); context->etypes_des = tmptypes; ret = set_etypes (context, "default_as_etypes", &tmptypes); if(ret) return ret; free(context->as_etypes); context->as_etypes = tmptypes; ret = set_etypes (context, "default_tgs_etypes", &tmptypes); if(ret) return ret; free(context->tgs_etypes); context->tgs_etypes = tmptypes; ret = set_etypes (context, "permitted_enctypes", &tmptypes); if(ret) return ret; free(context->permitted_enctypes); context->permitted_enctypes = tmptypes; /* default keytab name */ tmp = NULL; if(!issuid()) tmp = getenv("KRB5_KTNAME"); if(tmp != NULL) context->default_keytab = tmp; else INIT_FIELD(context, string, default_keytab, KEYTAB_DEFAULT, "default_keytab_name"); INIT_FIELD(context, string, default_keytab_modify, NULL, "default_keytab_modify_name"); INIT_FIELD(context, string, time_fmt, "%Y-%m-%dT%H:%M:%S", "time_format"); INIT_FIELD(context, string, date_fmt, "%Y-%m-%d", "date_format"); INIT_FIELD(context, bool, log_utc, FALSE, "log_utc"); /* init dns-proxy slime */ tmp = krb5_config_get_string(context, NULL, "libdefaults", "dns_proxy", NULL); if(tmp) roken_gethostby_setup(context->http_proxy, tmp); krb5_free_host_realm (context, context->default_realms); context->default_realms = NULL; { krb5_addresses addresses; char **adr, **a; krb5_set_extra_addresses(context, NULL); adr = krb5_config_get_strings(context, NULL, "libdefaults", "extra_addresses", NULL); memset(&addresses, 0, sizeof(addresses)); for(a = adr; a && *a; a++) { ret = krb5_parse_address(context, *a, &addresses); if (ret == 0) { krb5_add_extra_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } krb5_config_free_strings(adr); krb5_set_ignore_addresses(context, NULL); adr = krb5_config_get_strings(context, NULL, "libdefaults", "ignore_addresses", NULL); memset(&addresses, 0, sizeof(addresses)); for(a = adr; a && *a; a++) { ret = krb5_parse_address(context, *a, &addresses); if (ret == 0) { krb5_add_ignore_addresses(context, &addresses); krb5_free_addresses(context, &addresses); } } krb5_config_free_strings(adr); } INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); /* prefer dns_lookup_kdc over srv_lookup. */ INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); INIT_FIELD(context, int, max_msg_size, 1000 * 1024, "maximum_message_size"); INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); if (context->default_cc_name) free(context->default_cc_name); context->default_cc_name = NULL; context->default_cc_name_set = 0; s = krb5_config_get_strings(context, NULL, "logging", "krb5", NULL); if(s) { char **p; if (context->debug_dest) krb5_closelog(context, context->debug_dest); krb5_initlog(context, "libkrb5", &context->debug_dest); for(p = s; *p; p++) krb5_addlog_dest(context, context->debug_dest, *p); krb5_config_free_strings(s); } tmp = krb5_config_get_string(context, NULL, "libdefaults", "check-rd-req-server", NULL); if (tmp == NULL && !issuid()) tmp = getenv("KRB5_CHECK_RD_REQ_SERVER"); if(tmp) { if (strcasecmp(tmp, "ignore") == 0) context->flags |= KRB5_CTX_F_RD_REQ_IGNORE; } ret = krb5_config_get_bool_default(context, NULL, TRUE, "libdefaults", "fcache_strict_checking", NULL); if (ret) context->flags |= KRB5_CTX_F_FCACHE_STRICT_CHECKING; return 0; }
krb5_error_code krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) { krb5_kdc_configuration *c; c = calloc(1, sizeof(*c)); if (c == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } c->require_preauth = TRUE; c->kdc_warn_pwexpire = 0; c->encode_as_rep_as_tgs_rep = FALSE; c->tgt_use_strongest_session_key = FALSE; c->preauth_use_strongest_session_key = FALSE; c->svc_use_strongest_session_key = FALSE; c->use_strongest_server_key = TRUE; c->check_ticket_addresses = TRUE; c->allow_null_ticket_addresses = TRUE; c->allow_anonymous = FALSE; c->trpolicy = TRPOLICY_ALWAYS_CHECK; c->enable_pkinit = FALSE; c->pkinit_princ_in_cert = TRUE; c->pkinit_require_binding = TRUE; c->db = NULL; c->num_db = 0; c->logf = NULL; c->require_preauth = krb5_config_get_bool_default(context, NULL, c->require_preauth, "kdc", "require-preauth", NULL); #ifdef DIGEST c->enable_digest = krb5_config_get_bool_default(context, NULL, FALSE, "kdc", "enable-digest", NULL); { const char *digests; digests = krb5_config_get_string(context, NULL, "kdc", "digests_allowed", NULL); if (digests == NULL) digests = "ntlm-v2"; c->digests_allowed = parse_flags(digests,_kdc_digestunits, 0); if (c->digests_allowed == -1) { kdc_log(context, c, 0, "unparsable digest units (%s), turning off digest", digests); c->enable_digest = 0; } else if (c->digests_allowed == 0) { kdc_log(context, c, 0, "no digest enable, turning digest off", digests); c->enable_digest = 0; } } #endif #ifdef KX509 c->enable_kx509 = krb5_config_get_bool_default(context, NULL, FALSE, "kdc", "enable-kx509", NULL); if (c->enable_kx509) { c->kx509_template = krb5_config_get_string(context, NULL, "kdc", "kx509_template", NULL); c->kx509_ca = krb5_config_get_string(context, NULL, "kdc", "kx509_ca", NULL); if (c->kx509_ca == NULL || c->kx509_template == NULL) { kdc_log(context, c, 0, "missing kx509 configuration, turning off"); c->enable_kx509 = FALSE; } } #endif c->tgt_use_strongest_session_key = krb5_config_get_bool_default(context, NULL, c->tgt_use_strongest_session_key, "kdc", "tgt-use-strongest-session-key", NULL); c->preauth_use_strongest_session_key = krb5_config_get_bool_default(context, NULL, c->preauth_use_strongest_session_key, "kdc", "preauth-use-strongest-session-key", NULL); c->svc_use_strongest_session_key = krb5_config_get_bool_default(context, NULL, c->svc_use_strongest_session_key, "kdc", "svc-use-strongest-session-key", NULL); c->use_strongest_server_key = krb5_config_get_bool_default(context, NULL, c->use_strongest_server_key, "kdc", "use-strongest-server-key", NULL); c->check_ticket_addresses = krb5_config_get_bool_default(context, NULL, c->check_ticket_addresses, "kdc", "check-ticket-addresses", NULL); c->allow_null_ticket_addresses = krb5_config_get_bool_default(context, NULL, c->allow_null_ticket_addresses, "kdc", "allow-null-ticket-addresses", NULL); c->allow_anonymous = krb5_config_get_bool_default(context, NULL, c->allow_anonymous, "kdc", "allow-anonymous", NULL); c->max_datagram_reply_length = krb5_config_get_int_default(context, NULL, 1400, "kdc", "max-kdc-datagram-reply-length", NULL); { const char *trpolicy_str; trpolicy_str = krb5_config_get_string_default(context, NULL, "DEFAULT", "kdc", "transited-policy", NULL); if(strcasecmp(trpolicy_str, "always-check") == 0) { c->trpolicy = TRPOLICY_ALWAYS_CHECK; } else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0) { c->trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL; } else if(strcasecmp(trpolicy_str, "always-honour-request") == 0) { c->trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST; } else if(strcasecmp(trpolicy_str, "DEFAULT") == 0) { /* default */ } else { kdc_log(context, c, 0, "unknown transited-policy: %s, " "reverting to default (always-check)", trpolicy_str); } } c->encode_as_rep_as_tgs_rep = krb5_config_get_bool_default(context, NULL, c->encode_as_rep_as_tgs_rep, "kdc", "encode_as_rep_as_tgs_rep", NULL); c->kdc_warn_pwexpire = krb5_config_get_time_default (context, NULL, c->kdc_warn_pwexpire, "kdc", "kdc_warn_pwexpire", NULL); c->enable_pkinit = krb5_config_get_bool_default(context, NULL, c->enable_pkinit, "kdc", "enable-pkinit", NULL); c->pkinit_kdc_identity = krb5_config_get_string(context, NULL, "kdc", "pkinit_identity", NULL); c->pkinit_kdc_anchors = krb5_config_get_string(context, NULL, "kdc", "pkinit_anchors", NULL); c->pkinit_kdc_cert_pool = krb5_config_get_strings(context, NULL, "kdc", "pkinit_pool", NULL); c->pkinit_kdc_revoke = krb5_config_get_strings(context, NULL, "kdc", "pkinit_revoke", NULL); c->pkinit_kdc_ocsp_file = krb5_config_get_string(context, NULL, "kdc", "pkinit_kdc_ocsp", NULL); c->pkinit_kdc_friendly_name = krb5_config_get_string(context, NULL, "kdc", "pkinit_kdc_friendly_name", NULL); c->pkinit_princ_in_cert = krb5_config_get_bool_default(context, NULL, c->pkinit_princ_in_cert, "kdc", "pkinit_principal_in_certificate", NULL); c->pkinit_require_binding = krb5_config_get_bool_default(context, NULL, c->pkinit_require_binding, "kdc", "pkinit_win2k_require_binding", NULL); c->pkinit_dh_min_bits = krb5_config_get_int_default(context, NULL, 0, "kdc", "pkinit_dh_min_bits", NULL); *config = c; return 0; }