Esempio n. 1
0
static krb5_error_code
set_etypes (krb5_context context,
	    const char *name,
	    krb5_enctype **ret_enctypes)
{
    char **etypes_str;
    krb5_enctype *etypes = NULL;

    etypes_str = krb5_config_get_strings(context, NULL, "libdefaults",
					 name, NULL);
    if(etypes_str){
	int i, j, k;
	for(i = 0; etypes_str[i]; i++);
	etypes = malloc((i+1) * sizeof(*etypes));
	if (etypes == NULL) {
	    krb5_config_free_strings (etypes_str);
	    return krb5_enomem(context);
	}
	for(j = 0, k = 0; j < i; j++) {
	    krb5_enctype e;
	    if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0)
		continue;
	    if (krb5_enctype_valid(context, e) != 0)
		continue;
	    etypes[k++] = e;
	}
	etypes[k] = ETYPE_NULL;
	krb5_config_free_strings(etypes_str);
    }
    *ret_enctypes = etypes;
    return 0;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_check_transited_realms(krb5_context context,
			    const char *const *realms,
			    unsigned int num_realms,
			    int *bad_realm)
{
    size_t i;
    int ret = 0;
    char **bad_realms = krb5_config_get_strings(context, NULL,
						"libdefaults",
						"transited_realms_reject",
						NULL);
    if(bad_realms == NULL)
	return 0;

    for(i = 0; i < num_realms; i++) {
	char **p;
	for(p = bad_realms; *p; p++)
	    if(strcmp(*p, realms[i]) == 0) {
		ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
		krb5_set_error_message (context, ret,
					N_("no transit allowed "
					   "through realm %s", ""),
					*p);
		if(bad_realm)
		    *bad_realm = (int)i;
		break;
	    }
    }
    krb5_config_free_strings(bad_realms);
    return ret;
}
Esempio n. 3
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_check_transited_realms(krb5_context context,
			    const char *const *realms, 
			    int num_realms, 
			    int *bad_realm)
{
    int i;
    int ret = 0;
    char **bad_realms = krb5_config_get_strings(context, NULL, 
						"libdefaults", 
						"transited_realms_reject", 
						NULL);
    if(bad_realms == NULL)
	return 0;

    for(i = 0; i < num_realms; i++) {
	char **p;
	for(p = bad_realms; *p; p++)
	    if(strcmp(*p, realms[i]) == 0) {
		krb5_set_error_string (context, "no transit through realm %s",
				       *p);
		ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
		if(bad_realm)
		    *bad_realm = i;
		break;
	    }
    }
    krb5_config_free_strings(bad_realms);
    return ret;
}
Esempio n. 4
0
const char *
kadm5_check_password_quality (krb5_context context,
			      krb5_principal principal,
			      krb5_data *pwd_data)
{
    const struct kadm5_pw_policy_check_func *proc;
    static char error_msg[1024];
    const char *msg;
    char **v, **vp;
    int ret;

    /*
     * Check if we should use the old version of policy function.
     */

    v = krb5_config_get_strings(context, NULL,
				"password_quality",
				"policies",
				NULL);
    if (v == NULL) {
	msg = (*passwd_quality_check) (context, principal, pwd_data);
	if (msg)
	    krb5_set_error_message(context, 0, "password policy failed: %s", msg);
	return msg;
    }

    error_msg[0] = '\0';

    msg = NULL;
    for(vp = v; *vp; vp++) {
	proc = find_func(context, *vp);
	if (proc == NULL) {
	    msg = "failed to find password verifier function";
	    krb5_set_error_message(context, 0, "Failed to find password policy "
				   "function: %s", *vp);
	    break;
	}
	ret = (proc->func)(context, principal, pwd_data, NULL,
			   error_msg, sizeof(error_msg));
	if (ret) {
	    krb5_set_error_message(context, 0, "Password policy "
				   "%s failed with %s",
				   proc->name, error_msg);
	    msg = error_msg;
	    break;
	}
    }
    krb5_config_free_strings(v);

    /* If the default quality check isn't used, lets check that the
     * old quality function the user have set too */
    if (msg == NULL && passwd_quality_check != min_length_passwd_quality_v0) {
	msg = (*passwd_quality_check) (context, principal, pwd_data);
	if (msg)
	    krb5_set_error_message(context, 0, "(old) password policy "
				   "failed with %s", msg);

    }
    return msg;
}
Esempio n. 5
0
krb5_error_code
kadm5_add_passwd_quality_verifier(krb5_context context,
				  const char *check_library)
{
#ifdef HAVE_DLOPEN

    if(check_library == NULL) {
	krb5_error_code ret = 0;
        char **strs;
	char **tmp;

	strs = krb5_config_get_strings(context, NULL,
				       "password_quality",
				       "policy_libraries",
				       NULL);
	if (strs == NULL)
	    return 0;

	for (tmp = strs; *tmp; tmp++) {
	    ret = add_verifier(context, *tmp);
	    if (ret)
		break;
	}
        krb5_config_free_strings(strs);
	return ret;
    } else {
	return add_verifier(context, check_library);
    }
#else
    return 0;
#endif /* HAVE_DLOPEN */
}
Esempio n. 6
0
static int
dns_find_realm(krb5_context context,
	       const char *domain,
	       krb5_realm **realms)
{
    static const char *default_labels[] = { "_kerberos", NULL };
    char dom[MAXHOSTNAMELEN];
    struct rk_dns_reply *r;
    const char **labels;
    char **config_labels;
    int i, ret;

    config_labels = krb5_config_get_strings(context, NULL, "libdefaults",
					    "dns_lookup_realm_labels", NULL);
    if(config_labels != NULL)
	labels = (const char **)config_labels;
    else
	labels = default_labels;
    if(*domain == '.')
	domain++;
    for (i = 0; labels[i] != NULL; i++) {
	ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain);
	if(ret < 0 || (size_t)ret >= sizeof(dom)) {
	    if (config_labels)
		krb5_config_free_strings(config_labels);
	    return -1;
	}
    	r = rk_dns_lookup(dom, "TXT");
    	if(r != NULL) {
	    ret = copy_txt_to_realms (r->head, realms);
	    rk_dns_free_data(r);
	    if(ret == 0) {
		if (config_labels)
		    krb5_config_free_strings(config_labels);
		return 0;
	    }
	}
    }
    if (config_labels)
	krb5_config_free_strings(config_labels);
    return -1;
}
Esempio n. 7
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_check_transited(krb5_context context,
		     krb5_const_realm client_realm,
		     krb5_const_realm server_realm,
		     krb5_realm *realms,
		     unsigned int num_realms,
		     int *bad_realm)
{
    char **tr_realms;
    char **p;
    size_t i;

    if(num_realms == 0)
	return 0;

    tr_realms = krb5_config_get_strings(context, NULL,
					"capaths",
					client_realm,
					server_realm,
					NULL);
    for(i = 0; i < num_realms; i++) {
	for(p = tr_realms; p && *p; p++) {
	    if(strcmp(*p, realms[i]) == 0)
		break;
	}
	if(p == NULL || *p == NULL) {
	    krb5_config_free_strings(tr_realms);
	    krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT,
				    N_("no transit allowed "
				       "through realm %s", ""),
				    realms[i]);
	    if(bad_realm)
		*bad_realm = i;
	    return KRB5KRB_AP_ERR_ILL_CR_TKT;
	}
    }
    krb5_config_free_strings(tr_realms);
    return 0;
}
Esempio n. 8
0
static void
check_escaped_strings(void)
{
    krb5_context context;
    krb5_config_section *c = NULL;
    krb5_error_code ret;
    int i;

    ret = krb5_init_context(&context);
    if (ret)
        errx(1, "krb5_init_context %d", ret);

    ret = krb5_config_parse_file(context, "test_config_strings.out", &c);
    if (ret)
        krb5_errx(context, 1, "krb5_config_parse_file()");

    for (i=0; i < sizeof(config_strings_tests)/sizeof(config_strings_tests[0]); i++) {
        char **ps;
        const char **s;
        const char **e;

        ps = krb5_config_get_strings(context, c, "escapes", config_strings_tests[i].name,
                                     NULL);
        if (ps == NULL)
            errx(1, "Failed to read string value %s", config_strings_tests[i].name);

        e = config_strings_tests[i].expected;

        for (s = (const char **)ps; *s && *e; s++, e++) {
            if (strcmp(*s, *e))
                errx(1,
                     "Unexpected configuration string at value [%s].\n"
                     "Actual=[%s]\n"
                     "Expected=[%s]\n",
                     config_strings_tests[i].name, *s, *e);
        }

        if (*s || *e)
            errx(1, "Configuation string list for value [%s] has incorrect length.",
		 config_strings_tests[i].name);

        krb5_config_free_strings(ps);
    }

    ret = krb5_config_file_free(context, c);
    if (ret)
        krb5_errx(context, 1, "krb5_config_file_free()");

    krb5_free_context(context);
}
Esempio n. 9
0
void
kcm_openlog(void)
{
    char **s = NULL, **p;
    krb5_initlog(kcm_context, "kcm", &logf);
    s = krb5_config_get_strings(kcm_context, NULL, "kcm", "logging", NULL);
    if(s == NULL)
        s = krb5_config_get_strings(kcm_context, NULL, "logging", "kcm", NULL);
    if(s) {
        for(p = s; *p; p++)
            krb5_addlog_dest(kcm_context, logf, *p);
        krb5_config_free_strings(s);
    } else
        krb5_addlog_dest(kcm_context, logf, DEFAULT_LOG_DEST);
    krb5_set_warn_dest(kcm_context, logf);
}
Esempio n. 10
0
void
kdc_openlog(krb5_context context, 
	    krb5_kdc_configuration *config)
{
    char **s = NULL, **p;
    krb5_initlog(context, "kdc", &config->logf);
    s = krb5_config_get_strings(context, NULL, "kdc", "logging", NULL);
    if(s == NULL)
	s = krb5_config_get_strings(context, NULL, "logging", "kdc", NULL);
    if(s){
	for(p = s; *p; p++)
	    krb5_addlog_dest(context, config->logf, *p);
	krb5_config_free_strings(s);
    }else
	krb5_addlog_dest(context, config->logf, DEFAULT_LOG_DEST);
    krb5_set_warn_dest(context, config->logf);
}
Esempio n. 11
0
static void
init_context_once(void *ctx)
{
    krb5_context context = ctx;
    char **dirs;

    dirs = krb5_config_get_strings(context, NULL, "libdefaults",
				   "plugin_dir", NULL);
    if (dirs == NULL)
	dirs = rk_UNCONST(sysplugin_dirs);

    _krb5_load_plugins(context, "krb5", (const char **)dirs);

    if (dirs != rk_UNCONST(sysplugin_dirs))
	krb5_config_free_strings(dirs);

    bindtextdomain(HEIMDAL_TEXTDOMAIN, HEIMDAL_LOCALEDIR);
}
Esempio n. 12
0
static void
config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 
		 const char *conf_string)
{
    int i;
	
    char **hostlist;
    hostlist = krb5_config_get_strings(context, NULL, 
				       "realms", kd->realm, conf_string, NULL);

    if(hostlist == NULL)
	return;
    kd->flags |= KD_CONFIG_EXISTS;
    for(i = 0; hostlist && hostlist[i] != NULL; i++)
	append_host_string(context, kd, hostlist[i], kd->def_port, kd->port);

    krb5_config_free_strings(hostlist);
}
Esempio n. 13
0
static krb5_error_code
check_compat(OM_uint32 *minor_status,
	     krb5_context context, krb5_const_principal name,
	     const char *option, krb5_boolean *compat,
	     krb5_boolean match_val)
{
    krb5_error_code ret = 0;
    char **p, **q;
    krb5_principal match;


    p = krb5_config_get_strings(context, NULL, "gssapi",
				option, NULL);
    if(p == NULL)
	return 0;

    match = NULL;
    for(q = p; *q; q++) {
	ret = krb5_parse_name(context, *q, &match);
	if (ret)
	    break;

	if (krb5_principal_match(context, name, match)) {
	    *compat = match_val;
	    break;
	}

	krb5_free_principal(context, match);
	match = NULL;
    }
    if (match)
	krb5_free_principal(context, match);
    krb5_config_free_strings(p);

    if (ret) {
	if (minor_status)
	    *minor_status = ret;
	return GSS_S_FAILURE;
    }

    return 0;
}
Esempio n. 14
0
/*
 * This function implements MIT's auth_to_local_names configuration for
 * configuration compatibility.  Specifically:
 *
 * [realms]
 *     <realm-name> = {
 *         auth_to_local_names = {
 *             <unparsed-principal-name> = <username>
 *         }
 *     }
 *
 * If multiple usernames are configured then the last one is taken.
 *
 * The configuration can only be expected to hold a relatively small
 * number of mappings.  For lots of mappings use a DB.
 */
