1b528cefcSMark Murray /* 2adb0ddaeSAssar Westerlund * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36adb0ddaeSAssar Westerlund RCSID("$Id: send_to_kdc.c,v 1.44 2001/05/14 22:49:56 assar Exp $"); 37b528cefcSMark Murray 38b528cefcSMark Murray /* 39b528cefcSMark Murray * send the data in `req' on the socket `fd' (which is datagram iff udp) 40b528cefcSMark Murray * waiting `tmout' for a reply and returning the reply in `rep'. 41b528cefcSMark Murray * iff limit read up to this many bytes 42b528cefcSMark Murray * returns 0 and data in `rep' if succesful, otherwise -1 43b528cefcSMark Murray */ 44b528cefcSMark Murray 45b528cefcSMark Murray static int 46b528cefcSMark Murray recv_loop (int fd, 47b528cefcSMark Murray time_t tmout, 48b528cefcSMark Murray int udp, 49b528cefcSMark Murray size_t limit, 50b528cefcSMark Murray krb5_data *rep) 51b528cefcSMark Murray { 52b528cefcSMark Murray fd_set fdset; 53b528cefcSMark Murray struct timeval timeout; 54b528cefcSMark Murray int ret; 55b528cefcSMark Murray int nbytes; 56b528cefcSMark Murray 575e9cd1aeSAssar Westerlund if (fd >= FD_SETSIZE) { 585e9cd1aeSAssar Westerlund return -1; 595e9cd1aeSAssar Westerlund } 605e9cd1aeSAssar Westerlund 61b528cefcSMark Murray krb5_data_zero(rep); 62b528cefcSMark Murray do { 63b528cefcSMark Murray FD_ZERO(&fdset); 64b528cefcSMark Murray FD_SET(fd, &fdset); 65b528cefcSMark Murray timeout.tv_sec = tmout; 66b528cefcSMark Murray timeout.tv_usec = 0; 67b528cefcSMark Murray ret = select (fd + 1, &fdset, NULL, NULL, &timeout); 68b528cefcSMark Murray if (ret < 0) { 69b528cefcSMark Murray if (errno == EINTR) 70b528cefcSMark Murray continue; 71b528cefcSMark Murray return -1; 72b528cefcSMark Murray } else if (ret == 0) { 73b528cefcSMark Murray return 0; 74b528cefcSMark Murray } else { 75b528cefcSMark Murray void *tmp; 76b528cefcSMark Murray 77b528cefcSMark Murray if (ioctl (fd, FIONREAD, &nbytes) < 0) { 78b528cefcSMark Murray krb5_data_free (rep); 79b528cefcSMark Murray return -1; 80b528cefcSMark Murray } 81b528cefcSMark Murray if(nbytes == 0) 82b528cefcSMark Murray return 0; 83b528cefcSMark Murray 84b528cefcSMark Murray if (limit) 85b528cefcSMark Murray nbytes = min(nbytes, limit - rep->length); 86b528cefcSMark Murray 87b528cefcSMark Murray tmp = realloc (rep->data, rep->length + nbytes); 88b528cefcSMark Murray if (tmp == NULL) { 89b528cefcSMark Murray krb5_data_free (rep); 90b528cefcSMark Murray return -1; 91b528cefcSMark Murray } 92b528cefcSMark Murray rep->data = tmp; 93b528cefcSMark Murray ret = recv (fd, (char*)tmp + rep->length, nbytes, 0); 94b528cefcSMark Murray if (ret < 0) { 95b528cefcSMark Murray krb5_data_free (rep); 96b528cefcSMark Murray return -1; 97b528cefcSMark Murray } 98b528cefcSMark Murray rep->length += ret; 99b528cefcSMark Murray } 100b528cefcSMark Murray } while(!udp && (limit == 0 || rep->length < limit)); 101b528cefcSMark Murray return 0; 102b528cefcSMark Murray } 103b528cefcSMark Murray 104b528cefcSMark Murray /* 105b528cefcSMark Murray * Send kerberos requests and receive a reply on a udp or any other kind 106b528cefcSMark Murray * of a datagram socket. See `recv_loop'. 107b528cefcSMark Murray */ 108b528cefcSMark Murray 109b528cefcSMark Murray static int 110b528cefcSMark Murray send_and_recv_udp(int fd, 111b528cefcSMark Murray time_t tmout, 112b528cefcSMark Murray const krb5_data *req, 113b528cefcSMark Murray krb5_data *rep) 114b528cefcSMark Murray { 115b528cefcSMark Murray if (send (fd, req->data, req->length, 0) < 0) 116b528cefcSMark Murray return -1; 117b528cefcSMark Murray 118b528cefcSMark Murray return recv_loop(fd, tmout, 1, 0, rep); 119b528cefcSMark Murray } 120b528cefcSMark Murray 121b528cefcSMark Murray /* 122b528cefcSMark Murray * `send_and_recv' for a TCP (or any other stream) socket. 123b528cefcSMark Murray * Since there are no record limits on a stream socket the protocol here 124b528cefcSMark Murray * is to prepend the request with 4 bytes of its length and the reply 125b528cefcSMark Murray * is similarly encoded. 126b528cefcSMark Murray */ 127b528cefcSMark Murray 128b528cefcSMark Murray static int 129b528cefcSMark Murray send_and_recv_tcp(int fd, 130b528cefcSMark Murray time_t tmout, 131b528cefcSMark Murray const krb5_data *req, 132b528cefcSMark Murray krb5_data *rep) 133b528cefcSMark Murray { 134b528cefcSMark Murray unsigned char len[4]; 135b528cefcSMark Murray unsigned long rep_len; 136b528cefcSMark Murray krb5_data len_data; 137b528cefcSMark Murray 138b528cefcSMark Murray _krb5_put_int(len, req->length, 4); 139b528cefcSMark Murray if(net_write(fd, len, sizeof(len)) < 0) 140b528cefcSMark Murray return -1; 141b528cefcSMark Murray if(net_write(fd, req->data, req->length) < 0) 142b528cefcSMark Murray return -1; 143b528cefcSMark Murray if (recv_loop (fd, tmout, 0, 4, &len_data) < 0) 144b528cefcSMark Murray return -1; 145b528cefcSMark Murray if (len_data.length != 4) { 146b528cefcSMark Murray krb5_data_free (&len_data); 147b528cefcSMark Murray return -1; 148b528cefcSMark Murray } 149b528cefcSMark Murray _krb5_get_int(len_data.data, &rep_len, 4); 150b528cefcSMark Murray krb5_data_free (&len_data); 151b528cefcSMark Murray if (recv_loop (fd, tmout, 0, rep_len, rep) < 0) 152b528cefcSMark Murray return -1; 153b528cefcSMark Murray if(rep->length != rep_len) { 154b528cefcSMark Murray krb5_data_free (rep); 155b528cefcSMark Murray return -1; 156b528cefcSMark Murray } 157b528cefcSMark Murray return 0; 158b528cefcSMark Murray } 159b528cefcSMark Murray 160b528cefcSMark Murray /* 161b528cefcSMark Murray * `send_and_recv' tailored for the HTTP protocol. 162b528cefcSMark Murray */ 163b528cefcSMark Murray 164b528cefcSMark Murray static int 165b528cefcSMark Murray send_and_recv_http(int fd, 166b528cefcSMark Murray time_t tmout, 167b528cefcSMark Murray const char *prefix, 168b528cefcSMark Murray const krb5_data *req, 169b528cefcSMark Murray krb5_data *rep) 170b528cefcSMark Murray { 171b528cefcSMark Murray char *request; 172b528cefcSMark Murray char *str; 173b528cefcSMark Murray int ret; 174b528cefcSMark Murray int len = base64_encode(req->data, req->length, &str); 175b528cefcSMark Murray 176b528cefcSMark Murray if(len < 0) 177b528cefcSMark Murray return -1; 178b528cefcSMark Murray asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str); 179b528cefcSMark Murray free(str); 180b528cefcSMark Murray if (request == NULL) 181b528cefcSMark Murray return -1; 182b528cefcSMark Murray ret = net_write (fd, request, strlen(request)); 183b528cefcSMark Murray free (request); 184b528cefcSMark Murray if (ret < 0) 185b528cefcSMark Murray return ret; 186b528cefcSMark Murray ret = recv_loop(fd, tmout, 0, 0, rep); 187b528cefcSMark Murray if(ret) 188b528cefcSMark Murray return ret; 189b528cefcSMark Murray { 190b528cefcSMark Murray unsigned long rep_len; 191b528cefcSMark Murray char *s, *p; 192b528cefcSMark Murray 193b528cefcSMark Murray s = realloc(rep->data, rep->length + 1); 194b528cefcSMark Murray if (s == NULL) { 195b528cefcSMark Murray krb5_data_free (rep); 196b528cefcSMark Murray return -1; 197b528cefcSMark Murray } 198b528cefcSMark Murray s[rep->length] = 0; 199b528cefcSMark Murray p = strstr(s, "\r\n\r\n"); 200b528cefcSMark Murray if(p == NULL) { 201b528cefcSMark Murray free(s); 202b528cefcSMark Murray return -1; 203b528cefcSMark Murray } 204b528cefcSMark Murray p += 4; 205b528cefcSMark Murray rep->data = s; 206b528cefcSMark Murray rep->length -= p - s; 207b528cefcSMark Murray if(rep->length < 4) { /* remove length */ 208b528cefcSMark Murray free(s); 209b528cefcSMark Murray return -1; 210b528cefcSMark Murray } 211b528cefcSMark Murray rep->length -= 4; 212b528cefcSMark Murray _krb5_get_int(p, &rep_len, 4); 213b528cefcSMark Murray if (rep_len != rep->length) { 214b528cefcSMark Murray free(s); 215b528cefcSMark Murray return -1; 216b528cefcSMark Murray } 217b528cefcSMark Murray memmove(rep->data, p + 4, rep->length); 218b528cefcSMark Murray } 219b528cefcSMark Murray return 0; 220b528cefcSMark Murray } 221b528cefcSMark Murray 222b528cefcSMark Murray static int 223b528cefcSMark Murray init_port(const char *s, int fallback) 224b528cefcSMark Murray { 225b528cefcSMark Murray if (s) { 226b528cefcSMark Murray int tmp; 227b528cefcSMark Murray 228b528cefcSMark Murray sscanf (s, "%d", &tmp); 229b528cefcSMark Murray return htons(tmp); 230b528cefcSMark Murray } else 231b528cefcSMark Murray return fallback; 232b528cefcSMark Murray } 233b528cefcSMark Murray 234b528cefcSMark Murray /* 235b528cefcSMark Murray * Return 0 if succesful, otherwise 1 236b528cefcSMark Murray */ 237b528cefcSMark Murray 238b528cefcSMark Murray static int 239b528cefcSMark Murray send_via_proxy (krb5_context context, 240b528cefcSMark Murray const char *hostname, 241b528cefcSMark Murray const krb5_data *send, 242b528cefcSMark Murray krb5_data *receive) 243b528cefcSMark Murray { 2445e9cd1aeSAssar Westerlund char *proxy2 = strdup(context->http_proxy); 2455e9cd1aeSAssar Westerlund char *proxy = proxy2; 246b528cefcSMark Murray char *prefix; 247b528cefcSMark Murray char *colon; 248b528cefcSMark Murray struct addrinfo hints; 249b528cefcSMark Murray struct addrinfo *ai, *a; 250b528cefcSMark Murray int ret; 251b528cefcSMark Murray int s; 252b528cefcSMark Murray char portstr[NI_MAXSERV]; 253b528cefcSMark Murray 2545e9cd1aeSAssar Westerlund if (proxy == NULL) 2555e9cd1aeSAssar Westerlund return ENOMEM; 2565e9cd1aeSAssar Westerlund if (strncmp (proxy, "http://", 7) == 0) 2575e9cd1aeSAssar Westerlund proxy += 7; 2585e9cd1aeSAssar Westerlund 259b528cefcSMark Murray colon = strchr(proxy, ':'); 260b528cefcSMark Murray if(colon != NULL) 261b528cefcSMark Murray *colon++ = '\0'; 262b528cefcSMark Murray memset (&hints, 0, sizeof(hints)); 263b528cefcSMark Murray hints.ai_family = PF_UNSPEC; 264b528cefcSMark Murray hints.ai_socktype = SOCK_STREAM; 265b528cefcSMark Murray snprintf (portstr, sizeof(portstr), "%d", 266b528cefcSMark Murray ntohs(init_port (colon, htons(80)))); 2675e9cd1aeSAssar Westerlund ret = getaddrinfo (proxy, portstr, &hints, &ai); 2685e9cd1aeSAssar Westerlund free (proxy2); 269b528cefcSMark Murray if (ret) 270adb0ddaeSAssar Westerlund return krb5_eai_to_heim_errno(ret, errno); 271b528cefcSMark Murray 272b528cefcSMark Murray for (a = ai; a != NULL; a = a->ai_next) { 273b528cefcSMark Murray s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 274b528cefcSMark Murray if (s < 0) 275b528cefcSMark Murray continue; 276b528cefcSMark Murray if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { 277b528cefcSMark Murray close (s); 278b528cefcSMark Murray continue; 279b528cefcSMark Murray } 280b528cefcSMark Murray break; 281b528cefcSMark Murray } 282b528cefcSMark Murray if (a == NULL) { 283b528cefcSMark Murray freeaddrinfo (ai); 284b528cefcSMark Murray return 1; 285b528cefcSMark Murray } 286b528cefcSMark Murray freeaddrinfo (ai); 287b528cefcSMark Murray 288b528cefcSMark Murray asprintf(&prefix, "http://%s/", hostname); 289b528cefcSMark Murray if(prefix == NULL) { 290b528cefcSMark Murray close(s); 291b528cefcSMark Murray return 1; 292b528cefcSMark Murray } 293b528cefcSMark Murray ret = send_and_recv_http(s, context->kdc_timeout, 294b528cefcSMark Murray prefix, send, receive); 295b528cefcSMark Murray close (s); 296b528cefcSMark Murray free(prefix); 297b528cefcSMark Murray if(ret == 0 && receive->length != 0) 298b528cefcSMark Murray return 0; 299b528cefcSMark Murray return 1; 300b528cefcSMark Murray } 301b528cefcSMark Murray 302b528cefcSMark Murray /* 303adb0ddaeSAssar Westerlund * Send the data `send' to one hots in `hostlist' and get back the reply 304b528cefcSMark Murray * in `receive'. 305b528cefcSMark Murray */ 306b528cefcSMark Murray 307b528cefcSMark Murray krb5_error_code 3085e9cd1aeSAssar Westerlund krb5_sendto (krb5_context context, 309b528cefcSMark Murray const krb5_data *send, 3105e9cd1aeSAssar Westerlund char **hostlist, 3115e9cd1aeSAssar Westerlund int port, 312b528cefcSMark Murray krb5_data *receive) 313b528cefcSMark Murray { 3145e9cd1aeSAssar Westerlund krb5_error_code ret = 0; 3155e9cd1aeSAssar Westerlund char **hp, *p; 316b528cefcSMark Murray int fd; 317b528cefcSMark Murray int i; 318b528cefcSMark Murray 319adb0ddaeSAssar Westerlund for (i = 0; i < context->max_retries; ++i) { 320b528cefcSMark Murray for (hp = hostlist; (p = *hp); ++hp) { 321b528cefcSMark Murray char *colon; 322b528cefcSMark Murray int http_flag = 0; 323b528cefcSMark Murray int tcp_flag = 0; 324b528cefcSMark Murray struct addrinfo *ai, *a; 325b528cefcSMark Murray struct addrinfo hints; 326b528cefcSMark Murray char portstr[NI_MAXSERV]; 327b528cefcSMark Murray 328b528cefcSMark Murray if(strncmp(p, "http://", 7) == 0){ 329b528cefcSMark Murray p += 7; 330b528cefcSMark Murray http_flag = 1; 331b528cefcSMark Murray port = htons(80); 332b528cefcSMark Murray } else if(strncmp(p, "http/", 5) == 0) { 333b528cefcSMark Murray p += 5; 334b528cefcSMark Murray http_flag = 1; 335b528cefcSMark Murray port = htons(80); 336b528cefcSMark Murray }else if(strncmp(p, "tcp/", 4) == 0){ 337b528cefcSMark Murray p += 4; 338b528cefcSMark Murray tcp_flag = 1; 339b528cefcSMark Murray } else if(strncmp(p, "udp/", 4) == 0) { 340b528cefcSMark Murray p += 4; 341b528cefcSMark Murray } 342b528cefcSMark Murray if(http_flag && context->http_proxy) { 343b528cefcSMark Murray if (send_via_proxy (context, p, send, receive)) 344b528cefcSMark Murray continue; 345b528cefcSMark Murray else 346b528cefcSMark Murray goto out; 347b528cefcSMark Murray } 348b528cefcSMark Murray colon = strchr (p, ':'); 349b528cefcSMark Murray if (colon) 350b528cefcSMark Murray *colon++ = '\0'; 351b528cefcSMark Murray 352b528cefcSMark Murray memset (&hints, 0, sizeof(hints)); 353b528cefcSMark Murray hints.ai_family = PF_UNSPEC; 354b528cefcSMark Murray if (tcp_flag || http_flag) 355b528cefcSMark Murray hints.ai_socktype = SOCK_STREAM; 356b528cefcSMark Murray else 357b528cefcSMark Murray hints.ai_socktype = SOCK_DGRAM; 358b528cefcSMark Murray snprintf (portstr, sizeof(portstr), "%d", 359b528cefcSMark Murray ntohs(init_port (colon, port))); 360b528cefcSMark Murray ret = getaddrinfo (p, portstr, &hints, &ai); 361b528cefcSMark Murray if (ret) 362b528cefcSMark Murray continue; 363b528cefcSMark Murray for (a = ai; a != NULL; a = a->ai_next) { 364b528cefcSMark Murray fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); 365b528cefcSMark Murray if (fd < 0) 366b528cefcSMark Murray continue; 367b528cefcSMark Murray if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) { 368b528cefcSMark Murray close (fd); 369b528cefcSMark Murray continue; 370b528cefcSMark Murray } 371b528cefcSMark Murray if(http_flag) 372b528cefcSMark Murray ret = send_and_recv_http(fd, context->kdc_timeout, 373b528cefcSMark Murray "", send, receive); 374b528cefcSMark Murray else if(tcp_flag) 375b528cefcSMark Murray ret = send_and_recv_tcp (fd, context->kdc_timeout, 376b528cefcSMark Murray send, receive); 377b528cefcSMark Murray else 378b528cefcSMark Murray ret = send_and_recv_udp (fd, context->kdc_timeout, 379b528cefcSMark Murray send, receive); 380b528cefcSMark Murray close (fd); 381adb0ddaeSAssar Westerlund if(ret == 0 && receive->length != 0) { 382adb0ddaeSAssar Westerlund freeaddrinfo(ai); 383b528cefcSMark Murray goto out; 384b528cefcSMark Murray } 385adb0ddaeSAssar Westerlund } 386adb0ddaeSAssar Westerlund freeaddrinfo(ai); 387adb0ddaeSAssar Westerlund } 388adb0ddaeSAssar Westerlund } 389adb0ddaeSAssar Westerlund krb5_clear_error_string (context); 390b528cefcSMark Murray ret = KRB5_KDC_UNREACH; 391b528cefcSMark Murray out: 3925e9cd1aeSAssar Westerlund return ret; 3935e9cd1aeSAssar Westerlund } 3945e9cd1aeSAssar Westerlund 3955e9cd1aeSAssar Westerlund krb5_error_code 3965e9cd1aeSAssar Westerlund krb5_sendto_kdc2(krb5_context context, 3975e9cd1aeSAssar Westerlund const krb5_data *send, 3985e9cd1aeSAssar Westerlund const krb5_realm *realm, 3995e9cd1aeSAssar Westerlund krb5_data *receive, 4005e9cd1aeSAssar Westerlund krb5_boolean master) 4015e9cd1aeSAssar Westerlund { 4025e9cd1aeSAssar Westerlund krb5_error_code ret; 4035e9cd1aeSAssar Westerlund char **hostlist; 4045e9cd1aeSAssar Westerlund int port; 4055e9cd1aeSAssar Westerlund 4065e9cd1aeSAssar Westerlund port = krb5_getportbyname (context, "kerberos", "udp", 88); 4075e9cd1aeSAssar Westerlund 4085e9cd1aeSAssar Westerlund if (master || context->use_admin_kdc) 4095e9cd1aeSAssar Westerlund ret = krb5_get_krb_admin_hst (context, realm, &hostlist); 4105e9cd1aeSAssar Westerlund else 4115e9cd1aeSAssar Westerlund ret = krb5_get_krbhst (context, realm, &hostlist); 4125e9cd1aeSAssar Westerlund if (ret) 4135e9cd1aeSAssar Westerlund return ret; 4145e9cd1aeSAssar Westerlund ret = krb5_sendto(context, send, hostlist, port, receive); 415b528cefcSMark Murray krb5_free_krbhst (context, hostlist); 416adb0ddaeSAssar Westerlund if (ret == KRB5_KDC_UNREACH) 417adb0ddaeSAssar Westerlund krb5_set_error_string(context, 418adb0ddaeSAssar Westerlund "unable to reach any KDC in realm %s", *realm); 419b528cefcSMark Murray return ret; 420b528cefcSMark Murray } 4215e9cd1aeSAssar Westerlund 4225e9cd1aeSAssar Westerlund krb5_error_code 4235e9cd1aeSAssar Westerlund krb5_sendto_kdc(krb5_context context, 4245e9cd1aeSAssar Westerlund const krb5_data *send, 4255e9cd1aeSAssar Westerlund const krb5_realm *realm, 4265e9cd1aeSAssar Westerlund krb5_data *receive) 4275e9cd1aeSAssar Westerlund { 4285e9cd1aeSAssar Westerlund return krb5_sendto_kdc2(context, send, realm, receive, FALSE); 4295e9cd1aeSAssar Westerlund } 430