Beispiel #1
0
/*
 * Build a tree given a set of profile values retrieved by
 * walk_rtree_capath_vals().
 */
static krb5_error_code
rtree_capath_tree(
    krb5_context context,
    const krb5_data *client,
    const krb5_data *server,
    char **vals,
    krb5_principal **rettree)
{
    krb5_error_code retval = 0;
    unsigned int nvals, nlinks, nprincs, i;
    krb5_data srcrealm, dstrealm;
    krb5_principal *tree, *pprinc;

    *rettree = NULL;
    tree = pprinc = NULL;
    for (nvals = 0; vals[nvals] != NULL; nvals++)
	;
    if (vals[0] != NULL && *vals[0] == '.') {
	nlinks = 0;
    } else {
	nlinks = nvals;
    }
    nprincs = nlinks + 2;
    tree = calloc(nprincs + 1, sizeof(krb5_principal));
    if (tree == NULL) {
	retval = ENOMEM;
	goto error;
    }
    for (i = 0; i < nprincs + 1; i++)
	tree[i] = NULL;
    /* Invariant: PPRINC points one past end of list. */
    pprinc = &tree[0];
    /* Local TGS name */
    retval = krb5_tgtname(context, client, client, pprinc++);
    if (retval) goto error;
    srcrealm = *client;
    for (i = 0; i < nlinks; i++) {
	dstrealm.data = vals[i];
	dstrealm.length = strcspn(vals[i], "\t ");
	retval = krb5_tgtname(context, &dstrealm, &srcrealm, pprinc++);
	if (retval) goto error;
	srcrealm = dstrealm;
    }
    retval = krb5_tgtname(context, server, &srcrealm, pprinc++);
    if (retval) goto error;
    *rettree = tree;

error:
    profile_free_list(vals);
    if (retval) {
	while (pprinc != NULL && pprinc > &tree[0]) {
	    /* krb5_free_principal() correctly handles null input */
	    krb5_free_principal(context, *--pprinc);
	    *pprinc = NULL;
	}
	free(tree);
    }
    return retval;
}
Beispiel #2
0
/* Ensure that a plugin interface is configured.  id must be valid. */
static krb5_error_code
configure_interface(krb5_context context, int id)
{
    krb5_error_code ret;
    struct plugin_interface *interface = &context->plugins[id];
    char **modstrs = NULL, **enable = NULL, **disable = NULL;

    if (interface->configured)
        return 0;

    /* Detect consistency errors when plugin interfaces are added. */
    assert(sizeof(interface_names) / sizeof(*interface_names) ==
           PLUGIN_NUM_INTERFACES);

    /* Get profile variables for this interface. */
    ret = get_profile_var(context, id, KRB5_CONF_MODULE, &modstrs);
    if (ret)
        goto cleanup;
    ret = get_profile_var(context, id, KRB5_CONF_DISABLE, &disable);
    if (ret)
        goto cleanup;
    ret = get_profile_var(context, id, KRB5_CONF_ENABLE_ONLY, &enable);
    if (ret)
        goto cleanup;

    /* Create the full list of dynamic and built-in modules. */
    if (modstrs != NULL) {
        ret = make_full_list(context, modstrs, &interface->modules);
        if (ret)
            goto cleanup;
    }

    /* Remove disabled modules. */
    if (disable != NULL)
        remove_disabled_modules(interface->modules, disable);

    /* Filter and re-order the list according to enable-modules. */
    if (enable != NULL)
        filter_enabled_modules(interface->modules, enable);

cleanup:
    profile_free_list(modstrs);
    profile_free_list(enable);
    profile_free_list(disable);
    return ret;
}
Beispiel #3
0
bool sss_krb5_realm_has_proxy(const char *realm)
{
    krb5_context context = NULL;
    krb5_error_code kerr;
    struct _profile_t *profile = NULL;
    const char  *profile_path[4] = {"realms", NULL, "kdc", NULL};
    char **list = NULL;
    bool res = false;
    size_t c;

    if (realm == NULL) {
        return false;
    }

    kerr = krb5_init_context(&context);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_init_context failed.\n");
        return false;
    }

    kerr = krb5_get_profile(context, &profile);
    if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "krb5_get_profile failed.\n");
        goto done;
    }

    profile_path[1] = realm;

    kerr = profile_get_values(profile, profile_path, &list);
    if (kerr == PROF_NO_RELATION || kerr == PROF_NO_SECTION) {
        kerr = 0;
        goto done;
    } else if (kerr != 0) {
        DEBUG(SSSDBG_OP_FAILURE, "profile_get_values failed.\n");
        goto done;
    }

    for (c = 0; list[c] != NULL; c++) {
        if (strncasecmp(KDC_PROXY_INDICATOR, list[c],
                        KDC_PROXY_INDICATOR_LEN) == 0) {
            DEBUG(SSSDBG_TRACE_ALL,
                  "Found KDC Proxy indicator [%s] in [%s].\n",
                  KDC_PROXY_INDICATOR, list[c]);
            res = true;
            break;
        }
    }

