[178] in Info-AFS_Redistribution

home help back first fref pref prev next nref lref last post

Re: X11R4 XDM authentication and/or additional documentation

daemon@ATHENA.MIT.EDU (Paul Traina)
Wed Jun 26 17:55:55 1991

From: Paul Traina <pst@stanford.edu>
To: Scanner <scanner@rpi.edu>, cball@bu-it.bu.edu
Cc: Info-AFS@transarc.com
In-Reply-To: Your message of "Wed, 26 Jun 91 15:56:57 EDT."
Date: Wed, 26 Jun 91 14:00:21 -0700

  > Has anyone out there implemented a X11R4 XDM which does
  > AFS/Kerberos authentication?

Yes,  I have -- it supports both MIT kerberos and Transarc Kerberos
depending upon how you have defined it.  If you do
	-DAFS, it does AFS/Kerberos (nothing else needed)

	-DAFS -DKERBEROS, does both -- however you need a special
		package developed by qjb@mit.edu (maintained by
		probe now?) for this to work.
  
  One of the recent set of changes was to have XDM call "klog" as part
  of the verify step. This gives behavior similar to the Transarc login
  where if the klog fails it back off and try regular unix
  authentication.

Ick, the "real" code in klog is one call called ka_UserAuthenticate.
  
  Current I kludge the "pagsh" stuff since you can't get source to
  "pagsh" by just running xdm under via the undocumented "-c" option for
  pagsh. This only works if each "xdm" is only managing one display. If
  it manages more than one display then you'll have to wait for one of
  my next xdm changes which runs each display-manager under a new pag.

Pagsh really only does one thing, forks and then executed the setpag()
routine.
  
  I'm clearly working around deficiencies for lack of source to creating
  a PAG.

I don't think I'm giving away any of Transarc's greatest secrets when
I demostrate (in this code) how to call either of those routines.  With
this info, you should be able to transarcify any login-type program.

Best,

Paul

P.S. This code has been running at Stanford for 6+ months and is available
	in /afs/ir.stanford.edu/users/p/pst/src/athena/xdm.  (which has
	other changes such as support for a console window at login
	prompt.)


*** /afs/ir/src/X11R4/mit/clients/xdm/verify.c	Fri Oct 12 12:17:48 1990
--- ./verify.c	Tue Oct  9 23:57:30 1990
***************
*** 31,40 ****
--- 31,85 ----
  # include	<grp.h>
  # endif
  
+ #ifdef	KERBEROS
+ #include <krb.h>
+ #include <netdb.h>
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #   ifdef BIND_HACK
+ #   include <arpa/nameser.h>
+ #   include <arpa/resolv.h>
+ #   endif BIND_HACK
+ #   ifdef AFS
+ #   include "../login/aklog.h"
+ #   include <setjmp.h>
+ #   endif AFS
+ #endif KERBEROS
+ 
+ #ifdef	KERBEROS
+ #define	KRB_ENVIRON	"KRBTKFILE"	/* ticket file environment var */
+ #define	KRB_TK_DIR	"/tmp/tkt_"	/* where to put the ticket */
+ #define	MAXPWSIZE	128		/* biggest kerberos password */
+ 
+ extern char *krb_err_txt[];		/* from libkrb */
+ 
+ AUTH_DAT *kdata = (AUTH_DAT *) NULL;
+ KTEXT ticket = (KTEXT) NULL;
+ char tkfile[MAXPATHLEN];
+ int krbflag = 0;
+ char *getenv();
+ 
+ #  ifdef AFS
+ jmp_buf aklog_jmp;
+ #  endif AFS
+ #endif	KERBEROS
+ 
  struct passwd joeblow = {
  	"Nobody", "***************"
  };
  
+ 
+ #if defined(KERBEROS) && defined(AFS)
+ void
+ aklog_login_exit ARGS((char c))
+ {
+ 	fflush(stderr);
+ 	fflush(stdout);
+ 	longjmp(aklog_jmp, 1);
+ }
+ extern int LogError();
+ #endif KERBEROS && AFS
+ 
  Verify (d, greet, verify)
  struct display		*d;
  struct greet_info	*greet;
***************
*** 45,50 ****
--- 90,106 ----
  	char		**userEnv (), **systemEnv (), **parseArgs ();
  	char		*shell, *home;
  	char		**argv;
+ #ifdef	KERBEROS
+ 	char		pp[9], *namep;
+ 	int		krbval;
+ 	char		realm[REALM_SZ];
+ 	int		kpass_ok = 0;
+ 	int		lpass_ok = 0;
+ #else	KERBEROS
+ #ifdef	AFS		/* AFS without MIT KERBEROS */
+ 	int		reason;
+ #endif	AFS
+ #endif	KERBEROS
  
  	p = getpwnam (greet->name);
  	if (!p || strlen (greet->name) == 0)
***************
*** 51,62 ****
  		p = &joeblow;
  	Debug ("Verify %s %s\n", greet->name, greet->password);
  
! 	if (strcmp (crypt (greet->password, p->pw_passwd),
! 		    p->pw_passwd)) {
! 		Debug ("verify failed\n");
! 		bzero(greet->password, strlen(greet->password));
  		return 0;
  	}
  
  	Debug ("verify succeeded\n");
  	bzero(greet->password, strlen(greet->password));
--- 107,190 ----
  		p = &joeblow;
  	Debug ("Verify %s %s\n", greet->name, greet->password);
  
! #ifdef	KERBEROS
! 	if (!strcmp (crypt (greet->password, p->pw_passwd), p->pw_passwd))
! 		lpass_ok = 1;
! 
! 	if (p->pw_uid) {	/* don't get tickets for root */
! 		if (krb_get_lrealm(realm, 1) != KSUCCESS) 
! 			(void) strncpy(realm, KRB_REALM, sizeof(realm));
! 
! #  ifdef BIND_HACK
! 		/* set the nameserver timeout to be reasonable, so
! 		   people don't take 5 minutes to login.  This is
! 		   a disgusting abstraction violation. */
! 		_res.retrans = 1;
! #  endif BIND_HACK
! 		sprintf(tkfile, "%s%d", KRB_TK_DIR, p->pw_uid);
! 
! 		krb_set_tkt_string(tkfile);
! 
! 		if (setreuid(p->pw_uid, -1) < 0) {
! 			/* can't set ruid to user! */
! 			krbval = -1;
! 			LogError("Can't set ruid for ticket file %s\n", tkfile);
! 		} else
! 			krbval = krb_get_pw_in_tkt(greet->name, "", realm,
! 					"krbtgt", realm, DEFAULT_TKT_LIFE,
! 					greet->password);
! 
! 		switch(krbval) {
! 			case INTK_OK:
! 			case INTK_W_NOTALL:
! 				kpass_ok = 1;
! 				krbflag  = 1;
! 				break;
! 
! 			/* These errors should be silent so the kerberos
! 			   database can't be probed */
! 
! 			case KDC_NULL_KEY:
! 			case KDC_PR_UNKNOWN:
! 			case INTK_BADPW:
! 			case KDC_PR_N_UNIQUE:
! 			case -1:
! 				break;
! 
! 			default:
! 				LogError("Unknown kerberos error: user=%s %s\n",
! 					greet->name, krb_err_txt[krbval]);
! 		}
! 	}
! 
! 	/* Policy: If the local password or the kerberos password
! 	   is good, the user is good.  We do trust the kerberos
! 	   password, but it is dangerous, as the kerberos server
! 	   could be spoofed (not easy, but possible).
! 	*/
! 
! 	bzero(greet->password, strlen(greet->password));
! 
! 	if (!lpass_ok && !kpass_ok)
  		return 0;
+ 
+ #else	KERBEROS		/* not using kerberos */
+ 
+ #ifdef	AFS			/* AFS without MIT kerberos */
+ 	if (ka_UserAuthenticate(greet->name, /* inst */ "", /* realm */ 0,
+ 				greet->password, /* sepag */ 1, &reason)) {
+ 		Debug ("afs verify failed, trying normal unix verify\n");
+ #endif
+ 		if (strcmp (crypt (greet->password, p->pw_passwd),
+ 			    p->pw_passwd)) {
+ 			Debug ("verify failed\n");
+ 			bzero(greet->password, strlen(greet->password));
+ 			return 0;
+ 		}
+ #ifdef	AFS
  	}
+ #endif  AFS
+ #endif	KERBEROS
  
  	Debug ("verify succeeded\n");
  	bzero(greet->password, strlen(greet->password));
***************
*** 84,89 ****
--- 212,243 ----
  	printEnv (verify->systemEnviron);
  	Debug ("end of environments\n");
  
+ #if defined(AFS) && defined(KERBEROS)
+ 	/* set up the AFS environment from MIT kerberos info */
+ 
+ 	(void) setpag();
+ 
+ 	if (krbflag) {		/* if we've got a valid ticket */
+ 		static char *ak_argv[] = { "aklog" };
+ 		aklog_params params;
+ 
+ 		(void) chown(getenv(KRB_ENVIRON, verify->uid));
+ 
+ 		aklog_init_params(&params);
+ 
+ 		/* we don't want AKLOG to exit on us when done! */
+ 		params.exitprog = aklog_login_exit;
+ 		params.pstderr  = (void(*)ARGS((char *))) LogError;
+ 		params.pstderr	= (void(*)ARGS((char *))) LogError;
+ 
+ 		if (setjmp(aklog_jmp) == 0)
+ 			aklog(sizeof(ak_argv) / sizeof (char *),
+ 				ak_argv, &params);
+ 
+ 		
+ 	}
+ #endif	AFS && KERBEROS
+ 
  	return 1;
  }
  
***************
*** 101,106 ****
--- 255,264 ----
  	env = setEnv (env, "USER", user);
  	env = setEnv (env, "PATH", d->userPath);
  	env = setEnv (env, "SHELL", shell);
+ #ifdef	KERBEROS
+ 	if (krbflag)
+ 		env = setEnv (env, KRB_ENVIRON, tkfile);
+ #endif
  	return env;
  }
  


home help back first fref pref prev next nref lref last post