$NetBSD$

--- xlock/passwd.c.orig	Thu Apr 25 09:36:27 2002
+++ xlock/passwd.c
@@ -352,9 +352,9 @@
 
 #if defined( HAVE_KRB4 ) || defined( HAVE_KRB5 )
 #ifdef HAVE_KRB4
-#include <krb.h>
+#include <kerberosIV/krb.h>
 #else /* HAVE_KRB5 */
-#include <krb5.h>
+#include <krb5/krb5.h>
 #endif
 static int  krb_check_password(struct passwd *, char *);
 
@@ -1598,155 +1598,84 @@
 #endif /* HAVE_KRB4 */
 
 #ifdef HAVE_KRB5
-/*-
- * Pretty much all of this was snatched out of the kinit from the Kerberos5b6
- * distribution.  The reason why I felt it was necessary to use kinit was
- * that if someone is locked for a long time, their credentials could expire,
- * so xlock must be able to get a new ticket.  -- dah <rodmur@ecst.csuchico.edu>
- */
-#define KRB5_DEFAULT_OPTIONS 		0
-#define KRB5_DEFAULT_LIFE 60*60*10	/* 10 hours */
+int
+fake_prompter(krb5_context c, void *d, const char *b, int n, krb5_prompt p[])
+{
+	return 0;
+}
+
 static int
 krb_check_password(struct passwd *pwd, char *pass)
 {
-	krb5_context kcontext;
-	krb5_timestamp now;
-	krb5_ccache ccache = NULL;
+        krb5_get_init_creds_opt opt;
+	krb5_error_code ret;
 	krb5_principal me;
-	krb5_principal server;
-	int         options = KRB5_DEFAULT_OPTIONS;
-	krb5_deltat lifetime = KRB5_DEFAULT_LIFE;
-	krb5_error_code code;
-	krb5_creds  my_creds;
-	char       *client_name;
-	krb5_address **addrs = (krb5_address **) 0;
-	krb5_preauthtype *preauth = NULL;
+	krb5_context context;
+	krb5_ccache ccache;
+	krb5_realm realm;
+	krb5_creds cred;
+
+	memset(&cred, 0x0, sizeof(cred));
+	ret = krb5_init_context(&context);
+	if (ret) {
+		com_err(ProgramName, ret, "unable to initialise krb5");
+		return False;
+	}
 
-        krb5_deltat rlife = 0;
+	/* XXX XAX: deal with forwardable/proxiable tickets */
 
-	krb5_data   tgtname =
-	{
-		0,
-		KRB5_TGS_NAME_SIZE,
-		KRB5_TGS_NAME
-	};
-
-	krb5_init_context(&kcontext);
-	krb5_init_ets(kcontext);
-
-	if ((code = krb5_timeofday(kcontext, &now))) {
-		com_err(ProgramName, code, "while getting time of day");
-		return False;	/* seems better to deny access, than just exit, which
-				   was what happened in kinit  */
-	}
-	if ((code = krb5_cc_default(kcontext, &ccache))) {
-		com_err(ProgramName, code, "while getting default ccache");
+	ret = krb5_get_default_principal(context, &me);
+	if (ret) {
+		com_err(ProgramName, ret, "unable to get default principal");
 		return False;
 	}
-	code = krb5_cc_get_principal(kcontext, ccache, &me);
-	if (code) {
-		if ((code = krb5_parse_name(kcontext, pwd->pw_name, &me))) {
-			com_err(ProgramName, code, "when parsing name %s", pwd->pw_name);
-			return False;
-		}
-	}
-	if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
-		com_err(ProgramName, code, "when unparsing name");
+
+	ret = krb5_cc_default(context, &ccache);
+	if (ret) {
+		com_err(ProgramName, ret, "unable to resolve credentials "
+		    "cache");
 		return False;
 	}
-	(void) memset((char *) &my_creds, 0, sizeof (my_creds));
 
+        krb5_get_init_creds_opt_init(&opt);
+        krb5_get_init_creds_opt_set_default_flags(context, "xlock",realm, &opt);
 
-	if ((code = 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))) {
-		com_err(ProgramName, code, "while building server name");
+	ret = krb5_get_init_creds_password(context, &cred, me,
+	    pass, (krb5_prompter_fct)fake_prompter, NULL, 0, NULL, &opt);
+	switch (ret) {
+	case 0:
+		break;
+	case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+	case KRB5KRB_AP_ERR_MODIFIED:
+		com_err(ProgramName, ret, "krb5 password incorrect");
+		return False;
+	default:
+		com_err(ProgramName, ret, "krb5_get_init_creds failed");
 		return False;
 	}
 
+	/* XXX XAX: I cannot necessarily verify the credentials that I
+	 *          just received, since I may not have any credentials.
+	 *          I'll look into this later.
+	 */
 
-	my_creds.client = me;
-	my_creds.server = server;
-
-	my_creds.times.starttime = 0;
-
-	my_creds.times.renew_till = 0;
-
-	/*
-        ** find our default ticket, and copy out renewable, forwardable info.
-        */
-	{
-	krb5_cc_cursor cur;
-	krb5_creds creds;
-
-	if ((code = krb5_cc_start_seq_get(kcontext, ccache, &cur))) {
-	    com_err(ProgramName, code, "while starting to retrieve tickets");
-	} else {
-
-	    while (!(code = krb5_cc_next_cred(kcontext, ccache, &cur, &creds))) {
-		if (creds.server->length == 2 &&
-		        strcmp(creds.server->realm.data, me->realm.data) == 0 &&
-		        strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
-		        strcmp((char *)creds.server->data[1].data, me->realm.data) == 0 &&
-		        creds.times.endtime > now) {
-		    /*
-                    ** this is the krbtgt token to steal options from...
-		    */
-	    
-		    if (creds.times.renew_till) {
-		       options |= KDC_OPT_RENEWABLE;
-		       my_creds.times.renew_till = creds.times.renew_till;
-		    }
-		    if (creds.ticket_flags & TKT_FLG_FORWARDABLE) {
-		       options |= KDC_OPT_FORWARDABLE;
-		    }
-		}
-		krb5_free_cred_contents(kcontext, &creds);
-	    }
-        }
-
-	}
-
-	if (strlen(pass) == 0)
-		(void) strcpy(pass, "*");
-	/* if pass is NULL, krb5_get_in_tkt_with_password will prompt with
-	   krb5_default_pwd_prompt1 for password, you don't want that in
-	   this application, most likely the user won't have '*' for a
-	   password -- dah <rodmur@ecst.csuchico.edu> */
-
-	code = krb5_get_in_tkt_with_password(kcontext, options, addrs,
-					     NULL, preauth, pass, 0,
-					     &my_creds, 0);
-
-	(void) memset(pass, 0, sizeof (pass));
-
-	if (code) {
-		if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
-			return False;	/* bad password entered */
-		else {
-			com_err(ProgramName, code, "while getting initial credentials");
-			return False;
-		}
-	}
-	code = krb5_cc_initialize(kcontext, ccache, me);
-	if (code != 0) {
-		com_err(ProgramName, code, "when initializing cache");
+	ret = krb5_cc_initialize(context, ccache, cred.client);
+	if (ret) {
+		com_err(ProgramName, ret, "krb5_cc_initialize");
 		return False;
 	}
-	code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
-	if (code) {
-		com_err(ProgramName, code, "while storing credentials");
+	ret = krb5_cc_store_cred(context, ccache, &cred);
+	if (ret) {
+		com_err(ProgramName, ret, "krb5_cc_store_cred");
 		return False;
 	}
-	krb5_free_principal(kcontext, server);
 
-	krb5_free_context(kcontext);
+	/* Clean up */
+	krb5_free_creds_contents(context, &cred);
+	krb5_cc_close(context, ccache);
+	krb5_free_context(context);
 
-	return True;		/* success */
+	return True;
 }
 #endif /* HAVE_KRB5 */
 
