/* Heimdal */ krb5_error_code smb_krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters) { krb5_krbhst_handle hnd; krb5_krbhst_info *hinfo; krb5_error_code rc; int num_kdcs, i; struct sockaddr *sa; struct addrinfo *ai; *addr_pp = NULL; *naddrs = 0; rc = krb5_krbhst_init(ctx, realm->data, KRB5_KRBHST_KDC, &hnd); if (rc) { DEBUG(0, ("smb_krb5_locate_kdc: krb5_krbhst_init failed (%s)\n", error_message(rc))); return rc; } for ( num_kdcs = 0; (rc = krb5_krbhst_next(ctx, hnd, &hinfo) == 0); num_kdcs++) ; krb5_krbhst_reset(ctx, hnd); if (!num_kdcs) { DEBUG(0, ("smb_krb5_locate_kdc: zero kdcs found !\n")); krb5_krbhst_free(ctx, hnd); return -1; } sa = SMB_MALLOC_ARRAY( struct sockaddr, num_kdcs ); if (!sa) { DEBUG(0, ("smb_krb5_locate_kdc: malloc failed\n")); krb5_krbhst_free(ctx, hnd); naddrs = 0; return -1; } memset(sa, '\0', sizeof(struct sockaddr) * num_kdcs ); for (i = 0; i < num_kdcs && (rc = krb5_krbhst_next(ctx, hnd, &hinfo) == 0); i++) { #if defined(HAVE_KRB5_KRBHST_GET_ADDRINFO) rc = krb5_krbhst_get_addrinfo(ctx, hinfo, &ai); if (rc) { DEBUG(0,("krb5_krbhst_get_addrinfo failed: %s\n", error_message(rc))); continue; } #endif if (hinfo->ai && hinfo->ai->ai_family == AF_INET) memcpy(&sa[i], hinfo->ai->ai_addr, sizeof(struct sockaddr)); } krb5_krbhst_free(ctx, hnd); *naddrs = num_kdcs; *addr_pp = sa; return 0; }
int main(int argc, char **argv) { int i, j; krb5_context context; int types[] = {KRB5_KRBHST_KDC, KRB5_KRBHST_ADMIN, KRB5_KRBHST_CHANGEPW, KRB5_KRBHST_KRB524}; const char *type_str[] = {"kdc", "admin", "changepw", "krb524"}; int optidx = 0; setprogname (argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; krb5_init_context (&context); for(i = 0; i < argc; i++) { krb5_krbhst_handle handle; char host[MAXHOSTNAMELEN]; for (j = 0; j < sizeof(types)/sizeof(*types); ++j) { printf ("%s for %s:\n", type_str[j], argv[i]); krb5_krbhst_init(context, argv[i], types[j], &handle); while(krb5_krbhst_next_as_string(context, handle, host, sizeof(host)) == 0) printf("\thost: %s\n", host); krb5_krbhst_reset(context, handle); printf ("\n"); } } return 0; }
static krb5_error_code gethostlist(krb5_context context, const char *realm, unsigned int type, char ***hostlist) { krb5_error_code ret; int nhost = 0; krb5_krbhst_handle handle; char host[MAXHOSTNAMELEN]; krb5_krbhst_info *hostinfo; ret = krb5_krbhst_init(context, realm, type, &handle); if (ret) return ret; while(krb5_krbhst_next(context, handle, &hostinfo) == 0) nhost++; if(nhost == 0) { krb5_set_error_message(context, KRB5_KDC_UNREACH, N_("No KDC found for realm %s", ""), realm); return KRB5_KDC_UNREACH; } *hostlist = calloc(nhost + 1, sizeof(**hostlist)); if(*hostlist == NULL) { krb5_krbhst_free(context, handle); return ENOMEM; } krb5_krbhst_reset(context, handle); nhost = 0; while(krb5_krbhst_next_as_string(context, handle, host, sizeof(host)) == 0) { if(((*hostlist)[nhost++] = strdup(host)) == NULL) { krb5_free_krbhst(context, *hostlist); krb5_krbhst_free(context, handle); return ENOMEM; } } (*hostlist)[nhost] = NULL; krb5_krbhst_free(context, handle); return 0; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendto (krb5_context context, const krb5_data *send_data, krb5_krbhst_handle handle, krb5_data *receive) { krb5_error_code ret; krb5_socket_t fd; size_t i; krb5_data_zero(receive); for (i = 0; i < context->max_retries; ++i) { krb5_krbhst_info *hi; while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; _krb5_debug(context, 2, "trying to communicate with host %s in realm %s", hi->hostname, _krb5_krbhst_get_realm(handle)); if (context->send_to_kdc) { struct send_to_kdc *s = context->send_to_kdc; ret = (*s->func)(context, s->data, hi, context->kdc_timeout, send_data, receive); if (ret == 0 && receive->length != 0) goto out; continue; } ret = send_via_plugin(context, hi, context->kdc_timeout, send_data, receive); if (ret == 0 && receive->length != 0) goto out; else if (ret != KRB5_PLUGIN_NO_HANDLE) continue; if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { if (send_via_proxy (context, hi, send_data, receive) == 0) { ret = 0; goto out; } continue; } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); if (ret) continue; for (a = ai; a != NULL; a = a->ai_next) { fd = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (rk_IS_BAD_SOCKET(fd)) continue; rk_cloexec(fd); if (timed_connect (fd, a, context->kdc_timeout) < 0) { rk_closesocket (fd); continue; } switch (hi->proto) { case KRB5_KRBHST_HTTP : ret = send_and_recv_http(fd, context->kdc_timeout, "", send_data, receive); break; case KRB5_KRBHST_TCP : ret = send_and_recv_tcp (fd, context->kdc_timeout, send_data, receive); break; case KRB5_KRBHST_UDP : ret = send_and_recv_udp (fd, context->kdc_timeout, send_data, receive); break; } rk_closesocket (fd); if(ret == 0 && receive->length != 0) goto out; } } krb5_krbhst_reset(context, handle); } krb5_clear_error_message (context); ret = KRB5_KDC_UNREACH; out: _krb5_debug(context, 2, "result of trying to talk to realm %s = %d", _krb5_krbhst_get_realm(handle), ret); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_sendto (krb5_context context, const krb5_data *send_data, krb5_krbhst_handle handle, krb5_data *receive) { krb5_error_code ret; int fd; int i; krb5_data_zero(receive); for (i = 0; i < context->max_retries; ++i) { krb5_krbhst_info *hi; while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; if (context->send_to_kdc) { struct send_to_kdc *s = context->send_to_kdc; ret = (*s->func)(context, s->data, hi, send_data, receive); if (ret == 0 && receive->length != 0) goto out; continue; } if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { if (send_via_proxy (context, hi, send_data, receive) == 0) { ret = 0; goto out; } continue; } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); if (ret) continue; for (a = ai; a != NULL; a = a->ai_next) { fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (fd < 0) continue; if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) { close (fd); continue; } switch (hi->proto) { case KRB5_KRBHST_HTTP : ret = send_and_recv_http(fd, context->kdc_timeout, "", send_data, receive); break; case KRB5_KRBHST_TCP : ret = send_and_recv_tcp (fd, context->kdc_timeout, send_data, receive); break; case KRB5_KRBHST_UDP : ret = send_and_recv_udp (fd, context->kdc_timeout, send_data, receive); break; } close (fd); if(ret == 0 && receive->length != 0) goto out; } } krb5_krbhst_reset(context, handle); } krb5_clear_error_string (context); ret = KRB5_KDC_UNREACH; out: return ret; }