done:
    profile_free_list(list);
    profile_release(profile);
    krb5_free_context(context);

    return res;
}
krb5_error_code
pkinit_libdefault_string(krb5_context context, const krb5_data *realm,
			 const char *option, char **ret_value)
{
    krb5_error_code retval;
    char **values = NULL;

    retval = pkinit_libdefault_strings(context, realm, option, &values);
    if (retval)
	return retval;

    if (values[0] == NULL) {
	retval = ENOENT;
    } else {
	*ret_value = strdup(values[0]);
	if (*ret_value == NULL)
	    retval = ENOMEM;
    }

    profile_free_list(values);
    return retval;
}
Beispiel #5
0
/* Set up conn->http.tls.  Return true on success. */
static krb5_boolean
setup_tls(krb5_context context, const krb5_data *realm,
          struct conn_state *conn, struct select_state *selstate)
{
    krb5_error_code ret;
    krb5_boolean ok = FALSE;
    char **anchors = NULL, *realmstr = NULL;
    const char *names[4];

    if (init_tls_vtable(context) != 0 || context->tls->setup == NULL)
        return FALSE;

    realmstr = k5memdup0(realm->data, realm->length, &ret);
    if (realmstr == NULL)
        goto cleanup;

    /* Load the configured anchors. */
    names[0] = KRB5_CONF_REALMS;
    names[1] = realmstr;
    names[2] = KRB5_CONF_HTTP_ANCHORS;
    names[3] = NULL;
    ret = profile_get_values(context->profile, names, &anchors);
    if (ret != 0 && ret != PROF_NO_RELATION)
        goto cleanup;

    if (context->tls->setup(context, conn->fd, conn->http.servername, anchors,
                            &conn->http.tls) != 0) {
        TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(context, &conn->addr);
        goto cleanup;
    }

