Subject: security/3826: login for krb5-1.0
To: None <gnats-bugs@gnats.netbsd.org>
From: Chris Jones <cjones@rupert.oscs.montana.edu>
List: netbsd-bugs
Date: 07/02/1997 14:10:23
>Number:         3826
>Category:       security
>Synopsis:       update to k5login.c and friends for krb5-1.0
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jul  4 03:50:05 1997
>Last-Modified:
>Originator:     Chris Jones
>Organization:
-------------------------------------------------------------------------------
Chris Jones                                    cjones@rupert.honors.montana.edu
           Mad scientist in training...
"Is this going to be a stand-up programming session, sir, or another bug hunt?"
>Release:        1997/7/1
>Environment:
	
System: NetBSD clydesdale.math.montana.edu 1.2G NetBSD 1.2G (CLYDESDALE) #2: Fri Jun 20 12:18:19 MDT 1997 cjones@clydesdale.math.montana.edu:/usr/src/sys/arch/i386/compile/CLYDESDALE i386


>Description:
A real Kerberos guru would know more about this than I, but here's my
take on the Kerberos 5 situation:

The API for krb5 changed between one of the betas and the current, 1.0
release.  Consequently, things that compiled under the beta no longer
work.  Here's a patch to make /usr/bin/login work with the new API
instead of the old one.

One issue here is the addition of -L/usr/local/lib and
-I/usr/local/include to the Makefile.  That's where krb5 installs to
by default, so I need these in order to compile here.  But they
weren't there before, so maybe there's a good reason for them to not
be there.

>How-To-Repeat:
	
>Fix:
diff -c -r /foo/src/usr.bin/login/Makefile /usr/src/usr.bin/login/Makefile
*** /foo/src/usr.bin/login/Makefile	Tue Jun 24 05:25:30 1997
--- /usr/src/usr.bin/login/Makefile	Wed Jul  2 13:51:27 1997
***************
*** 11,18 ****
  .if defined(KERBEROS5)
  SRCS+=	k5login.c
  DPADD+=	${LIBKRB5} ${LIBCRYPTO}
! LDADD+=	-lkrb5 -lcrypto
! CFLAGS+= -DKERBEROS5
  .elif defined(KERBEROS)
  SRCS+=	klogin.c
  DPADD+=	${LIBKRB} ${LIBDES}
--- 11,18 ----
  .if defined(KERBEROS5)
  SRCS+=	k5login.c
  DPADD+=	${LIBKRB5} ${LIBCRYPTO}
! LDADD+=	-L/usr/local/lib -lkrb5 -lcrypto -lcom_err
! CFLAGS+= -I/usr/local/include -DKERBEROS5
  .elif defined(KERBEROS)
  SRCS+=	klogin.c
  DPADD+=	${LIBKRB} ${LIBDES}
diff -c -r /foo/src/usr.bin/login/k5login.c /usr/src/usr.bin/login/k5login.c
*** /foo/src/usr.bin/login/k5login.c	Tue Feb 11 05:22:49 1997
--- /usr/src/usr.bin/login/k5login.c	Wed Jul  2 13:50:51 1997
***************
*** 43,52 ****
  #ifdef KERBEROS5
  #include <sys/param.h>
  #include <sys/syslog.h>
! #include <com_err.h>
! #include <krb5/krb5.h>
! #include <krb5/ext-proto.h>
! #include <krb5/los-proto.h>
  #include <pwd.h>
  #include <netdb.h>
  #include <stdio.h>
--- 43,49 ----
  #ifdef KERBEROS5
  #include <sys/param.h>
  #include <sys/syslog.h>
! #include <krb5.h>
  #include <pwd.h>
  #include <netdb.h>
  #include <stdio.h>
***************
*** 57,74 ****
  #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  
  krb5_data tgtname = {
      KRB5_TGS_NAME_SIZE,
      KRB5_TGS_NAME
  };
  
! /*
!  * Try no preauthentication first; then try the encrypted timestamp
!  */
! int preauth_search_list[] = {
! 	0,			
! 	KRB5_PADATA_ENC_TIMESTAMP,
! 	-1
! 	};
  
  extern int notickets;
  extern char *krbtkfile_env;
--- 54,65 ----
  #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  
  krb5_data tgtname = {
+     0,
      KRB5_TGS_NAME_SIZE,
      KRB5_TGS_NAME
  };
  
! krb5_context kcontext;
  
  extern int notickets;
  extern char *krbtkfile_env;
***************
*** 109,115 ****
  	}
  #endif
  