static krb5_error_code
an2ln_local_names(krb5_context context,
		  krb5_const_principal aname,
		  size_t lnsize,
		  char *lname)
{
    krb5_error_code ret;
    char *unparsed;
    char **values;
    char *res;
    size_t i;

    if (!princ_realm_is_default(context, aname))
	return KRB5_PLUGIN_NO_HANDLE;

    ret = krb5_unparse_name_flags(context, aname,
				  KRB5_PRINCIPAL_UNPARSE_NO_REALM,
				  &unparsed);
    if (ret)
	return ret;

    ret = KRB5_PLUGIN_NO_HANDLE;
    values = krb5_config_get_strings(context, NULL, "realms", aname->realm,
				     "auth_to_local_names", unparsed, NULL);
    free(unparsed);
    if (!values)
	return ret;
    /* Take the last value, just like MIT */
    for (res = NULL, i = 0; values[i]; i++)
	res = values[i];
    if (res) {
	ret = 0;
	if (strlcpy(lname, res, lnsize) >= lnsize)
	    ret = KRB5_CONFIG_NOTENUFSPACE;

	if (!*res || strcmp(res, ":") == 0)
	    ret = KRB5_NO_LOCALNAME;
    }

    krb5_config_free_strings(values);
    return ret;
}
Esempio n. 15
0
File: log.c Progetto: AllardJ/Tomato
void
kdc_openlog(krb5_context context,
	    krb5_kdc_configuration *config)
{
    char **s = NULL, **p;
    krb5_initlog(context, "kdc", &config->logf);
    s = krb5_config_get_strings(context, NULL, "kdc", "logging", NULL);
    if(s == NULL)
	s = krb5_config_get_strings(context, NULL, "logging", "kdc", NULL);
    if(s){
	for(p = s; *p; p++)
	    krb5_addlog_dest(context, config->logf, *p);
	krb5_config_free_strings(s);
    }else {
	char *s;
	asprintf(&s, "0-1/FILE:%s/%s", hdb_db_dir(context), KDC_LOG_FILE);
	krb5_addlog_dest(context, config->logf, s);
	free(s);
    }
    krb5_set_warn_dest(context, config->logf);
}
Esempio n. 16
0
File: log.c Progetto: gojdic/samba
krb5_error_code KRB5_LIB_FUNCTION
krb5_openlog(krb5_context context,
	     const char *program,
	     krb5_log_facility **fac)
{
    krb5_error_code ret;
    char **p, **q;

    ret = krb5_initlog(context, program, fac);
    if(ret)
	return ret;

    p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
    if(p == NULL)
	p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
    if(p){
	for(q = p; *q && ret == 0; q++)
	    ret = krb5_addlog_dest(context, *fac, *q);
	krb5_config_free_strings(p);
    }else
	ret = krb5_addlog_dest(context, *fac, "SYSLOG");
    return ret;
}
Esempio n. 17
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;
}
Esempio n. 18
0
static krb5_error_code
change_pw_and_update_keytab(krb5_context context,
			    kcm_ccache ccache)
{
    char newpw[121];
    krb5_error_code ret;
    unsigned kvno;
    krb5_salt salt;
    krb5_enctype *etypes = NULL;
    int i;
    char *cpn = NULL;
    char **spns = NULL;

    krb5_data_zero(&salt.saltvalue);

    ret = krb5_unparse_name(context, ccache->client, &cpn);
    if (ret) {
	kcm_log(0, "Failed to unparse name: %s",
		krb5_get_err_text(context, ret));
	goto out;
    }

    ret = krb5_get_default_in_tkt_etypes(context, &etypes);
    if (ret) {
	kcm_log(0, "Failed to determine default encryption types: %s",
		krb5_get_err_text(context, ret));
	goto out;
    }

    /* Generate a random password (there is no set keys protocol) */
    generate_random_pw(context, newpw, sizeof(newpw));

    /* Change it */
    ret = change_pw(context, ccache, cpn, newpw);
    if (ret)
	goto out;

    /* Do an AS-REQ to determine salt and key version number */
    ret = get_salt_and_kvno(context, ccache, etypes, cpn, newpw,
			    &salt, &kvno);
    if (ret) {
	kcm_log(0, "Failed to determine salting principal for principal %s: %s",
		cpn, krb5_get_err_text(context, ret));
	goto out;
    }

    /* Add canonical name */
    ret = update_keytab_entries(context, ccache, etypes, cpn,
				NULL, newpw, salt, kvno);
    if (ret)
	goto out;

    /* Add SPN aliases, if any */
    spns = krb5_config_get_strings(context, NULL, "kcm",
				   "system_ccache", "spn_aliases", NULL);
    if (spns != NULL) {
	for (i = 0; spns[i] != NULL; i++) {
	    ret = update_keytab_entries(context, ccache, etypes, cpn,
					spns[i], newpw, salt, kvno);
	    if (ret)
		goto out;
	}
    }

    kcm_log(0, "Changed expired password for principal %s in cache %s",
	    cpn, ccache->name);

out:
    if (cpn != NULL)
	free(cpn);
    if (spns != NULL)
	krb5_config_free_strings(spns);
    if (etypes != NULL)
	free(etypes);
    krb5_free_salt(context, salt);
    memset(newpw, 0, sizeof(newpw));

    return ret;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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(&reg_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;
}
Esempio n. 21
0
krb5_error_code
hdb_generate_key_set(krb5_context context, krb5_principal principal,
		     Key **ret_key_set, size_t *nkeyset, int no_salt)
{
    char **ktypes, **kp;
    krb5_error_code ret;
    Key *k, *key_set;
    size_t i, j;
    static const char *default_keytypes[] = {
	"aes256-cts-hmac-sha1-96:pw-salt",
	"des3-cbc-sha1:pw-salt",
	"arcfour-hmac-md5:pw-salt",
	NULL
    };

    ktypes = krb5_config_get_strings(context, NULL, "kadmin",
				     "default_keys", NULL);
    if (ktypes == NULL)
	ktypes = (char **)(intptr_t)default_keytypes;

    *ret_key_set = key_set = NULL;
    *nkeyset = 0;

    ret = 0;

    for(kp = ktypes; kp && *kp; kp++) {
	const char *p;
	krb5_salt salt;
	krb5_enctype *enctypes;
	size_t num_enctypes;

	p = *kp;
	/* check alias */
	if(strcmp(p, "v5") == 0)
	    p = "pw-salt";
	else if(strcmp(p, "v4") == 0)
	    p = "des:pw-salt:";
	else if(strcmp(p, "afs") == 0 || strcmp(p, "afs3") == 0)
	    p = "des:afs3-salt";
	else if (strcmp(p, "arcfour-hmac-md5") == 0)
	    p = "arcfour-hmac-md5:pw-salt";

	memset(&salt, 0, sizeof(salt));

	ret = parse_key_set(context, p,
			    &enctypes, &num_enctypes, &salt, principal);
	if (ret) {
	    krb5_warn(context, ret, "bad value for default_keys `%s'", *kp);
	    ret = 0;
	    continue;
	}

	for (i = 0; i < num_enctypes; i++) {
	    /* find duplicates */
	    for (j = 0; j < *nkeyset; j++) {

		k = &key_set[j];

		if (k->key.keytype == enctypes[i]) {
		    if (no_salt)
			break;
		    if (k->salt == NULL && salt.salttype == KRB5_PW_SALT)
			break;
		    if (k->salt->type == salt.salttype &&
			k->salt->salt.length == salt.saltvalue.length &&
			memcmp(k->salt->salt.data, salt.saltvalue.data,
			       salt.saltvalue.length) == 0)
			break;
		}
	    }
	    /* not a duplicate, lets add it */
	    if (j == *nkeyset) {
		ret = add_enctype_to_key_set(&key_set, nkeyset, enctypes[i],
					     no_salt ? NULL : &salt);
		if (ret) {
		    free(enctypes);
		    krb5_free_salt(context, salt);
		    goto out;
		}
	    }
	}
	free(enctypes);
	krb5_free_salt(context, salt);
    }

    *ret_key_set = key_set;

 out:
    if (ktypes != (char **)(intptr_t)default_keytypes)
	krb5_config_free_strings(ktypes);

    if (ret) {
	krb5_warn(context, ret,
		  "failed to parse the [kadmin]default_keys values");

	for (i = 0; i < *nkeyset; i++)
	    free_Key(&key_set[i]);
	free(key_set);
    } else if (*nkeyset == 0) {
	krb5_warnx(context,
		   "failed to parse any of the [kadmin]default_keys values");
	ret = EINVAL; /* XXX */
    }

    return ret;
}
Esempio n. 22
0
static krb5_error_code
load_plugins(krb5_context context)
{
    struct plugin *e;
    krb5_error_code ret;
    char **dirs = NULL, **di;
    struct dirent *entry;
    char *path;
    DIR *d = NULL;

    if (!plugins_needs_scan)
	return 0;
    plugins_needs_scan = 0;

#ifdef HAVE_DLOPEN

    dirs = krb5_config_get_strings(context, NULL, "libdefaults",
				   "plugin_dir", NULL);
    if (dirs == NULL)
	dirs = rk_UNCONST(sysplugin_dirs);

    for (di = dirs; *di != NULL; di++) {
        char * dir = *di;

#ifdef KRB5_USE_PATH_TOKENS
        if (_krb5_expand_path_tokens(context, *di, &dir))
            goto next_dir;
#endif

        trim_trailing_slash(dir);

        d = opendir(dir);

	if (d == NULL)
	    goto next_dir;

	rk_cloexec_dir(d);

	while ((entry = readdir(d)) != NULL) {
	    char *n = entry->d_name;

	    /* skip . and .. */
            if (!is_valid_plugin_filename(n))
		continue;

	    path = NULL;
	    ret = 0;
#ifdef __APPLE__
	    { /* support loading bundles on MacOS */
		size_t len = strlen(n);
		if (len > 7 && strcmp(&n[len - 7],  ".bundle") == 0)
		    ret = asprintf(&path, "%s/%s/Contents/MacOS/%.*s", dir, n, (int)(len - 7), n);
	    }
#endif
	    if (ret < 0 || path == NULL)
		ret = asprintf(&path, "%s/%s", dir, n);

	    if (ret < 0 || path == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "malloc: out of memory");
		return ret;
	    }

	    /* check if already tried */
	    for (e = registered; e != NULL; e = e->next)
		if (e->type == DSO && strcmp(e->u.dso.path, path) == 0)
		    break;
	    if (e) {
		free(path);
	    } else {
		loadlib(context, path); /* store or frees path */
	    }
	}
	closedir(d);

    next_dir:
        if (dir != *di)
            free(dir);
    }
    if (dirs != rk_UNCONST(sysplugin_dirs))
	krb5_config_free_strings(dirs);
#endif /* HAVE_DLOPEN */
    return 0;
}
Esempio n. 23
0
/**
 * Map a principal name to a local username.
 *
 * Returns 0 on success, KRB5_NO_LOCALNAME if no mapping was found, or
 * some Kerberos or system error.
 *
 * Inputs:
 *
 * @param context    A krb5_context
 * @param aname      A principal name
 * @param lnsize     The size of the buffer into which the username will be written
 * @param lname      The buffer into which the username will be written
 *
 * @ingroup krb5_support
 */
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_aname_to_localname(krb5_context context,
			krb5_const_principal aname,
			size_t lnsize,
			char *lname)
{
    static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT;
    krb5_error_code ret;
    size_t i;
    char **rules = NULL;
    char *rule;

    if (lnsize)
	lname[0] = '\0';

    heim_base_once_f(&reg_def_plugins, context, reg_def_plugins_once);

    /* Try MIT's auth_to_local_names config first */
    ret = an2ln_local_names(context, aname, lnsize, lname);
    if (ret != KRB5_PLUGIN_NO_HANDLE)
	return ret;

    rules = krb5_config_get_strings(context, NULL, "realms", aname->realm,
				    "auth_to_local", NULL);
    if (!rules) {
	/* Heimdal's default rule */
	ret = an2ln_default(context, "HEIMDAL_DEFAULT", aname, lnsize, lname);
	if (ret == KRB5_PLUGIN_NO_HANDLE)
	    return KRB5_NO_LOCALNAME;
	return ret;
    }

    /*
     * MIT rules.
     *
     * Note that RULEs and DBs only have white-list functionality,
     * thus RULEs and DBs that we don't understand we simply ignore.
     *
     * This means that plugins that implement black-lists are
     * dangerous: if a black-list plugin isn't found, the black-list
     * won't be enforced.  But black-lists are dangerous anyways.
     */
    for (ret = KRB5_PLUGIN_NO_HANDLE, i = 0; rules[i]; i++) {
	rule = rules[i];

	/* Try NONE, DEFAULT, and HEIMDAL_DEFAULT rules */
	ret = an2ln_default(context, rule, aname, lnsize, lname);
	if (ret == KRB5_PLUGIN_NO_HANDLE)
	    /* Try DB, RULE, ... plugins */
	    ret = an2ln_plugin(context, rule, aname, lnsize, lname);

	if (ret == 0 && lnsize && !lname[0])
	    continue; /* Success but no lname?!  lies! */
	else if (ret != KRB5_PLUGIN_NO_HANDLE)
	    break;
    }

    if (ret == KRB5_PLUGIN_NO_HANDLE) {
	if (lnsize)
	    lname[0] = '\0';
	ret = KRB5_NO_LOCALNAME;
    }

    krb5_config_free_strings(rules);
    return ret;
}