    ok = TRUE;

cleanup:
    free(realmstr);
    profile_free_list(anchors);
    return ok;
}
Beispiel #6
0
krb5_error_code
krb5int_locate_server (krb5_context context, const krb5_data *realm,
		       struct addrlist *addrlist,
		       enum locate_service_type svc,
		       int socktype, int family)
{
    krb5_error_code code;
    struct addrlist al = ADDRLIST_INIT;
    char **hostlist = NULL;
    struct srv_dns_entry *dns_list_head = NULL;

    *addrlist = al;

    /*
     * Solaris Kerberos (illumos)
     * Allow main programs to override _locate_server()
     */
    code = override_locate_server(context, realm, &al, svc, socktype, family);
    if (code != KRB5_PLUGIN_NO_HANDLE) {
    	if (code == 0) 
	    *addrlist = al;
	else if (al.space)
	    free_list (&al);
	return (code);
    }
    /* Solaris Kerberos (illumos) */

    code = module_locate_server(context, realm, &al, svc, socktype, family);
    Tprintf("module_locate_server returns %d\n", code);
    if (code == KRB5_PLUGIN_NO_HANDLE) {
	/*
	 * We always try the local file before DNS.  Note that there
	 * is no way to indicate "service not available" via the
	 * config file.
	 */
	code = prof_locate_server(context, realm, &hostlist, svc);

	/*
	 * Solaris Kerberos:
	 * If kpasswd_server has not been configured and dns_lookup_kdc -
	 * dns_fallback are not configured then admin_server should
	 * be inferred, per krb5.conf(4).
	 */
	if (code && svc == locate_service_kpasswd &&
	    !maybe_use_dns(context, "dns_lookup_kdc", 0)) {
		code = prof_locate_server(context, realm, &hostlist,
			locate_service_kadmin);
	}

#ifdef KRB5_DNS_LOOKUP
	/*
	 * Solaris Kerberos:
	 * There is no point in trying to locate the KDC in DNS if "realm"
	 * is empty.
	 */
	/* Try DNS for all profile errors?  */
	if (code && !krb5_is_referral_realm(realm)) {
	    krb5_error_code code2;
	    code2 = dns_locate_server(context, realm, &dns_list_head,
				    svc, socktype, family);

	    if (code2 != KRB5_PLUGIN_NO_HANDLE)
		code = code2;
	}
#endif /* KRB5_DNS_LOOKUP */

	/* We could put more heuristics here, like looking up a hostname
	   of "kerberos."+REALM, etc.  */
    }

    if (code != 0) {
	if (al.space)
	    free_list (&al);
	if (hostlist)
	    profile_free_list(hostlist);
	if (dns_list_head)
	    krb5int_free_srv_dns_data(dns_list_head);

	return code;
    }

    /*
     * At this point we have no errors, let's check to see if we have
     * any KDC entries from krb5.conf or DNS.
     */
    if (!hostlist && !dns_list_head) {
	switch(svc) {
	case locate_service_master_kdc:
	    krb5_set_error_message(context,
				KRB5_REALM_CANT_RESOLVE,
				dgettext(TEXT_DOMAIN,
					"Cannot find a master KDC entry in krb5.conf(4) or DNS Service Location records for realm '%.*s'"),
				realm->length, realm->data);
	    break;
	case locate_service_kadmin:
	    krb5_set_error_message(context,
				KRB5_REALM_CANT_RESOLVE,
				dgettext(TEXT_DOMAIN,
					"Cannot find a kadmin KDC entry in krb5.conf(4) or DNS Service Location records for realm '%.*s'"),
				realm->length, realm->data);
	    break;
	case locate_service_kpasswd:
	    krb5_set_error_message(context,
				KRB5_REALM_CANT_RESOLVE,
				dgettext(TEXT_DOMAIN,
					"Cannot find a kpasswd KDC entry in krb5.conf(4) or DNS Service Location records for realm '%.*s'"),
				realm->length, realm->data);
	    break;
	default: 	  /*  locate_service_kdc: */
		krb5_set_error_message(context,
				    KRB5_REALM_CANT_RESOLVE,
				    dgettext(TEXT_DOMAIN,
					    "Cannot find any KDC entries in krb5.conf(4) or DNS Service Location records for realm '%.*s'"),
				    realm->length, realm->data);
			       
	}
	return KRB5_REALM_CANT_RESOLVE;
    }

    /* We have KDC entries, let see if we can get their net addrs. */
    if (hostlist)
	code = prof_hostnames2netaddrs(hostlist, svc,
				    socktype, family, &al);
    else if (dns_list_head)
	code = dns_hostnames2netaddrs(dns_list_head, svc,
				    socktype, family, &al);
    if (code) {
	if (hostlist)
	    profile_free_list(hostlist);
	if (dns_list_head)
	    krb5int_free_srv_dns_data(dns_list_head);
	return code;
    }

    /*
     * Solaris Kerberos:
     * If an entry for _kerberos-master. does not exist (checked for
     * above) but _kpasswd. does then treat that as an entry for the
     * master KDC (but use port 88 not the kpasswd port). MS AD creates
     * kpasswd entries by default in DNS.
     */
    if (!dns_list_head && svc == locate_service_master_kdc &&
	al.naddrs == 0) {

	/* Look for _kpasswd._tcp|udp */
	code = dns_locate_server(context, realm, &dns_list_head,
				locate_service_kpasswd, socktype, family);

	if (code == 0 && dns_list_head) {
	    int i;
	    struct addrinfo *a;

	    code = dns_hostnames2netaddrs(dns_list_head, svc,
					socktype, family, &al);

	    /* Set the port to 88 instead of the kpasswd port */
	    if (code == 0 && al.naddrs > 0) {
		for (i = 0; i < al.naddrs; i++) {
		    if (al.addrs[i].ai->ai_family == AF_INET)
			for (a = al.addrs[i].ai; a != NULL; a = a->ai_next)
			    ((struct sockaddr_in *)a->ai_addr)->sin_port =
				htons(KRB5_DEFAULT_PORT);
				
		    if (al.addrs[i].ai->ai_family == AF_INET6)
			for (a = al.addrs[i].ai; a != NULL; a = a->ai_next)
			     ((struct sockaddr_in6 *)a->ai_addr)->sin6_port =
				    htons(KRB5_DEFAULT_PORT);
		}
	    }
	}
    }

    /* No errors so far, lets see if we have KDC net addrs */
    if (al.naddrs == 0) {
	char *hostlist_str = NULL, *dnslist_str  = NULL;
	if (al.space)
	    free_list (&al);

	if (hostlist) {
	    hostlist_str = hostlist2str(hostlist);
	    krb5_set_error_message(context, KRB5_REALM_CANT_RESOLVE,
				dgettext(TEXT_DOMAIN,
					"Cannot resolve network address for KDCs '%s' specified in krb5.conf(4) for realm %.*s"),
				hostlist_str ? hostlist_str : "unknown",
				realm->length, realm->data);
	    if (hostlist_str)
		free(hostlist_str);
	} else if (dns_list_head) {
	    dnslist_str = dnslist2str(dns_list_head);
	    krb5_set_error_message(context, KRB5_REALM_CANT_RESOLVE,
				dgettext(TEXT_DOMAIN,
					"Cannot resolve network address for KDCs '%s' discovered via DNS Service Location records for realm '%.*s'"),
				dnslist_str ? dnslist_str : "unknown",
				realm->length, realm->data);
	    if (dnslist_str)
		    free(dnslist_str);
	}

	if (hostlist)
	    profile_free_list(hostlist);
	if (dns_list_head)
	    krb5int_free_srv_dns_data(dns_list_head);

	return KRB5_REALM_CANT_RESOLVE;
    }

    if (hostlist)
	    profile_free_list(hostlist);
    if (dns_list_head)
	    krb5int_free_srv_dns_data(dns_list_head);

    *addrlist = al;
    return 0;
}
Beispiel #7
0
static krb5_error_code
kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib)
{
    krb5_error_code status = 0;
    int     ndx;
    void  **vftabl_addrs = NULL;
    /* N.B.: If this is "const" but not "static", the Solaris 10
       native compiler has trouble building the library because of
       absolute relocations needed in read-only section ".rodata".
       When it's static, it goes into ".picdata", which is
       read-write.  */
    static const char *const dbpath_names[] = {
	KDB_MODULE_SECTION, "db_module_dir", NULL,
    };
    const char *filebases[2];
    char **profpath = NULL;
    char **path = NULL;

    filebases[0] = lib_name;
    filebases[1] = NULL;

    if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) {
	initialize_adb_error_table();
	kdb_db2_pol_err_loaded = 1;
    }

    *lib = calloc((size_t) 1, sizeof(**lib));
    if (*lib == NULL) {
	status = ENOMEM;
	goto clean_n_exit;
    }

    status = kdb_init_lib_lock(*lib);
    if (status) {
	goto clean_n_exit;
    }

    strcpy((*lib)->name, lib_name);

    /* Fetch the list of directories specified in the config
       file(s) first.  */
    status = profile_get_values(kcontext->profile, dbpath_names, &profpath);
    if (status != 0 && status != PROF_NO_RELATION)
	goto clean_n_exit;
    ndx = 0;
    if (profpath)
	while (profpath[ndx] != NULL)
	    ndx++;

    path = calloc(ndx + db_dl_n_locations, sizeof (char *));
    if (path == NULL) {
	status = errno;
	goto clean_n_exit;
    }
    if (ndx)
	memcpy(path, profpath, ndx * sizeof(profpath[0]));
    memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *));
    status = 0;
    
    if ((status = krb5int_open_plugin_dirs ((const char **) path, 
                                            filebases, 
                                            &(*lib)->dl_dir_handle, &kcontext->err))) {
        char *err_str = krb5_get_error_message(kcontext, status);
	status = KRB5_KDB_DBTYPE_NOTFOUND;
	krb5_set_error_message (kcontext, status,
				"Unable to find requested database type: %s", err_str);
	krb5_free_error_message (kcontext, err_str);
	goto clean_n_exit;
    }

    if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table",
                                               &vftabl_addrs, &kcontext->err))) {
        char *err_str = krb5_get_error_message(kcontext, status);
        status = KRB5_KDB_DBTYPE_INIT;
        krb5_set_error_message (kcontext, status,
                                "plugin symbol 'kdb_function_table' lookup failed: %s", err_str);
        krb5_free_error_message (kcontext, err_str);
	goto clean_n_exit;
    }

    if (vftabl_addrs[0] == NULL) {
	/* No plugins! */
	status = KRB5_KDB_DBTYPE_NOTFOUND;
	krb5_set_error_message (kcontext, status,
				_("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"),
				lib_name);
	goto clean_n_exit;
    }

    memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl));
    kdb_setup_opt_functions(*lib);
    
    if ((status = (*lib)->vftabl.init_library())) {
        /* ERROR. library not initialized cleanly */
        goto clean_n_exit;
    }    
    
