[412] in Kerberos-V5-bugs
Re: Some bugs, some questions, and a Next.cf
daemon@ATHENA.MIT.EDU (Andrew Gross)
Wed Jan 26 02:56:48 1994
Date: Tue, 25 Jan 94 23:56:29 -0800
From: Andrew Gross <drew@drew.extern.ucsd.edu>
To: drew@drew.extern.ucsd.edu, tytso@MIT.EDU
Cc: krb5-bugs@athena.mit.edu.
> Date: Mon, 24 Jan 94 23:11:45 -0800
> From: Andrew Gross <drew@drew.extern.ucsd.edu>
>
> Are you all interested in mods to make multihomed hosts possible
> under K5? I can make kadmind listen on all interfaces, krshd/krlogind
> choose the right pricipal based on the interface being used, and
> kdb5_edit extract several principals to the v5srvtab (one per
> interface). I understand that you do not have any use for this
> functionality but could it be added (#defined) to show others who want
> to use it how it can be done?
>
> Yes, I'm interested; send me diffs, and I'll see about getting them
> integrated in. Please try to make the changes as clean as possible.
> While the Kerberos V5 distributions haven't been exactly clean
> themselves, I've been trying make the code cleaner, and I'd rather not
> add any dirty code in.
Hello,
Don't you violate a law of thermodynamics if you only add cleaner
code???
Here are the patches I have for multihomed hosts. They are
reasonably clean except for I don't like how the buffer overflow for
the hostname being too long is handled in the krshd/krlogind patches.
It should be a fatal error but the syslog/exit does not appeal to me.
Thank you,
Andrew Gross
=========================================================================
%%% To make kadmind listen on multiple interfaces, it just needs to
%%% in adm_network.c(line 223) put INADDR_ANY into
%%% client_server_info.server_name.sin_addr[.s_addr] in the "#ifdef unicos61"
%%% construct.
%%% This is a patch for kdb5_edit. It adds the nxst command which can
%%% be used to extract multiple principals into the v5srvtab. I got
%%% this from the kerberos mailing list and all credit for it goes
%%% to Jonathan Kamens (jik@MIT.Edu).
diff -r -c edit/kdb5_ed_ct.ct edit.x/kdb5_ed_ct.ct
*** edit/kdb5_ed_ct.ct Thu Jan 13 12:10:55 1994
--- edit.x/kdb5_ed_ct.ct Fri Jan 21 07:43:11 1994
***************
*** 54,59 ****
--- 54,62 ----
request extract_srvtab, "Extract service key table",
extract_srvtab, xst, ex_st;
+ request new_extract_srvtab, "Extract service key table",
+ new_extract_srvtab, nxst, n_ex_st;
+
request extract_v4_srvtab, "Extract service key table",
extract_v4_srvtab, xst4;
diff -r -c edit/kdb5_edit.c edit.x/kdb5_edit.c
*** edit/kdb5_edit.c Thu Jan 13 12:11:41 1994
--- edit.x/kdb5_edit.c Fri Jan 21 07:46:50 1994
***************
*** 673,678 ****
--- 673,815 ----
}
void
+ new_extract_srvtab(argc, argv)
+ int argc;
+ char *argv[];
+ {
+ char ktname[MAXPATHLEN+sizeof("WRFILE:")+1], *ktnameptr = 0;
+ krb5_keytab ktid;
+ krb5_error_code retval;
+ krb5_principal princ;
+ krb5_db_entry dbentry;
+ char *pname;
+ register int i;
+ int nentries;
+ krb5_boolean more;
+ krb5_keytab_entry newentry;
+ char *subsysname = argv[0];
+ static int srvtab_number = 0;
+
+ argv++, argc--;
+
+ while (argc && **argv == '-') {
+ if (! strcmp(&argv[0][1], "file")) {
+ argv++, argc--;
+ if (! argc) {
+ com_err(subsysname, 0, "Missing argument after '-file'");
+ goto usage;
+ }
+ ktnameptr = argv[0];
+ argv++, argc--;
+ }
+ else {
+ goto usage;
+ }
+ }
+
+ if (! argc) {
+ goto usage;
+ }
+
+ if (!dbactive) {
+ com_err(subsysname, 0, Err_no_database);
+ return;
+ }
+ if (!valid_master_key) {
+ com_err(subsysname, 0, Err_no_master_msg);
+ return;
+ }
+
+ memset(ktname, 0, sizeof(ktname));
+ strcpy(ktname, "WRFILE:");
+ if (ktnameptr) {
+ if (strlen(ktnameptr) + strlen(ktname) + 1 > sizeof(ktname)) {
+ com_err(subsysname, 0, "File name '%s' is too long",
+ ktnameptr);
+ return;
+ }
+ strcat(ktname, ktnameptr);
+ }
+ else {
+ (void) sprintf(&ktname[strlen(ktname)], "new-srvtab-%d",
+ srvtab_number++);
+ }
+
+ if (retval = krb5_kt_resolve(ktname, &ktid)) {
+ com_err(subsysname, retval, "while resolving keytab name '%s'",
+ ktname);
+ return;
+ }
+
+ for (; argc; argc--, argv++) {
+ /* iterate over the names */
+ pname = malloc(strlen(*argv) + strlen(cur_realm)+2);
+ if (!pname) {
+ com_err(subsysname, ENOMEM,
+ "while preparing to extract key for %s", *argv);
+ continue;
+ }
+ strcpy(pname, *argv);
+ if (!strchr(*argv, REALM_SEP)) {
+ strcat(pname, REALM_SEP_STR);
+ strcat(pname, cur_realm);
+ }
+
+ if (retval = krb5_parse_name(pname, &princ)) {
+ com_err(subsysname, retval, "while parsing '%s'", pname);
+ free(pname);
+ continue;
+ }
+ nentries = 1;
+ if (retval = krb5_db_get_principal(princ, &dbentry, &nentries,
+ &more)) {
+ com_err(subsysname, retval, "while retrieving '%s'", pname);
+ goto cleanmost;
+ } else if (more) {
+ com_err(subsysname, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE,
+ "while retrieving '%s'", pname);
+ if (nentries)
+ krb5_db_free_principal(&dbentry, nentries);
+ goto cleanmost;
+ } else if (!nentries) {
+ com_err(subsysname, KRB5_KDB_NOENTRY, "while retrieving '%s'",
+ pname);
+ goto cleanmost;
+ }
+ if (retval = krb5_kdb_decrypt_key(&master_encblock,
+ &dbentry.key,
+ &newentry.key)) {
+ com_err(subsysname, retval, "while decrypting key for '%s'",
+ pname);
+ goto cleanall;
+ }
+ newentry.principal = princ;
+ newentry.vno = dbentry.kvno;
+ if (retval = krb5_kt_add_entry(ktid, &newentry)) {
+ com_err(subsysname, retval, "while adding key to keytab '%s'",
+ ktname);
+ } else
+ printf("'%s' added to keytab '%s'\n",
+ pname, ktname);
+ memset((char *)newentry.key.contents, 0, newentry.key.length);
+ krb5_xfree(newentry.key.contents);
+ cleanall:
+ krb5_db_free_principal(&dbentry, nentries);
+ cleanmost:
+ free(pname);
+ krb5_free_principal(princ);
+ }
+ if (retval = krb5_kt_close(ktid))
+ com_err(subsysname, retval, "while closing keytab");
+ return;
+
+ usage:
+ com_err(subsysname, 0, "Usage: %s [ -file srvtab-file ] principal ...",
+ subsysname);
+ return;
+ }
+
+ void
extract_v4_srvtab(argc, argv)
int argc;
char *argv[];
%%% These are the patches for krshd and krlogind. Basically I
%%% do a gethostbyname on the data returned from getsockname and
%%% use that hostname in the krb5_sname_to_principal call.
%%% I don't like how I handled the buffer overflow error in the
%%% first branch of the "if (hp)" statement but I'm not sure what
%%% would be better.
diff -r -c bsd/krlogind.c bsd.x/krlogind.c
*** bsd/krlogind.c Fri Jan 14 12:42:19 1994
--- bsd.x/krlogind.c Tue Jan 25 23:25:44 1994
***************
*** 106,111 ****
--- 106,112 ----
* #define KERBEROS
*/
#define LOG_REMOTE_REALM
+ #define LOG_ALL_LOGINS
#define CRYPT
#ifdef KRB5_KRB4_COMPAT
#define SERVE_V4
***************
*** 1393,1398 ****
--- 1394,1401 ----
krb5_data inbuf;
char v4_instance[INST_SZ]; /* V4 Instance */
char v4_version[9];
+ char hostname[100];
+ struct hostent *hp;
len = sizeof(laddr);
if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
***************
*** 1399,1404 ****
--- 1402,1420 ----
exit(1);
}
+ hp = gethostbyaddr((char *)&laddr.sin_addr, sizeof (struct in_addr),
+ laddr.sin_family);
+ if (hp){
+ if ( 100 < strlen(hp->h_name) + 1) {
+ syslog(LOG_ERR,"gethostbyaddr returned name > 100 chars\n");
+ exit(244);
+ }
+ strcpy(hostname,hp->h_name);
+ } else {
+ /* assume inet dot form is no more than 100 chars */
+ strcpy(hostname,(char *)inet_ntoa(laddr.sin_addr));
+ }
+
len = sizeof(peersin);
if (getpeername(netf, (struct sockaddr *)&peersin, &len)) {
syslog(LOG_ERR, "get peer name failed %d", netf);
***************
*** 1415,1422 ****
--- 1431,1442 ----
peeraddr.length = SIZEOF_INADDR;
peeraddr.contents = (krb5_octet *)&peersin.sin_addr;
+ if (status = krb5_sname_to_principal(hostname, "host", KRB5_NT_SRV_HST,
+ &server)) {
+ /*DREW
if (status = krb5_sname_to_principal(NULL, "host", KRB5_NT_SRV_HST,
&server)) {
+ */
syslog(LOG_ERR, "parse server name %s: %s", "host",
error_message(status));
exit(1);
diff -r -c bsd/krshd.c bsd.x/krshd.c
*** bsd/krshd.c Fri Jan 14 12:42:26 1994
--- bsd.x/krshd.c Tue Jan 25 23:26:20 1994
***************
*** 1383,1394 ****
char v4_instance[INST_SZ]; /* V4 Instance */
char v4_version[9];
krb5_ticket *ticket;
len = sizeof(laddr);
if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
exit(1);
}
!
#ifdef unicos61
#define SIZEOF_INADDR SIZEOF_in_addr
#else
--- 1383,1409 ----
char v4_instance[INST_SZ]; /* V4 Instance */
char v4_version[9];
krb5_ticket *ticket;
+ char hostname[100];
+ struct hostent *hp;
len = sizeof(laddr);
if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
exit(1);
}
!
! hp = gethostbyaddr((char *)&laddr.sin_addr, sizeof (struct in_addr),
! laddr.sin_family);
! if (hp){
! if ( 100 < strlen(hp->h_name) + 1) {
! syslog(LOG_ERR,"gethostbyaddr returned name > 100 chars\n");
! exit(244);
! }
! strcpy(hostname,hp->h_name);
! } else {
! /* assume inet dot form is no more than 100 chars */
! strcpy(hostname,(char *)inet_ntoa(laddr.sin_addr));
! }
!
#ifdef unicos61
#define SIZEOF_INADDR SIZEOF_in_addr
#else
***************
*** 1395,1402 ****
--- 1410,1421 ----
#define SIZEOF_INADDR sizeof(struct in_addr)
#endif
+ if (status = krb5_sname_to_principal(hostname, "host", KRB5_NT_SRV_HST,
+ &server)) {
+ /*DREW
if (status = krb5_sname_to_principal(NULL, "host", KRB5_NT_SRV_HST,
&server)) {
+ */
syslog(LOG_ERR, "parse server name %s: %s", "host",
error_message(status));
exit(1);