Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / lib / auth / afskauthlib / verify.c
1 /*
2  * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  * 
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 RCSID("$Id: verify.c,v 1.20 1999/12/02 16:58:37 joda Exp $");
37 #endif
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <pwd.h>
41 #ifdef KRB5
42 #include <krb5.h>
43 #endif
44 #ifdef KRB4
45 #include <krb.h>
46 #include <kafs.h>
47 #endif
48 #include <roken.h>
49
50 #ifdef KRB5
51 static char krb5ccname[128];
52 #endif
53 #ifdef KRB4
54 static char krbtkfile[128];
55 #endif
56
57 /* 
58    In some cases is afs_gettktstring called twice (once before
59    afs_verify and once after afs_verify).
60    In some cases (rlogin with access allowed via .rhosts) 
61    afs_verify is not called!
62    So we can't rely on correct value in krbtkfile in some
63    cases!
64 */
65
66 static int correct_tkfilename=0;
67 static int pag_set=0;
68
69 #ifdef KRB4
70 static void
71 set_krbtkfile(uid_t uid)
72 {
73     snprintf (krbtkfile, sizeof(krbtkfile), "%s%d", TKT_ROOT, (unsigned)uid);
74     krb_set_tkt_string (krbtkfile);
75     correct_tkfilename = 1;
76 }
77 #endif
78
79 /* XXX this has to be the default cache name, since the KRB5CCNAME
80  * environment variable isn't exported by login/xdm
81  */
82
83 #ifdef KRB5
84 static void
85 set_krb5ccname(uid_t uid)
86 {
87     snprintf (krb5ccname, sizeof(krb5ccname), "FILE:/tmp/krb5cc_%d", uid);
88 #ifdef KRB4
89     snprintf (krbtkfile, sizeof(krbtkfile), "%s%d", TKT_ROOT, (unsigned)uid);
90 #endif
91     correct_tkfilename = 1;
92 }
93 #endif
94
95 static void
96 set_spec_krbtkfile(void)
97 {
98     int fd;
99 #ifdef KRB4
100     snprintf (krbtkfile, sizeof(krbtkfile), "%s_XXXXXX", TKT_ROOT);
101     fd = mkstemp(krbtkfile);
102     close(fd);
103     unlink(krbtkfile); 
104     krb_set_tkt_string (krbtkfile);
105 #endif
106 #ifdef KRB5
107     snprintf(krb5ccname, sizeof(krb5ccname),"FILE:/tmp/krb5cc_XXXXXX");
108     fd=mkstemp(krb5ccname+5);
109     close(fd);
110     unlink(krb5ccname+5);
111 #endif
112 }
113
114 #ifdef KRB5
115 static int
116 verify_krb5(struct passwd *pwd,
117             char *password,
118             int32_t *exp,
119             int quiet)
120 {
121     krb5_context context;
122     krb5_error_code ret;
123     krb5_ccache ccache;
124     krb5_principal principal;
125     
126     krb5_init_context(&context);
127
128     ret = krb5_parse_name (context, pwd->pw_name, &principal);
129     if (ret) {
130         syslog(LOG_AUTH|LOG_DEBUG, "krb5_parse_name: %s", 
131                krb5_get_err_text(context, ret));
132         goto out;
133     }
134
135     set_krb5ccname(pwd->pw_uid);
136     ret = krb5_cc_resolve(context, krb5ccname, &ccache);
137     if(ret) {
138         syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_resolve: %s", 
139                krb5_get_err_text(context, ret));
140         goto out;
141     }
142
143     ret = krb5_verify_user_lrealm(context,
144                                   principal,
145                                   ccache,
146                                   password,
147                                   TRUE,
148                                   NULL);
149     if(ret) {
150         syslog(LOG_AUTH|LOG_DEBUG, "krb5_verify_user: %s", 
151                krb5_get_err_text(context, ret));
152         goto out;
153     }
154
155     if(chown(krb5_cc_get_name(context, ccache), pwd->pw_uid, pwd->pw_gid)) {
156         syslog(LOG_AUTH|LOG_DEBUG, "chown: %s", 
157                krb5_get_err_text(context, errno));
158         goto out;
159     }
160
161 #ifdef KRB4
162     if (krb5_config_get_bool(context, NULL,
163                              "libdefaults",
164                              "krb4_get_tickets",
165                              NULL)) {
166         CREDENTIALS c;
167         krb5_creds mcred, cred;
168         krb5_realm realm;
169
170         krb5_get_default_realm(context, &realm);
171         krb5_make_principal(context, &mcred.server, realm,
172                             "krbtgt",
173                             realm,
174                             NULL);
175         free (realm);
176         ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
177         if(ret == 0) {
178             ret = krb524_convert_creds_kdc(context, ccache, &cred, &c);
179             if(ret)
180                 krb5_warn(context, ret, "converting creds");
181             else {
182                 set_krbtkfile(pwd->pw_uid);
183                 tf_setup(&c, c.pname, c.pinst); 
184             }
185             memset(&c, 0, sizeof(c));
186             krb5_free_creds_contents(context, &cred);
187         } else
188             syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", 
189                    krb5_get_err_text(context, ret));
190             
191         krb5_free_principal(context, mcred.server);
192     }
193     if (!pag_set && k_hasafs()) {
194         k_setpag();
195         pag_set = 1;
196         krb5_afslog_uid_home(context, ccache, NULL, NULL, 
197                              pwd->pw_uid, pwd->pw_dir);
198     }
199 #endif
200 out:
201     if(ret && !quiet)
202         printf ("%s\n", krb5_get_err_text (context, ret));
203     return ret;
204 }
205 #endif
206
207 #ifdef KRB4
208 static int
209 verify_krb4(struct passwd *pwd,
210             char *password,
211             int32_t *exp,
212             int quiet)
213 {
214     int ret = 1;
215     char lrealm[REALM_SZ];
216     
217     if (krb_get_lrealm (lrealm, 1) != KFAILURE) {
218         set_krbtkfile(pwd->pw_uid);
219         ret = krb_verify_user (pwd->pw_name, "", lrealm, password,
220                                KRB_VERIFY_SECURE, NULL);
221         if (ret == KSUCCESS) {
222             if (!pag_set && k_hasafs()) {
223                 k_setpag ();
224                 pag_set = 1;
225                 krb_afslog_uid_home (0, 0, pwd->pw_uid, pwd->pw_dir);
226             }
227         } else if (!quiet)
228             printf ("%s\n", krb_get_err_text (ret));
229     }
230     return ret;
231 }
232 #endif
233
234 int
235 afs_verify(char *name,
236            char *password,
237            int32_t *exp,
238            int quiet)
239 {
240     int ret = 1;
241     struct passwd *pwd = k_getpwnam (name);
242
243     if(pwd == NULL)
244         return 1;
245     if (ret)
246         ret = unix_verify_user (name, password);
247 #ifdef KRB5
248     if (ret)
249         ret = verify_krb5(pwd, password, exp, quiet);
250 #endif
251 #ifdef KRB4
252     if(ret)
253         ret = verify_krb4(pwd, password, exp, quiet);
254 #endif
255     return ret;
256 }
257
258 char *
259 afs_gettktstring (void)
260 {
261     char *ptr;
262     struct passwd *pwd;
263
264     if (!correct_tkfilename) {
265         ptr = getenv("LOGNAME"); 
266         if (ptr != NULL && ((pwd = getpwnam(ptr)) != NULL)) {
267             set_krb5ccname(pwd->pw_uid);
268 #ifdef KRB4
269             set_krbtkfile(pwd->pw_uid);
270             if (!pag_set && k_hasafs()) {
271                 k_setpag();
272                 pag_set=1;
273             }
274 #endif
275         } else {
276             set_spec_krbtkfile();
277         }
278     }
279 #ifdef KRB5
280     setenv("KRB5CCNAME",krb5ccname,1);
281 #endif
282 #ifdef KRB4
283     setenv("KRBTKFILE",krbtkfile,1);
284     return krbtkfile;
285 #else
286     return "";
287 #endif
288 }