static int send_via_proxy (krb5_context context, const krb5_krbhst_info *hi, const krb5_data *send_data, krb5_data *receive) { char *proxy2 = strdup(context->http_proxy); char *proxy = proxy2; char *prefix = NULL; char *colon; struct addrinfo hints; struct addrinfo *ai, *a; int ret; krb5_socket_t s = rk_INVALID_SOCKET; char portstr[NI_MAXSERV]; if (proxy == NULL) return ENOMEM; if (strncmp (proxy, "http://", 7) == 0) proxy += 7; colon = strchr(proxy, ':'); if(colon != NULL) *colon++ = '\0'; memset (&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf (portstr, sizeof(portstr), "%d", ntohs(init_port (colon, htons(80)))); ret = getaddrinfo (proxy, portstr, &hints, &ai); free (proxy2); if (ret) return krb5_eai_to_heim_errno(ret, errno); for (a = ai; a != NULL; a = a->ai_next) { s = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (s < 0) continue; rk_cloexec(s); if (timed_connect (s, a, context->kdc_timeout) < 0) { rk_closesocket (s); continue; } break; } if (a == NULL) { freeaddrinfo (ai); return 1; } freeaddrinfo (ai); ret = asprintf(&prefix, "http://%s/", hi->hostname); if(ret < 0 || prefix == NULL) { close(s); return 1; } ret = send_and_recv_http(s, context->kdc_timeout, prefix, send_data, receive); rk_closesocket (s); free(prefix); if(ret == 0 && receive->length != 0) return 0; return 1; }
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; }