clean_n_exit:
    if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); }
    /* Both of these DTRT with NULL.  */
    profile_free_list(profpath);
    free(path);
    if (status) {
        if (*lib) {
	    kdb_destroy_lib_lock(*lib);
            if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) {
                krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle);
            }
	    free(*lib);
	    *lib = NULL;
	}
    }
    return status;
}
Beispiel #8
0
krb5_error_code KRB5_CALLCONV
krb5_425_conv_principal(krb5_context context, const char *name,
			const char *instance, const char *realm,
			krb5_principal *princ)
{
     const struct krb_convert *p;
     char buf[256];		/* V4 instances are limited to 40 characters */
     krb5_error_code retval;
     char *domain, *cp;
     char **full_name = 0;
     const char *names[5], *names2[2];
     void*	iterator = NULL;
     char** v4realms = NULL;
     char* realm_name = NULL;
     char* dummy_value = NULL;
     
     /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm
        To do that, iterate over all the realms in the config file, looking for a matching 
        v4_realm line */
     names2 [0] = "realms";
     names2 [1] = NULL;
     retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator);
     while (retval == 0) {
     	retval = profile_iterator (&iterator, &realm_name, &dummy_value);
     	if ((retval == 0) && (realm_name != NULL)) {
     		names [0] = "realms";
     		names [1] = realm_name;
     		names [2] = "v4_realm";
     		names [3] = NULL;

     		retval = profile_get_values (context -> profile, names, &v4realms);
     		if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) {
     			realm = realm_name;
     			break;
     		} else if (retval == PROF_NO_RELATION) {
     			/* If it's not found, just keep going */
     			retval = 0;
     		}
     	} else if ((retval == 0) && (realm_name == NULL)) {
     		break;
     	}
	if (v4realms != NULL) {
	        profile_free_list(v4realms);
		v4realms = NULL;
	}
     	if (realm_name != NULL) {
     		profile_release_string (realm_name);
     		realm_name = NULL;
     	}
     	if (dummy_value != NULL) {
     		profile_release_string (dummy_value);
     		dummy_value = NULL;
     	}
     }
     
     if (instance) {
	  if (instance[0] == '\0') {
	       instance = 0;
	       goto not_service;
	  }
	  p = sconv_list;
	  while (1) {
	       if (!p->v4_str)
		    goto not_service;
	       if (!strcmp(p->v4_str, name))
		    break;
	       p++;
	  }
	  name = p->v5_str;
	  if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) {
	      names[0] = "realms";
	      names[1] = realm;
	      names[2] = "v4_instance_convert";
	      names[3] = instance;
	      names[4] = 0;
	      retval = profile_get_values(context->profile, names, &full_name);
	      if (retval == 0 && full_name && full_name[0]) {
		  instance = full_name[0];
	      } else {
		  strncpy(buf, instance, sizeof(buf));
		  buf[sizeof(buf) - 1] = '\0';
		  retval = krb5_get_realm_domain(context, realm, &domain);
		  if (retval)
		      return retval;
		  if (domain) {
		      for (cp = domain; *cp; cp++)
			  if (isupper((unsigned char) (*cp)))
			      *cp = tolower((unsigned char) *cp);
		      strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
		      strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
		      krb5_xfree(domain);
		  }
		  instance = buf;
	      }
	  }
     }
     