! 	krb5_init_ets();
  
  	/*
  	 * Root logins don't use Kerberos.
--- 100,106 ----
  	}
  #endif
  
! 	krb5_init_ets(kcontext);
  
  	/*
  	 * Root logins don't use Kerberos.
***************
*** 120,126 ****
  	 * without issuing any tickets.
  	 */
  	if (strcmp(pw->pw_name, "root") == 0 ||
! 	    krb5_get_default_realm(&realm))
  		return (1);
  
  	/*
--- 111,117 ----
  	 * without issuing any tickets.
  	 */
  	if (strcmp(pw->pw_name, "root") == 0 ||
! 	    krb5_get_default_realm(kcontext, &realm))
  		return (1);
  
  	/*
***************
*** 137,168 ****
  		"FILE:/tmp/krb5cc_root_%d.%s", pw->pw_uid, tty);
  	krbtkfile_env = tkt_location;
  
! 	principal = malloc(strlen(pw->pw_name)+strlen(instance)+2);
  	strcpy(principal, pw->pw_name);	/* XXX strcpy is safe */
  	if (strlen(instance)) {
  	    strcat(principal, "/");		/* XXX strcat is safe */
  	    strcat(principal, instance);	/* XXX strcat is safe */
  	}
  	
! 	if (kerror = krb5_cc_resolve(tkt_location, &ccache)) {
  	    syslog(LOG_NOTICE, "warning: %s while getting default ccache",
  		error_message(kerror));
  	    return(1);
  	}
  
! 	if (kerror = krb5_parse_name(principal, &me)) {
  	    syslog(LOG_NOTICE, "warning: %s when parsing name %s",
  		error_message(kerror), principal);
  	    return(1);
  	}
      
! 	if (kerror = krb5_unparse_name(me, &client_name)) {
  	    syslog(LOG_NOTICE, "warning: %s when unparsing name %s",
  		error_message(kerror), principal);
  	    return(1);
  	}
  
! 	kerror = krb5_cc_initialize (ccache, me);
  	if (kerror != 0) {
  	    syslog(LOG_NOTICE, "%s when initializing cache %s",
  		error_message(kerror), tkt_location);
--- 128,159 ----
  		"FILE:/tmp/krb5cc_root_%d.%s", pw->pw_uid, tty);
  	krbtkfile_env = tkt_location;
  
! 	principal = (char *)malloc(strlen(pw->pw_name)+strlen(instance)+2);
  	strcpy(principal, pw->pw_name);	/* XXX strcpy is safe */
  	if (strlen(instance)) {
  	    strcat(principal, "/");		/* XXX strcat is safe */
  	    strcat(principal, instance);	/* XXX strcat is safe */
  	}
  	
! 	if (kerror = krb5_cc_resolve(kcontext, tkt_location, &ccache)) {
  	    syslog(LOG_NOTICE, "warning: %s while getting default ccache",
  		error_message(kerror));
  	    return(1);
  	}
  
! 	if (kerror = krb5_parse_name(kcontext, principal, &me)) {
  	    syslog(LOG_NOTICE, "warning: %s when parsing name %s",
  		error_message(kerror), principal);
  	    return(1);
  	}
      
! 	if (kerror = krb5_unparse_name(kcontext, me, &client_name)) {
  	    syslog(LOG_NOTICE, "warning: %s when unparsing name %s",
  		error_message(kerror), principal);
  	    return(1);
  	}
  
