+2002-12-06 Tom Yu <tlyu@mit.edu>
+
+ * k5-int.h: Update prototype of krb5int_locate_server() to take
+ protocol family argument. Update krb5int_access to current call
+ signatures of locate_kdc() and locate_server(), as well as to add
+ add_host_to_list() for use by krb4 library.
+
2002-11-26 Tom Yu <tlyu@mit.edu>
* port-sockets.h: Add SOCKET_CONNECT, SOCKET_GETSOCKNAME, and
#define ADDRLIST_INIT { 0, 0, 0 }
extern void krb5int_free_addrlist (struct addrlist *);
extern int krb5int_grow_addrlist (struct addrlist *, int);
+extern int krb5int_add_host_to_list (struct addrlist *, const char *,
+ int, int, int, int);
krb5_error_code
krb5int_locate_server (krb5_context,
itself. Use 0 for dflport2 if there's no
secondary port (most common, except kdc
case). */
- int dflport1, int dflport2);
+ int dflport1, int dflport2,
+ int family);
#endif /* KRB5_LIBOS_PROTO__ */
/* To keep happy libraries which are (for now) accessing internal stuff */
/* Make sure to increment by one when changing the struct */
-#define KRB5INT_ACCESS_STRUCT_VERSION 5
+#define KRB5INT_ACCESS_STRUCT_VERSION 6
typedef struct _krb5int_access {
krb5_error_code (*krb5_locate_kdc) (krb5_context, const krb5_data *,
- struct addrlist *, int, int);
+ struct addrlist *, int, int, int);
krb5_error_code (*krb5_locate_server) (krb5_context, const krb5_data *,
struct addrlist *, int,
const char *, const char *,
- int, int, int);
+ int, int, int, int);
void (*free_addrlist) (struct addrlist *);
unsigned int krb5_max_skdc_timeout;
unsigned int krb5_skdc_timeout_shift;
krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg,
const struct addrlist *, krb5_data *reply,
struct sockaddr *, socklen_t *);
+ krb5_error_code (*add_host_to_list)(struct addrlist *lp,
+ const char *hostname,
+ int port, int secport,
+ int socktype, int family);
} krb5int_access;
#define KRB5INT_ACCESS_VERSION \
+2002-12-06 Tom Yu <tlyu@mit.edu>
+
+ * g_ad_tkt.c (get_ad_tkt): Add KRB5_CALLCONV.
+
+ * g_in_tkt.c (krb_get_in_tkt_preauth): Add KRB5_CALLCONV.
+ (krb_get_in_tkt): Add KRB5_CALLCONV.
+
+ * send_to_kdc.c (krb4int_send_to_kdc_addr): New function; does
+ what send_to_kdc() used to do but can also return local address.
+
2002-12-05 Tom Yu <tlyu@mit.edu>
* kname_parse.c (kname_unparse): Add new function ported from
return 0;
}
-int
+int KRB5_CALLCONV
get_ad_tkt(service, sinstance, realm, lifetime)
char *service;
char *sinstance;
NULL, 0, creds);
}
-int
+int KRB5_CALLCONV
krb_get_in_tkt_preauth(user, instance, realm, service, sinstance, life,
key_proc, decrypt_proc,
arg, preauth_p, preauth_len)
return retval;
}
-int
+int KRB5_CALLCONV
krb_get_in_tkt(user, instance, realm, service, sinstance, life,
key_proc, decrypt_proc, arg)
char *user;
#include "krbports.h"
#include "prot.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#include <unistd.h>
#endif
#include "port-sockets.h"
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+#include "krb4int.h"
#define S_AD_SZ sizeof(struct sockaddr_in)
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#else
-extern char *malloc(), *calloc(), *realloc();
-#endif
-
+/* These are really defaults from getservbyname() or hardcoded. */
static int cached_krb_udp_port = 0;
static int cached_krbsec_udp_port = 0;
-static int
-send_recv (KTEXT pkt, KTEXT rpkt, SOCKET f,
- struct sockaddr_in *_to, struct hostent *addrs);
-
+int krb4int_send_to_kdc_addr(KTEXT, KTEXT, char *,
+ struct sockaddr *, socklen_t *);
#ifdef DEBUG
static char *prog = "send_to_kdc";
*/
int
-send_to_kdc(pkt,rpkt,realm)
- KTEXT pkt;
- KTEXT rpkt;
- char *realm;
+krb4int_send_to_kdc_addr(
+ KTEXT pkt, KTEXT rpkt, char *realm,
+ struct sockaddr *addr, socklen_t *addrlen)
{
- int i;
- SOCKET f;
- int no_host; /* was a kerberos host found? */
- int retry;
- int n_hosts;
- int retval;
- struct sockaddr_in to;
- struct hostent *farkedhost;
- struct hostent *host, *hostlist;
- char *cp;
- char krbhst[MAXHOSTNAMELEN];
- char lrealm[REALM_SZ];
- char *scol;
- int krb_udp_port = 0;
- int krbsec_udp_port = 0;
+ struct addrlist al = ADDRLIST_INIT;
+ char lrealm[REALM_SZ];
+ krb5int_access internals;
+ krb5_error_code retval;
+ struct servent *sp;
+ int krb_udp_port = 0;
+ int krbsec_udp_port = 0;
+ char krbhst[MAXHOSTNAMELEN];
+ char *scol;
+ int i;
+ int err;
+ krb5_data message, reply;
/*
* If "realm" is non-null, use that, otherwise get the
* local realm.
*/
if (realm)
- (void) strncpy(lrealm, realm, sizeof(lrealm) - 1);
- else
- if (krb_get_lrealm(lrealm,1)) {
+ strncpy(lrealm, realm, sizeof(lrealm) - 1);
+ else {
+ if (krb_get_lrealm(lrealm, 1)) {
DEB (("%s: can't get local realm\n", prog));
- return(SKDC_CANT);
+ return SKDC_CANT;
}
+ }
lrealm[sizeof(lrealm) - 1] = '\0';
DEB (("lrealm is %s\n", lrealm));
- if (SOCKET_INITIALIZE()) {
- DEB (("%s: can't initialize sockets library\n",prog));
- return (SKDC_CANT);
- }
- /* from now on, exit through rtn label for cleanup */
+ retval = krb5int_accessor(&internals, KRB5INT_ACCESS_VERSION);
+ if (retval)
+ return KFAILURE;
/* The first time, decide what port to use for the KDC. */
if (cached_krb_udp_port == 0) {
- register struct servent *sp;
sp = getservbyname("kerberos","udp");
if (sp)
cached_krb_udp_port = sp->s_port;
as a fallback. */
if (cached_krbsec_udp_port == 0 &&
cached_krb_udp_port != htons(KERBEROS_PORT)) {
- register struct servent *sp;
sp = getservbyname("kerberos-sec","udp");
if (sp)
cached_krbsec_udp_port = sp->s_port;
DEB (("cached_krbsec_udp_port is %d\n", cached_krbsec_udp_port));
}
- memset((char *)&to, 0, S_AD_SZ);
- hostlist = (struct hostent *) malloc(sizeof(struct hostent));
- if (!hostlist) {
- retval = /*errno */SKDC_CANT;
- goto rtn_clean; /* Run SOCKET_CLEANUP then return. */
- }
- hostlist->h_name = 0; /* so it gets properly freed at "rtn" */
-
- f = socket(AF_INET, SOCK_DGRAM, 0);
- if (f == INVALID_SOCKET) {
- DEB (("%s: Can't open socket\n", prog));
- retval = /*errno */SKDC_CANT;
- goto rtn_clean; /* Run SOCKET_CLEANUP then return. */
- }
-
-/*
-** FIXME! FTP Software's WINSOCK implmentation insists that
-** a socket be bound before it can receive datagrams.
-** This is outside specs. Since it shouldn't hurt any
-** other implementations we'll go ahead and do it for
-** now.
-*/
- {
- struct sockaddr_in from;
- memset ((char *)&from, 0, S_AD_SZ);
- from.sin_family = AF_INET;
- from.sin_addr.s_addr = INADDR_ANY;
- if ( bind(f, (struct sockaddr *)&from, S_AD_SZ) == SOCKET_ERROR ) {
- DEB (("%s : Can't bind\n", prog));
- retval = SKDC_CANT;
- goto rtn;
- }
- }
-/* End of kludge (FIXME) for FTP Software WinSock stack. */
-
- no_host = 1;
- /* get an initial allocation */
- n_hosts = 0;
for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
#ifdef DEBUG
if (krb_debug) {
krb_udp_port = cached_krb_udp_port;
krbsec_udp_port = cached_krbsec_udp_port;
}
- farkedhost = gethostbyname(krbhst);
-#ifdef DEBUG
- if (krb_debug) {
- DEB (("%s.\n", farkedhost ? "Got it" : "Didn't get it"));
- (void) fflush(stdout);
- }
-#endif
- if (!farkedhost)
- continue;
- no_host = 0; /* found at least one */
- n_hosts++;
- /* preserve host network address to check later
- * (would be better to preserve *all* addresses,
- * take care of that later)
- */
- hostlist = (struct hostent *)
- realloc((char *)hostlist,
- (unsigned)
- sizeof(struct hostent)*(n_hosts+1));
- if (!hostlist) {
- retval = /*errno */SKDC_CANT;
- goto rtn;
- }
- hostlist[n_hosts-1] = *farkedhost; /* Copy into array */
- memset((char *)&hostlist[n_hosts], 0, sizeof(struct hostent));
- host = &hostlist[n_hosts-1];
- cp = malloc((unsigned)host->h_length);
- if (!cp) {
- retval = /*errno */SKDC_CANT;
- goto rtn;
- }
- memcpy(cp, host->h_addr, host->h_length);
-
-/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
- (or worse) only return one name ... */
-#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
- host->h_addr_list = (char **)malloc(sizeof(char *));
- if (!host->h_addr_list) {
- retval = /*errno */SKDC_CANT;
- goto rtn;
- }
-#endif /* ULTRIX022 || SunOS */
- host->h_addr = cp;
- to.sin_family = host->h_addrtype;
- memcpy((char *)&to.sin_addr, host->h_addr,
- host->h_length);
- to.sin_port = krb_udp_port;
- if (send_recv(pkt, rpkt, f, &to, hostlist)) {
- retval = KSUCCESS;
- goto rtn;
- }
- if (krbsec_udp_port) {
- to.sin_port = krbsec_udp_port;
- if (send_recv(pkt, rpkt, f, &to, hostlist)) {
- retval = KSUCCESS;
- goto rtn;
- }
+ err = internals.add_host_to_list(&al, krbhst,
+ krb_udp_port, krbsec_udp_port,
+ SOCK_DGRAM, PF_INET);
+ if (err) {
+ retval = SKDC_CANT;
+ goto free_al;
}
- DEB (("Timeout, error, or wrong descriptor\n"));
}
- if (no_host) {
+ if (al.naddrs == 0) {
DEB (("%s: can't find any Kerberos host.\n", prog));
retval = SKDC_CANT;
- goto rtn;
}
- /* retry each host in sequence */
- for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
- for (host = hostlist; host->h_name != (char *)NULL; host++) {
- to.sin_family = host->h_addrtype;
- memcpy((char *)&to.sin_addr, host->h_addr,
- host->h_length);
- if (send_recv(pkt, rpkt, f, &to, hostlist)) {
- retval = KSUCCESS;
- goto rtn;
- }
- }
- }
- retval = SKDC_RETRY;
-rtn:
- (void) closesocket (f);
-rtn_clean:
- SOCKET_CLEANUP(); /* Done with using sockets for awhile */
- if (hostlist) {
- register struct hostent *hp;
- for (hp = hostlist; hp->h_name; hp++)
-#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
- if (hp->h_addr_list) {
-#endif /* ULTRIX022 || SunOS */
- if (hp->h_addr)
- free(hp->h_addr);
-#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
- free((char *)hp->h_addr_list);
- }
-#endif /* ULTRIX022 || SunOS */
- free((char *)hostlist);
- }
- return(retval);
+ message.length = pkt->length;
+ message.data = (char *)pkt->dat; /* XXX yuck */
+ retval = internals.sendto_udp(NULL, &message, &al, &reply, addr,
+ addrlen);
+ DEB(("sendto_udp returns %d\n", retval));
+free_al:
+ internals.free_addrlist(&al);
+ if (retval)
+ return SKDC_CANT;
+ DEB(("reply.length=%d\n", reply.length));
+ if (reply.length > sizeof(rpkt->dat))
+ retval = SKDC_CANT;
+ rpkt->length = 0;
+ if (!retval) {
+ memcpy(rpkt->dat, reply.data, reply.length);
+ rpkt->length = reply.length;
+ }
+ krb5_free_data_contents(NULL, &reply);
+ return retval;
}
-/*
- * try to send out and receive message.
- * return 1 on success, 0 on failure
- */
-
-static int
-send_recv(pkt,rpkt,f,_to,addrs)
- KTEXT pkt;
- KTEXT rpkt;
- SOCKET f;
- struct sockaddr_in *_to;
- struct hostent *addrs;
+int
+send_to_kdc(KTEXT pkt, KTEXT rpkt, char *realm)
{
- fd_set readfds;
- register struct hostent *hp;
- struct sockaddr_in from;
- int sin_size;
- int numsent;
- int selresult;
- int recvresult;
- struct timeval timeout;
-
-#ifdef DEBUG
- if (krb_debug) {
- if (_to->sin_family == AF_INET) {
- printf("Sending message to ");
- far_fputs (inet_ntoa(_to->sin_addr), stdout);
- printf("...");
- } else
- printf("Sending message...");
- (void) fflush(stdout);
- }
-#endif
- if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
- (struct sockaddr *)_to,
- S_AD_SZ)) != pkt->length) {
- DEB (("sent only %d/%d\n",numsent, pkt->length));
- return 0;
- }
-#ifdef DEBUG
- if (krb_debug) {
- printf("Sent\nWaiting for reply...");
- (void) fflush(stdout);
- }
-#endif
- FD_ZERO(&readfds);
- FD_SET(f, &readfds);
- SOCKET_SET_ERRNO (0);
-
- /* select - either recv is ready, or timeout */
- /* see if timeout or error or wrong descriptor */
- /* Need to fill in the timeout structure each time, because on some
- systems -- e.g., Linux -- the timeout will be modified in place
- by the select syscall. */
- timeout.tv_sec = CLIENT_KRB_TIMEOUT;
- timeout.tv_usec = 0;
- selresult = select(SOCKET_NFDS(f), &readfds, (fd_set *)0, (fd_set *)0,
- &timeout);
- if (selresult != 1 || !FD_ISSET(f, &readfds)) {
-#ifdef DEBUG
- if (krb_debug) {
- fprintf(stderr, "select failed: selresult=%d, readfds=%x, errno=%d",
- selresult, readfds, SOCKET_ERRNO);
- perror("");
- }
-#endif
- return 0;
- }
-
- sin_size = sizeof(from);
- recvresult = recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
- (struct sockaddr *)&from, &sin_size);
- if (recvresult < 0) {
- DEB (("Recvfrom error %d\n", SOCKET_ERRNO));
- return 0;
- }
- rpkt->length = recvresult;
-#ifdef DEBUG
- if (krb_debug) {
- printf("received packet from ");
- far_fputs (inet_ntoa(from.sin_addr), stdout);
- printf("\n");
- fflush(stdout);
- }
-#endif
- for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
- if (!memcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
- hp->h_length)) {
- DEB (("Received it\n"));
- return 1;
- }
- DEB (("packet not from %x\n", hp->h_addr));
- }
- DEB (("%s: received packet from wrong host! (%x)\n",
- "send_to_kdc(send_rcv)", from.sin_addr.s_addr));
- return 0;
+ return krb4int_send_to_kdc_addr(pkt, rpkt, realm, NULL, NULL);
}
+2002-12-06 Tom Yu <tlyu@mit.edu>
+
+ * accessor.c (krb5int_accessor): Add add_host_to_list.
+
+ * changepw.c (krb5_locate_kpasswd): Update calls to
+ krb5_locate_kdc().
+
+ * locate_kdc.c (add_host_to_list): Renamed to
+ krb5int_add_host_to_list(), with macro to deal with existing
+ callers in this file. Now takes an argument to indicate protocol
+ family. Callers updated accordingly to also take protocol family
+ arguments.
+
+ * os-proto.h: Update prototype of krb5_locate_kdc().
+
+ * sendto_kdc.c (krb5_sendto_kdc): Update calls to
+ krb5_locate_kdc().
+ (krb5int_sendto): UDP reply length is in.pos-in.buf, not
+ in.bufsize.
+
+ * t_locate_kdc.c (main): Update call to krb5_locate_kdc().
+
+ * t_std_conf.c (test_locate_kdc): Update call to krb5_locate_kdc().
+
2002-11-14 Tom Yu <tlyu@mit.edu>
* changepw.c: Remove reference to adm_err.h.
internals_temp.md5_hash_provider = &krb5int_hash_md5;
internals_temp.arcfour_enc_provider = &krb5int_enc_arcfour;
internals_temp.sendto_udp = &krb5int_sendto;
+ internals_temp.add_host_to_list = krb5int_add_host_to_list;
*internals = internals_temp;
return 0;
}
code = krb5int_locate_server (context, realm, addrlist, 0,
"kpasswd_server", "_kpasswd", 0,
- DEFAULT_KPASSWD_PORT, 0);
+ DEFAULT_KPASSWD_PORT, 0, 0);
if (code) {
code = krb5int_locate_server (context, realm, addrlist, 0,
"admin_server", "_kerberos-adm", 1,
- DEFAULT_KPASSWD_PORT, 0);
+ DEFAULT_KPASSWD_PORT, 0, 0);
if (!code) {
/* Success with admin_server but now we need to change the
port number to use DEFAULT_KPASSWD_PORT. */
return 0;
}
-static int
-add_host_to_list (struct addrlist *lp, const char *hostname,
- int port, int secport, int socktype)
+#define add_host_to_list krb5int_add_host_to_list
+
+int
+krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
+ int port, int secport,
+ int socktype, int family)
{
struct addrinfo *addrs, *a, *anext, hint;
int err;
#endif
memset(&hint, 0, sizeof(hint));
+ hint.ai_family = family;
hint.ai_socktype = socktype;
sprintf(portbuf, "%d", ntohs(port));
sprintf(secportbuf, "%d", ntohs(secport));
krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
const char * name, struct addrlist *addrlist,
int get_masters, int socktype,
- int udpport, int sec_udpport)
+ int udpport, int sec_udpport, int family)
{
const char *realm_srv_names[4];
char **masterlist, **hostlist, *host, *port, *cp;
}
if (socktype != 0)
- code = add_host_to_list (addrlist, hostlist[i], p1, p2, socktype);
+ code = add_host_to_list (addrlist, hostlist[i], p1, p2,
+ socktype, family);
else {
code = add_host_to_list (addrlist, hostlist[i], p1, p2,
- SOCK_DGRAM);
+ SOCK_DGRAM, family);
if (code == 0)
code = add_host_to_list (addrlist, hostlist[i], p1, p2,
- SOCK_STREAM);
+ SOCK_STREAM, family);
}
if (code) {
#ifdef TEST
krb5_error_code ret;
ret = krb5_locate_srv_conf_1 (context, realm, name, al,
- get_masters, 0, udpport, sec_udpport);
+ get_masters, 0, udpport, sec_udpport, 0);
if (ret)
return ret;
if (al->naddrs == 0) /* Couldn't resolve any KDC names */
krb5_locate_srv_dns_1 (const krb5_data *realm,
const char *service,
const char *protocol,
- struct addrlist *addrlist)
+ struct addrlist *addrlist,
+ int family)
{
union {
unsigned char bytes[2048];
code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0,
(strcmp("_tcp", protocol)
? SOCK_DGRAM
- : SOCK_STREAM));
+ : SOCK_STREAM), family);
if (code)
break;
}
const char *service, const char *protocol,
struct addrlist *al)
{
- return krb5_locate_srv_dns_1 (realm, service, protocol, al);
+ return krb5_locate_srv_dns_1 (realm, service, protocol, al, 0);
}
#endif
#endif /* KRB5_DNS_LOOKUP */
const char *profname, const char *dnsname,
int socktype,
/* network order port numbers! */
- int dflport1, int dflport2)
+ int dflport1, int dflport2,
+ int family)
{
krb5_error_code code;
struct addrlist al = ADDRLIST_INIT;
*/
code = krb5_locate_srv_conf_1(context, realm, profname, &al, get_masters,
- socktype, dflport1, dflport2);
+ socktype, dflport1, dflport2, family);
#ifdef KRB5_DNS_LOOKUP
if (code && dnsname != 0) {
if (use_dns) {
code = 0;
if (socktype == SOCK_DGRAM || socktype == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", &al);
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_udp",
+ &al, family);
#ifdef TEST
if (code)
fprintf(stderr, "dns udp lookup returned error %d\n",
#endif
}
if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", &al);
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp",
+ &al, family);
#ifdef TEST
if (code)
fprintf(stderr, "dns tcp lookup returned error %d\n",
krb5_error_code
krb5_locate_kdc(krb5_context context, const krb5_data *realm,
struct addrlist *addrlist,
- int get_masters, int socktype)
+ int get_masters, int socktype, int family)
{
int udpport, sec_udpport;
(get_masters
? "_kerberos-master"
: "_kerberos"),
- socktype, udpport, sec_udpport);
+ socktype, udpport, sec_udpport, family);
}
struct addrlist;
krb5_error_code krb5_locate_kdc
- (krb5_context, const krb5_data *, struct addrlist *, int, int);
+ (krb5_context, const krb5_data *, struct addrlist *, int, int, int);
#ifdef HAVE_NETINET_IN_H
krb5_error_code krb5_unpack_full_ipaddr
else
socktype1 = SOCK_STREAM, socktype2 = SOCK_DGRAM;
- retval = krb5_locate_kdc(context, realm, &addrs, use_master, socktype1);
+ retval = krb5_locate_kdc(context, realm, &addrs, use_master, socktype1, 0);
if (socktype2) {
struct addrlist addrs2;
retval = krb5_locate_kdc(context, realm, &addrs2, use_master,
- socktype2);
+ socktype2, 0);
if (retval == 0) {
(void) merge_addrlists(&addrs, &addrs2);
krb5int_free_addrlist(&addrs2);
}
/* Success! */
reply->data = conns[winning_conn].x.in.buf;
- reply->length = conns[winning_conn].x.in.bufsize;
+ reply->length = (conns[winning_conn].x.in.pos
+ - conns[winning_conn].x.in.buf);
dprint("returning %d bytes in buffer %p\n",
(int) reply->length, reply->data);
retval = 0;
break;
case LOOKUP_WHATEVER:
- err = krb5_locate_kdc (ctx, &realm, &al, master, 0);
+ err = krb5_locate_kdc (ctx, &realm, &al, master, 0, 0);
break;
}
if (err) kfatal (err);
rlm.data = realm;
rlm.length = strlen(realm);
- retval = krb5_locate_kdc(ctx, &rlm, &addrs, get_masters, 0);
+ retval = krb5_locate_kdc(ctx, &rlm, &addrs, get_masters, 0, 0);
if (retval) {
com_err("krb5_locate_kdc", retval, 0);
return;