1 /* ========================================================================
2  * Copyright 1988-2007 University of Washington
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *
11  * ========================================================================
12  */
13 
14 /*
15  * Program:	Kerberos 5 check password
16  *
17  * Author:	Mark Crispin
18  *		Networks and Distributed Computing
19  *		Computing & Communications
20  *		University of Washington
21  *		Administration Building, AG-44
22  *		Seattle, WA  98195
23  *		Internet: MRC@CAC.Washington.EDU
24  *
25  * Date:	1 August 1988
26  * Last Edited:	11 October 2007
27  */
28 
29 /* Check password
30  * Accepts: login passwd struct
31  *	    password string
32  *	    argument count
33  *	    argument vector
34  * Returns: passwd struct if password validated, NIL otherwise
35  */
36 
checkpw(struct passwd * pw,char * pass,int argc,char * argv[])37 struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
38 {
39   char svrnam[MAILTMPLEN],cltnam[MAILTMPLEN];
40   krb5_context ctx;
41   krb5_timestamp now;
42   krb5_principal service;
43   krb5_ccache ccache;
44   krb5_error_code code;
45   krb5_creds *crd = (krb5_creds *) memset (fs_get (sizeof (krb5_creds)),0,
46 						   sizeof (krb5_creds));
47   struct passwd *ret = NIL;
48   if (*pass) {			/* only if password non-empty */
49 				/* make service name */
50     sprintf (svrnam,"%.80s@%.512s",
51 	     (char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
52 	     tcp_serverhost ());
53 				/* make client name with principal */
54     sprintf (cltnam,"%.80s/%.80s",pw->pw_name,
55 	     (char *) mail_parameters (NIL,GET_SERVICENAME,NIL));
56 				/* get a context */
57     if (!krb5_init_context (&ctx)) {
58 				/* get time, client and server principals */
59       if (!krb5_timeofday (ctx,&now) &&
60 	/* Normally, kerb_cp_svr_name (defined/set in env_unix.c) is NIL, so
61 	 * only the user name is used as a client principal.  A few sites want
62 	 * to have separate client principals for different services, but many
63 	 * other sites vehemently object...
64 	 */
65 	  !krb5_parse_name (ctx,kerb_cp_svr_name ? cltnam : pw->pw_name,
66 			    &crd->client) &&
67 	  !krb5_parse_name (ctx,svrnam,&service) &&
68 	  !krb5_build_principal_ext(ctx,&crd->server,
69 				    krb5_princ_realm (ctx,crd->client)->length,
70 				    krb5_princ_realm (ctx,crd->client)->data,
71 				    KRB5_TGS_NAME_SIZE,KRB5_TGS_NAME,
72 				    krb5_princ_realm (ctx,crd->client)->length,
73 				    krb5_princ_realm (ctx,crd->client)->data,
74 				    0)) {
75 				/* expire in 3 minutes */
76 	crd->times.endtime = now + (3 * 60);
77 	if (krb5_cc_resolve (ctx,"MEMORY:pwk",&ccache) ||
78 	    krb5_cc_initialize (ctx,ccache,crd->client)) ccache = 0;
79 	if (!krb5_get_in_tkt_with_password (ctx,NIL,NIL,NIL,NIL,pass,ccache,
80 					    crd,0) &&
81 	    !krb5_verify_init_creds (ctx,crd,service,0,ccache ? &ccache : 0,0))
82 	  ret = pw;
83 	krb5_free_creds (ctx,crd);/* flush creds and service principal */
84 	krb5_free_principal (ctx,service);
85       }
86       krb5_free_context (ctx);	/* don't need context any more */
87     }
88   }
89   return ret;
90 }
91