! 	kerror = krb5_cc_initialize (kcontext, ccache, me);
  	if (kerror != 0) {
  	    syslog(LOG_NOTICE, "%s when initializing cache %s",
  		error_message(kerror), tkt_location);
***************
*** 173,184 ****
      
  	my_creds.client = me;
  
! 	if (kerror = krb5_build_principal_ext(&server,
! 					krb5_princ_realm(me)->length,
! 					krb5_princ_realm(me)->data,
  					tgtname.length, tgtname.data,
! 					krb5_princ_realm(me)->length,
! 					krb5_princ_realm(me)->data,
  					0)) {
  	    syslog(LOG_NOTICE, "%s while building server name",
  		error_message(kerror));
--- 164,176 ----
      
  	my_creds.client = me;
  
! 	if (kerror = krb5_build_principal_ext(kcontext,
! 					&server,
! 					krb5_princ_realm(kcontext, me)->length,
! 					krb5_princ_realm(kcontext, me)->data,
  					tgtname.length, tgtname.data,
! 					krb5_princ_realm(kcontext, me)->length,
! 					krb5_princ_realm(kcontext, me)->data,
  					0)) {
  	    syslog(LOG_NOTICE, "%s while building server name",
  		error_message(kerror));
***************
*** 187,200 ****
  
  	my_creds.server = server;
  
! 	kerror = krb5_os_localaddr(&my_addresses);
  	if (kerror != 0) {
  	    syslog(LOG_NOTICE, "%s when getting my address",
  		error_message(kerror));
  	    return(1);
  	}
  
! 	if (kerror = krb5_timeofday(&now)) {
  	    syslog(LOG_NOTICE, "%s while getting time of day",
  		error_message(kerror));
  	    return(1);
--- 179,192 ----
  
  	my_creds.server = server;
  
! 	kerror = krb5_os_localaddr(kcontext, &my_addresses);
  	if (kerror != 0) {
  	    syslog(LOG_NOTICE, "%s when getting my address",
  		error_message(kerror));
  	    return(1);
  	}
  
! 	if (kerror = krb5_timeofday(kcontext, &now)) {
  	    syslog(LOG_NOTICE, "%s while getting time of day",
  		error_message(kerror));
  	    return(1);
***************
*** 204,224 ****
  	my_creds.times.endtime = now + lifetime;
  	my_creds.times.renew_till = 0;
  
! 	for (i=0; preauth_search_list[i] >= 0; i++) {
! 	    kerror = krb5_get_in_tkt_with_password(options, my_addresses,
! 		                                   preauth_search_list[i],
! 		                                   ETYPE_DES_CBC_CRC,
! 						   KEYTYPE_DES,
! 						   password,
! 						   ccache,
! 						   &my_creds, 0);
! 	    if (kerror != KRB5KDC_PREAUTH_FAILED &&
! 		kerror != KRB5KRB_ERR_GENERIC)
! 		    break;
! 	}
  
! 	krb5_free_principal(server);
! 	krb5_free_addresses(my_addresses);
  
  	if (chown(&tkt_location[5], pw->pw_uid, pw->pw_gid) < 0)
  		syslog(LOG_ERR, "chown tkfile (%s): %m", &tkt_location[5]);
--- 196,211 ----
  	my_creds.times.endtime = now + lifetime;
  	my_creds.times.renew_till = 0;
  
! 	kerror = krb5_get_in_tkt_with_password(kcontext, options,
! 					       my_addresses,
! 					       NULL,
! 					       NULL,
! 					       password,
! 					       ccache,
! 					       &my_creds, 0);
  
! 	krb5_free_principal(kcontext, server);
! 	krb5_free_addresses(kcontext, my_addresses);
  
  	if (chown(&tkt_location[5], pw->pw_uid, pw->pw_gid) < 0)
  		syslog(LOG_ERR, "chown tkfile (%s): %m", &tkt_location[5]);
***************
*** 249,259 ****
  	if (krbtkfile_env == NULL)
  	    return;
  
! 	code = krb5_cc_resolve(krbtkfile_env, &ccache);
  	if (!code) {
! 	    code = krb5_cc_destroy(ccache);
  	    if (!code) {
! 		krb5_cc_close(ccache);
  	    }
  	}
  }
--- 236,246 ----
  	if (krbtkfile_env == NULL)
  	    return;
  
! 	code = krb5_cc_resolve(kcontext, krbtkfile_env, &ccache);
  	if (!code) {
! 	    code = krb5_cc_destroy(kcontext, ccache);
  	    if (!code) {
! 		krb5_cc_close(kcontext, ccache);
  	    }
  	}
  }
Only in /usr/src/usr.bin/login: k5login.o
Only in /usr/src/usr.bin/login: login
diff -c -r /foo/src/usr.bin/login/login.c /usr/src/usr.bin/login/login.c
*** /foo/src/usr.bin/login/login.c	Sun Jun 29 05:25:38 1997
--- /usr/src/usr.bin/login/login.c	Wed Jul  2 13:12:27 1997
***************
*** 75,80 ****
--- 75,84 ----
  #include <utmp.h>
  #include <util.h>
  
+ #ifdef KERBEROS5
+ #include <krb5.h>		/* Solely for definition of kcontext */
+ #endif
+ 
  #include "pathnames.h"
  
  void	 badlogin __P((char *));
***************
*** 110,115 ****
--- 114,122 ----
  char	*krbtkfile_env;
  int	authok;
  #endif
+ #ifdef KERBEROS5
+ extern krb5_context kcontext;
+ #endif
  
  struct	passwd *pwd;
  int	failures;
***************
*** 135,140 ****
--- 142,150 ----
  	char *domain, *p, *salt, *ttyn, *pwprompt;
  	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
  	char localhost[MAXHOSTNAMELEN];
+ #ifdef KERBEROS5
+ 	krb5_error_code kerror;
+ #endif
  
  	tbuf[0] = '\0';
  	rval = 0;
***************
*** 218,223 ****
--- 228,242 ----
  		++tty;
  	else
  		tty = ttyn;
+ 
+ #ifdef KERBEROS5
+ 	kerror = krb5_init_context(&kcontext);
+ 	if(kerror) {
+ 		syslog(LOG_NOTICE, "%s when initializing Kerberos context",
+ 		    error_message(kerror));
+ 		exit(1);
+ 	}
+ #endif KERBEROS5
  
  	for (cnt = 0;; ask = 1) {
  #ifdef SKEY
Only in /usr/src/usr.bin/login: login.cat1
Only in /usr/src/usr.bin/login: login.o
>Audit-Trail:
>Unformatted: