[3242] in Kerberos-V5-bugs
pending/987: krb524d: multihome, des-md5 patches
daemon@ATHENA.MIT.EDU (Mark W. Eichin)
Sat Sep 1 16:35:12 2001
Resent-From: gnats@rt-11.mit.edu (GNATS Management)
Resent-To: gnats-admin@rt-11.mit.edu
Resent-Reply-To: krb5-bugs@MIT.EDU, "Mark W. Eichin" <eichin@thok.org>
Message-Id: <20010901203447.F359A15293@kuroneko>
Date: Sat, 1 Sep 2001 16:34:47 -0400 (EDT)
From: "Mark W. Eichin" <eichin@thok.org>
To: krb5-bugs@mit.edu
>Number: 987
>Category: pending
>Synopsis: krb524d: multihome, des-md5 patches
>Confidential: yes
>Severity: serious
>Priority: medium
>Responsible: gnats-admin
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Sat Sep 1 16:35:00 EDT 2001
>Last-Modified:
>Originator:
>Organization:
>Release:
>Environment:
>Description:
>How-To-Repeat:
>Fix:
>Audit-Trail:
>Unformatted:
Two patches (easily seperable, but I needed both to make krb524d at
all useful on my site.) First, extending the krb524d -p option to
take a hostname as well as a port, so that something sane can be
forced to happen on machines with multiple interfaces. Without this
option, krb524d can/will send the response with the wrong source
address and the client will reject the response. Note that it was
cleaner to move the default initialization of the sockaddr_in ahead of
the argument parsing, and then *if* there's an arg, stomp in the new
values; this is more readable by being less conditional-deep. I'd
have updated the man page, but there wasn't one; also, this code is
inherently tied to ipv4 so I did not attempt to make it ipv6-capabile.
The other patch: make the enctypes consistent, so that the service key
can be used to decrypt the ticket as long as it conforms, even if it
isn't an exact match. This case occured (DES-MD5 vs. DES-CRC) when
running a kerbnet-1.3 database under an mit-1.2.2 kdc and krb524d - a
suggested workaround was to clear the SUPPORT_DESMD5 flag, but the
master is still a kerbnet server which predates that feature, so this
was impractical.
These patches are off of the current CVS mainline.
_Mark_ <eichin@thok.org>
The Herd Of Kittens
Index: ChangeLog
===================================================================
RCS file: /cvs/krbdev/krb5/src/krb524/ChangeLog,v
retrieving revision 1.90
diff -u -r1.90 ChangeLog
--- ChangeLog 2001/08/08 16:59:12 1.90
+++ ChangeLog 2001/09/01 20:21:43
@@ -1,3 +1,18 @@
+2001-09-01 Mark W. Eichin <eichin@thok.org>
+
+ * krb524d.c (main): extend "-p" argument parsing to take a
+ hostname (or address) as well. incompatible change: a standalone
+ port number needs a preceding ":" to tell it apart; however, the
+ existing "-p" option hasn't made it into a release yet. This
+ change allows krb524d to answer requests on a specific interface
+ of a multihomed server, instead of getting a randomly chosen
+ (wrong) one (which causes the client to never see the response.)
+
+ * cnv_tkt_skey.c (krb524_convert_tkt_skey): if the ticket and the
+ service key both have usable DES enctypes, force the service key
+ to use the same one, since krb5_decrypt_tkt_part has no magic to
+ tell it they are equivalent.
+
2001-08-08 <epeisach@mit.edu>
* cnv_tkt_skey.c (HOST_BYTE_ORDER): When casting const int * to
Index: cnv_tkt_skey.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/krb524/cnv_tkt_skey.c,v
retrieving revision 1.24
diff -u -r1.24 cnv_tkt_skey.c
--- cnv_tkt_skey.c 2001/08/08 16:59:12 1.24
+++ cnv_tkt_skey.c 2001/09/01 20:21:44
@@ -67,6 +67,25 @@
krb5_address kaddr;
v5tkt->enc_part2 = NULL;
+ switch (v5tkt->enc_part.enctype) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_RAW:
+ /* ok, one of the v4 ones */
+ switch (v5_skey->enctype) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_RAW:
+ /* ok, one of the v4 ones that should match it */
+ if (krb524_debug)
+ fprintf(stderr, "v5_skey enctype %d stomped with v5tkt enctype %d\n",
+ v5_skey->enctype , v5tkt->enc_part.enctype);
+ v5_skey->enctype = v5tkt->enc_part.enctype;
+ }
+ }
+
if ((ret = krb5_decrypt_tkt_part(context, v5_skey, v5tkt))) {
return ret;
}
Index: krb524d.c
===================================================================
RCS file: /cvs/krbdev/krb5/src/krb524/krb524d.c,v
retrieving revision 1.51
diff -u -r1.51 krb524d.c
--- krb524d.c 2001/06/21 17:51:20 1.51
+++ krb524d.c 2001/09/01 20:21:44
@@ -71,7 +71,7 @@
static void usage(context)
krb5_context context;
{
- fprintf(stderr, "Usage: %s [-k[eytab]] [-m[aster] [-r realm]] [-nofork] [-p portnum]\n", whoami);
+ fprintf(stderr, "Usage: %s [-k[eytab]] [-m[aster] [-r realm]] [-nofork] [-p hostaddr[:portnum]]\n", whoami);
cleanup_and_exit(1, context);
}
@@ -107,6 +107,17 @@
use_master = use_keytab = nofork = 0;
config_params.mask = 0;
+ /* initialize default sockaddr_in, so we can override from
+ whatever args are explicitly mentioned */
+ memset((char *) &saddr, 0, sizeof(struct sockaddr_in));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = INADDR_ANY;
+ serv = getservbyname(KRB524_SERVICE, "udp");
+ if (serv == NULL) {
+ saddr.sin_port = htons(KRB524_PORT);
+ } else
+ saddr.sin_port = serv->s_port;
+
while (argc) {
if (strncmp(*argv, "-k", 2) == 0)
use_keytab = 1;
@@ -122,22 +133,64 @@
config_params.realm = *argv;
}
else if (strcmp(*argv, "-p") == 0) {
- char *endptr = 0;
- argv++; argc--;
- if (argc == 0)
- usage (context);
- if (port != 0) {
- com_err (whoami, 0,
- "port number may only be specified once");
- exit (1);
- }
- port = strtoul (*argv, &endptr, 0);
- if (*endptr != '\0' || port > 65535 || port == 0) {
- com_err (whoami, 0,
- "invalid port number %s, must be 1..65535\n",
- *argv);
- exit (1);
- }
+ /* -p takes an address and optional port number.
+ if the ":" is present, it separates the two. */
+ char *portstr, *strend;
+ argv++; argc--;
+ if (argc == 0)
+ usage(context);
+ /* peel off port number */
+ portstr = strrchr(*argv, ':');
+ if (portstr) {
+ unsigned long n;
+ portstr++;
+ n = strtoul(portstr, &strend, 0);
+ if (portstr == strend) {
+ com_err (whoami, 0, "port number <%s> not numeric", portstr);
+ exit (1);
+ } else if (*strend) {
+ com_err (whoami, 0, "non numeric trash <%s> after port number", strend);
+ exit (1);
+ } else if (n < 1 || n > 65535) {
+ com_err (whoami, 0, "port number <%d> out of range", n)
+ exit (1);
+ }
+ saddr.sin_port = htons(n);
+ portstr--;
+ }
+ /* handle host part */
+ if (portstr != *argv) {
+ /* if the ":" was the first char, there is no host part */
+ struct hostent *h;
+ char *hname = *argv;
+ if (portstr) {
+ /* we need to copy the hostname */
+ int hlen = portstr - *argv;
+ hname = malloc(hlen + 1);
+ strncpy(hname, *argv, hlen);
+ hname[hlen] = 0;
+ } else {
+ hname = malloc(strlen(*argv) + 1);
+ strcpy(hname, *argv);
+ }
+ h = gethostbyname(hname);
+ if (h) {
+ memcpy(&saddr.sin_addr.s_addr, h->h_addr_list[0], sizeof(saddr.sin_addr.s_addr));
+ } else {
+ /* gethostbyname failed, try inet_aton */
+ struct in_addr i;
+ int st;
+ st = inet_aton(hname, &i);
+ if (st) {
+ memcpy(&saddr.sin_addr.s_addr, &i.s_addr, sizeof(saddr.sin_addr.s_addr));
+ } else {
+ /* report the more interesting gethostbyname failure */
+ com_err (whoami, 0, "couldn't interpret <%s> as hostname or address", hname);
+ exit (1);
+ }
+ }
+ free(hname);
+ }
}
else
break;
@@ -160,20 +213,6 @@
if (use_master)
init_master(context, &config_params);
- memset((char *) &saddr, 0, sizeof(struct sockaddr_in));
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = INADDR_ANY;
- if (port == 0) {
- serv = getservbyname(KRB524_SERVICE, "udp");
- if (serv == NULL) {
- com_err(whoami, 0, "service entry `%s' not found, using %d",
- KRB524_SERVICE, KRB524_PORT);
- saddr.sin_port = htons(KRB524_PORT);
- } else
- saddr.sin_port = serv->s_port;
- } else
- saddr.sin_port = htons(port);
-
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
com_err(whoami, errno, "creating main socket");
cleanup_and_exit(1, context);