not_service:
     retval = krb5_build_principal(context, princ, strlen(realm), realm, name,
				   instance, NULL);
     if (iterator) profile_iterator_free (&iterator);
     if (full_name) profile_free_list(full_name);
     if (v4realms) profile_free_list(v4realms);
     if (realm_name) profile_release_string (realm_name);
     if (dummy_value) profile_release_string (dummy_value);
     return retval;
}
Beispiel #9
0
static krb5_error_code
locate_srv_conf_1(krb5_context context, const krb5_data *realm,
                  const char * name, struct serverlist *serverlist,
                  int socktype, int udpport, int sec_udpport)
{
    const char  *realm_srv_names[4];
    char **hostlist, *host, *port, *cp;
    krb5_error_code code;
    int i;

    Tprintf ("looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
             realm->data, name, ntohs (udpport), ntohs (sec_udpport));

    if ((host = malloc(realm->length + 1)) == NULL)
        return ENOMEM;

    strncpy(host, realm->data, realm->length);
    host[realm->length] = '\0';
    hostlist = 0;

    realm_srv_names[0] = KRB5_CONF_REALMS;
    realm_srv_names[1] = host;
    realm_srv_names[2] = name;
    realm_srv_names[3] = 0;

    code = profile_get_values(context->profile, realm_srv_names, &hostlist);
    free(host);

    if (code) {
        Tprintf ("config file lookup failed: %s\n",
                 error_message(code));
        if (code == PROF_NO_SECTION || code == PROF_NO_RELATION)
            code = 0;
        return code;
    }

    for (i=0; hostlist[i]; i++) {
        int p1, p2;

        host = hostlist[i];
        Tprintf ("entry %d is '%s'\n", i, host);
        /* Find port number, and strip off any excess characters. */
        if (*host == '[' && (cp = strchr(host, ']')))
            cp = cp + 1;
        else
            cp = host + strcspn(host, " \t:");
        port = (*cp == ':') ? cp + 1 : NULL;
        *cp = '\0';

        if (port) {
            unsigned long l;
#ifdef HAVE_STROUL
            char *endptr;
            l = strtoul (port, &endptr, 10);
            if (endptr == NULL || *endptr != 0)
                return EINVAL;
#else
            l = atoi (port);
#endif
            /* L is unsigned, don't need to check <0.  */
            if (l > 65535)
                return EINVAL;
            p1 = htons (l);
            p2 = 0;
        } else {
            p1 = udpport;
            p2 = sec_udpport;
        }

        /* If the hostname was in brackets, strip those off now. */
        if (*host == '[' && (cp = strchr(host, ']'))) {
            host++;
            *cp = '\0';
        }

        code = add_host_to_list(serverlist, host, p1, socktype, AF_UNSPEC);
        /* Second port is for IPv4 UDP only, and should possibly go away as
         * it was originally a krb4 compatibility measure. */
        if (code == 0 && p2 != 0 &&
            (socktype == 0 || socktype == SOCK_DGRAM))
            code = add_host_to_list(serverlist, host, p2, SOCK_DGRAM, AF_INET);
        if (code)
            goto cleanup;
    }

cleanup:
    profile_free_list(hostlist);
    return code;
}
Beispiel #10
0
krb5_error_code
krb5_get_krbhst(krb5_context context, const krb5_data *realm, char ***hostlist)
{
    char	**values, **cpp, *cp;
    const char	*realm_kdc_names[4];
    krb5_error_code	retval;
    int	i, count;
    char **rethosts;

    rethosts = 0;

    realm_kdc_names[0] = "realms";
    realm_kdc_names[1] = realm->data;
    realm_kdc_names[2] = "kdc";
    realm_kdc_names[3] = 0;

    if (context->profile == 0)
	return KRB5_CONFIG_CANTOPEN;

    retval = profile_get_values(context->profile, realm_kdc_names, &values);
    if (retval == PROF_NO_SECTION)
	return KRB5_REALM_UNKNOWN;
    if (retval == PROF_NO_RELATION)
	return KRB5_CONFIG_BADFORMAT;
    if (retval)
	return retval;

    /*
     * Do cleanup over the list.  We allow for some extra field to be
     * added to the kdc line later (maybe the port number)
     */
    for (cpp = values; *cpp; cpp++) {
	cp = strchr(*cpp, ' ');
	if (cp)
	    *cp = 0;
	cp = strchr(*cpp, '\t');
	if (cp)
	    *cp = 0;
	cp = strchr(*cpp, ':');
	if (cp)
	    *cp = 0;
    }
    count = cpp - values;
    rethosts = malloc(sizeof(char *) * (count + 1));
    if (!rethosts) {
        retval = ENOMEM;
        goto cleanup;
    }
    for (i = 0; i < count; i++) {
	unsigned int len = strlen (values[i]) + 1;
        rethosts[i] = malloc(len);
        if (!rethosts[i]) {
            retval = ENOMEM;
            goto cleanup;
        }
	memcpy (rethosts[i], values[i], len);
    }
    rethosts[count] = 0;
 cleanup:
    if (retval && rethosts) {
        for (cpp = rethosts; *cpp; cpp++)
            free(*cpp);
        free(rethosts);
	rethosts = 0;
    }
    profile_free_list(values);
    *hostlist = rethosts;
    return retval;
}
Beispiel #11
0
static krb5_error_code
locate_srv_conf_1(krb5_context context, const krb5_data *realm,
                  const char * name, struct serverlist *serverlist,
                  k5_transport transport, int udpport)
{
    const char *realm_srv_names[4];
    char **hostlist = NULL, *realmstr = NULL, *host = NULL;
    const char *hostspec;
    krb5_error_code code;
    int i, default_port;

    Tprintf("looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
            realm->data, name, udpport);

    realmstr = k5memdup0(realm->data, realm->length, &code);
    if (realmstr == NULL)
        goto cleanup;

    realm_srv_names[0] = KRB5_CONF_REALMS;
    realm_srv_names[1] = realmstr;
    realm_srv_names[2] = name;
    realm_srv_names[3] = 0;
    code = profile_get_values(context->profile, realm_srv_names, &hostlist);
    if (code) {
        Tprintf("config file lookup failed: %s\n", error_message(code));
        if (code == PROF_NO_SECTION || code == PROF_NO_RELATION)
            code = 0;
        goto cleanup;
    }

    for (i = 0; hostlist[i]; i++) {
        int port_num;
        k5_transport this_transport = transport;
        const char *uri_path = NULL;

        hostspec = hostlist[i];
        Tprintf("entry %d is '%s'\n", i, hostspec);

        parse_uri_if_https(hostspec, &this_transport, &hostspec, &uri_path);

        default_port = (this_transport == HTTPS) ? 443 : udpport;
        code = k5_parse_host_string(hostspec, default_port, &host, &port_num);
        if (code == 0 && host == NULL)
            code = EINVAL;
        if (code)
            goto cleanup;

        code = add_host_to_list(serverlist, host, port_num, this_transport,
                                AF_UNSPEC, uri_path, -1);
        if (code)
            goto cleanup;

        free(host);
        host = NULL;
    }

cleanup:
    free(realmstr);
    free(host);
    profile_free_list(hostlist);
    return code;
}
krb5_error_code
pkinit_cert_matching(krb5_context context,
		     pkinit_plg_crypto_context plg_cryptoctx,
		     pkinit_req_crypto_context req_cryptoctx,
		     pkinit_identity_crypto_context id_cryptoctx,
		     krb5_principal princ)
{

    krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
    int x;
    char **rules = NULL;
    rule_set *rs = NULL;
    int match_found = 0;
    pkinit_cert_matching_data **matchdata = NULL;
    pkinit_cert_matching_data *the_matching_cert = NULL;

    /* If no matching rules, select the default cert and we're done */
    pkinit_libdefault_strings(context, krb5_princ_realm(context, princ),
			      KRB5_CONF_PKINIT_CERT_MATCH, &rules);
    if (rules == NULL) {
	pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__);
	retval = crypto_cert_select_default(context, plg_cryptoctx,
					    req_cryptoctx, id_cryptoctx);
	goto cleanup;
    }

    /* parse each rule line one at a time and check all the certs against it */
    for (x = 0; rules[x] != NULL; x++) {
	pkiDebug("%s: Processing rule '%s'\n", __FUNCTION__, rules[x]);

	/* Free rules from previous time through... */
	if (rs != NULL) {
	    free_rule_set(context, rs);
	    rs = NULL;
	}
	retval = parse_rule_set(context, rules[x], &rs);
	if (retval) {
	    if (retval == EINVAL) {
		pkiDebug("%s: Ignoring invalid rule pkinit_cert_match = '%s'\n",
			 __FUNCTION__, rules[x]); 
		continue;
	    }
	    goto cleanup;
	}

	/*
	 * Optimize so that we do not get cert info unless we have
	 * valid rules to check.  Once obtained, keep it around
	 * until we are done.
	 */
	if (matchdata == NULL) {
	    retval = obtain_all_cert_matching_data(context, plg_cryptoctx,
						   req_cryptoctx, id_cryptoctx,
						   &matchdata);
	    if (retval || matchdata == NULL) {
		pkiDebug("%s: Error %d obtaining certificate information\n",
			 __FUNCTION__, retval);
		retval = ENOENT;
		goto cleanup;
	    }
	}

	retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx,
				 id_cryptoctx, princ, rs, matchdata,
				 &match_found, &the_matching_cert);
	if (retval) {
	    pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
		     __FUNCTION__, retval, rules[x]);
	    goto cleanup;
	}
	if (match_found) {
	    pkiDebug("%s: We have an exact match with rule '%s'\n",
		     __FUNCTION__, rules[x]);
	    break;
	}
    }

    if (match_found && the_matching_cert != NULL) {
	pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__);
	retval = crypto_cert_select(context, the_matching_cert);
	if (retval) {
	    pkiDebug("%s: crypto_cert_select error %d, %s\n",
		     __FUNCTION__, retval, error_message(retval));
	    goto cleanup;
	}
    } else {
	retval = ENOENT;    /* XXX */
	goto cleanup;
    }

    retval = 0;
cleanup:
    if (rules != NULL)
	profile_free_list(rules);
    if (rs != NULL)
	free_rule_set(context, rs);
    if (matchdata != NULL)
	free_all_cert_matching_data(context, matchdata);
    return retval;
}