]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - crypto/heimdal/lib/auth/afskauthlib/verify.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / crypto / heimdal / lib / auth / afskauthlib / verify.c
1 /*
2  * Copyright (c) 1995-2004 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 14203 2004-09-08 09:02:59Z joda $");
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     ret = krb5_init_context(&context);
127     if (ret) {
128         syslog(LOG_AUTH|LOG_DEBUG, "krb5_init_context failed: %d", ret);
129         goto out;
130     }
131
132     ret = krb5_parse_name (context, pwd->pw_name, &principal);
133     if (ret) {
134         syslog(LOG_AUTH|LOG_DEBUG, "krb5_parse_name: %s", 
135                krb5_get_err_text(context, ret));
136         goto out;
137     }
138
139     set_krb5ccname(pwd->pw_uid);
140     ret = krb5_cc_resolve(context, krb5ccname, &ccache);
141     if(ret) {
142         syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_resolve: %s", 
143                krb5_get_err_text(context, ret));
144         goto out;
145     }
146
147     ret = krb5_verify_user_lrealm(context,
148                                   principal,
149                                   ccache,
150                                   password,
151                                   TRUE,
152                                   NULL);
153     if(ret) {
154         syslog(LOG_AUTH|LOG_DEBUG, "krb5_verify_user: %s", 
155                krb5_get_err_text(context, ret));
156         goto out;
157     }
158
159     if(chown(krb5_cc_get_name(context, ccache), pwd->pw_uid, pwd->pw_gid)) {
160         syslog(LOG_AUTH|LOG_DEBUG, "chown: %s", 
161                krb5_get_err_text(context, errno));
162         goto out;
163     }
164
165 #ifdef KRB4
166     {
167         krb5_realm realm = NULL;
168         krb5_boolean get_v4_tgt;
169
170         krb5_get_default_realm(context, &realm);
171         krb5_appdefault_boolean(context, "afskauthlib", 
172                                 realm,
173                                 "krb4_get_tickets", FALSE, &get_v4_tgt);
174         if (get_v4_tgt) {
175             CREDENTIALS c;
176             krb5_creds mcred, cred;
177
178             krb5_cc_clear_mcred(&mcred);
179
180             krb5_make_principal(context, &mcred.server, realm,
181                                 "krbtgt",
182                                 realm,
183                                 NULL);
184             ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
185             if(ret == 0) {
186                 ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c);
187                 if(ret)
188                     krb5_warn(context, ret, "converting creds");
189                 else {
190                     set_krbtkfile(pwd->pw_uid);
191                     tf_setup(&c, c.pname, c.pinst); 
192                 }
193                 memset(&c, 0, sizeof(c));
194                 krb5_free_cred_contents(context, &cred);
195             } else
196                 syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", 
197                        krb5_get_err_text(context, ret));
198             
199             krb5_free_principal(context, mcred.server);
200         }
201         free (realm);
202         if (!pag_set && k_hasafs()) {
203             k_setpag();
204             pag_set = 1;
205         }
206
207         if (pag_set)
208             krb5_afslog_uid_home(context, ccache, NULL, NULL, 
209                                  pwd->pw_uid, pwd->pw_dir);
210     }
211 #endif
212  out:
213     if(ret && !quiet)
214         printf ("%s\n", krb5_get_err_text (context, ret));
215     return ret;
216 }
217 #endif
218
219 #ifdef KRB4
220 static int
221 verify_krb4(struct passwd *pwd,
222             char *password,
223             int32_t *exp,
224             int quiet)
225 {
226     int ret = 1;
227     char lrealm[REALM_SZ];
228     
229     if (krb_get_lrealm (lrealm, 1) != KFAILURE) {
230         set_krbtkfile(pwd->pw_uid);
231         ret = krb_verify_user (pwd->pw_name, "", lrealm, password,
232                                KRB_VERIFY_SECURE, NULL);
233         if (ret == KSUCCESS) {
234             if (!pag_set && k_hasafs()) {
235                 k_setpag ();
236                 pag_set = 1;
237             }
238             if (pag_set)
239                 krb_afslog_uid_home (0, 0, pwd->pw_uid, pwd->pw_dir);
240         } else if (!quiet)
241             printf ("%s\n", krb_get_err_text (ret));
242     }
243     return ret;
244 }
245 #endif
246
247 int
248 afs_verify(char *name,
249            char *password,
250            int32_t *exp,
251            int quiet)
252 {
253     int ret = 1;
254     struct passwd *pwd = k_getpwnam (name);
255
256     if(pwd == NULL)
257         return 1;
258
259     if (!pag_set && k_hasafs()) {
260         k_setpag();
261         pag_set=1;
262     }
263
264     if (ret)
265         ret = unix_verify_user (name, password);
266 #ifdef KRB5
267     if (ret)
268         ret = verify_krb5(pwd, password, exp, quiet);
269 #endif
270 #ifdef KRB4
271     if(ret)
272         ret = verify_krb4(pwd, password, exp, quiet);
273 #endif
274     return ret;
275 }
276
277 char *
278 afs_gettktstring (void)
279 {
280     char *ptr;
281     struct passwd *pwd;
282
283     if (!correct_tkfilename) {
284         ptr = getenv("LOGNAME"); 
285         if (ptr != NULL && ((pwd = getpwnam(ptr)) != NULL)) {
286             set_krb5ccname(pwd->pw_uid);
287 #ifdef KRB4
288             set_krbtkfile(pwd->pw_uid);
289             if (!pag_set && k_hasafs()) {
290                 k_setpag();
291                 pag_set=1;
292             }
293 #endif
294         } else {
295             set_spec_krbtkfile();
296         }
297     }
298 #ifdef KRB5
299     esetenv("KRB5CCNAME",krb5ccname,1);
300 #endif
301 #ifdef KRB4
302     esetenv("KRBTKFILE",krbtkfile,1);
303     return krbtkfile;
304 #else
305     return "";
306 #endif
307 }