static int dns_find_realm(krb5_context context, const char *domain, krb5_realm **realms) { static char *default_labels[] = { "_kerberos", NULL }; char dom[MAXHOSTNAMELEN]; struct dns_reply *r; char **labels; int i, ret; labels = krb5_config_get_strings(context, NULL, "libdefaults", "dns_lookup_realm_labels", NULL); if(labels == NULL) 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 || ret >= sizeof(dom)) return -1; r = dns_lookup(dom, "TXT"); if(r != NULL) { ret = copy_txt_to_realms (r->head, realms); dns_free_data(r); if(ret == 0) return 0; } } return -1; }
static krb5_error_code srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, const char *realm, const char *dns_type, const char *proto, const char *service, int port) { char domain[1024]; struct dns_reply *r; struct resource_record *rr; int num_srv; int proto_num; int def_port; *res = NULL; *count = 0; proto_num = string_to_proto(proto); if(proto_num < 0) { krb5_set_error_string(context, "unknown protocol `%s'", proto); return EINVAL; } if(proto_num == KRB5_KRBHST_HTTP) def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80)); else if(port == 0) def_port = ntohs(krb5_getportbyname (context, service, proto, 88)); else def_port = port; snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm); r = dns_lookup(domain, dns_type); if(r == NULL) return KRB5_KDC_UNREACH; for(num_srv = 0, rr = r->head; rr; rr = rr->next) if(rr->type == T_SRV) num_srv++; *res = malloc(num_srv * sizeof(**res)); if(*res == NULL) { dns_free_data(r); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } dns_srv_order(r); for(num_srv = 0, rr = r->head; rr; rr = rr->next) if(rr->type == T_SRV) { krb5_krbhst_info *hi; size_t len = strlen(rr->u.srv->target); hi = calloc(1, sizeof(*hi) + len); if(hi == NULL) { dns_free_data(r); while(--num_srv >= 0) free((*res)[num_srv]); free(*res); *res = NULL; return ENOMEM; } (*res)[num_srv++] = hi; hi->proto = proto_num; hi->def_port = def_port; if (port != 0) hi->port = port; else hi->port = rr->u.srv->port; strlcpy(hi->hostname, rr->u.srv->target, len + 1); } *count = num_srv; dns_free_data(r); return 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; }