Пример #1
0
static krb5_error_code
locate_srv_dns_1(const krb5_data *realm, const char *service,
                 const char *protocol, struct serverlist *serverlist)
{
    struct srv_dns_entry *head = NULL, *entry = NULL;
    krb5_error_code code = 0;
    int socktype;

    code = krb5int_make_srv_query_realm(realm, service, protocol, &head);
    if (code)
        return 0;

    if (head == NULL)
        return 0;

    /* Check for the "." case indicating no support.  */
    if (head->next == NULL && head->host[0] == '\0') {
        code = KRB5_ERR_NO_SERVICE;
        goto cleanup;
    }

    for (entry = head; entry != NULL; entry = entry->next) {
        socktype = (strcmp(protocol, "_tcp") == 0) ? SOCK_STREAM : SOCK_DGRAM;
        code = add_host_to_list(serverlist, entry->host, htons(entry->port),
                                socktype, AF_UNSPEC);
        if (code)
            goto cleanup;
    }

cleanup:
    krb5int_free_srv_dns_data(head);
    return code;
}
Пример #2
0
static krb5_error_code
locate_srv_dns_1(krb5_context context, const krb5_data *realm,
                 const char *service, const char *protocol,
                 struct serverlist *serverlist)
{
    struct srv_dns_entry *head = NULL, *entry = NULL;
    krb5_error_code code = 0;
    k5_transport transport;

    code = krb5int_make_srv_query_realm(context, realm, service, protocol,
                                        &head);
    if (code)
        return 0;

    if (head == NULL)
        return 0;

    /* Check for the "." case indicating no support.  */
    if (head->next == NULL && head->host[0] == '\0') {
        code = KRB5_ERR_NO_SERVICE;
        goto cleanup;
    }

    for (entry = head; entry != NULL; entry = entry->next) {
        transport = (strcmp(protocol, "_tcp") == 0) ? TCP : UDP;
        code = add_host_to_list(serverlist, entry->host, entry->port,
                                transport, AF_UNSPEC, NULL, -1);
        if (code)
            goto cleanup;
    }

cleanup:
    krb5int_free_srv_dns_data(head);
    return code;
}
Пример #3
0
/*
 * Collect a list of servers from DNS URI records, for the requested service
 * and transport type.  Problematic entries are skipped.
 */
static krb5_error_code
locate_uri(krb5_context context, const krb5_data *realm,
           const char *req_service, struct serverlist *serverlist,
           k5_transport req_transport, int default_port,
           krb5_boolean master_only)
{
    krb5_error_code ret;
    k5_transport transport, host_trans;
    struct srv_dns_entry *answers, *entry;
    char *host;
    const char *host_field, *path;
    int port, def_port, master;

    ret = k5_make_uri_query(context, realm, req_service, &answers);
    if (ret || answers == NULL)
        return ret;

    for (entry = answers; entry != NULL; entry = entry->next) {
        def_port = default_port;
        path = NULL;

        parse_uri_fields(entry->host, &transport, &host_field, &master);
        if (host_field == NULL)
            continue;

        /* TCP_OR_UDP allows entries of any transport type; otherwise
         * we're asking for a match. */
        if (req_transport != TCP_OR_UDP && req_transport != transport)
            continue;

        /* Process a MS-KKDCP target. */
        if (transport == HTTPS) {
            host_trans = 0;
            def_port = 443;
            parse_uri_if_https(host_field, &host_trans, &host_field, &path);
            if (host_trans != HTTPS)
                continue;
        }

        ret = k5_parse_host_string(host_field, def_port, &host, &port);
        if (ret == ENOMEM)
            break;

        if (ret || host == NULL) {
            ret = 0;
            continue;
        }

        ret = add_host_to_list(serverlist, host, port, transport, AF_UNSPEC,
                               path, master);
        free(host);
        if (ret)
            break;
    }

    krb5int_free_srv_dns_data(answers);
    return ret;
}
Пример #4
0
/* 
 * Solaris Kerberos: for backward compat.  Avoid using this
 * function!
 */
krb5_error_code
krb5_get_servername(krb5_context context,
    const krb5_data *realm,
    const char *name, const char *proto,
    char *srvhost,
    unsigned short *port)
{
    krb5_error_code code = KRB5_REALM_UNKNOWN;

#ifdef KRB5_DNS_LOOKUP
    {
	int use_dns = _krb5_use_dns_kdc(context);

	if (use_dns) {
	    struct srv_dns_entry *head = NULL;

	    code = krb5int_make_srv_query_realm(realm, name, proto, &head);
	    if (code)
		return (code);

	    if (head == NULL)
		return KRB5_REALM_CANT_RESOLVE;

	    *port = head->port;
	    (void) strlcpy(srvhost, head->host, MAX_DNS_NAMELEN);

#ifdef DEBUG
	    fprintf (stderr, "krb5_get_servername svrhost %s, port %d\n",
		srvhost, *port);
#endif
	    krb5int_free_srv_dns_data(head);
	}
    }
#endif /* KRB5_DNS_LOOKUP */

    return (code);
}
Пример #5
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;
}