- Complete re-write of sasc.
[dragonfly.git] / crypto / heimdal / lib / auth / afskauthlib / verify.c
1 /*
2  * Copyright (c) 1995-2000 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.25 2001/06/18 13:11:33 assar 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     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     if (krb5_config_get_bool(context, NULL,
167                              "libdefaults",
168                              "krb4_get_tickets",
169                              NULL)) {
170         CREDENTIALS c;
171         krb5_creds mcred, cred;
172         krb5_realm realm;
173
174         krb5_get_default_realm(context, &realm);
175         krb5_make_principal(context, &mcred.server, realm,
176                             "krbtgt",
177                             realm,
178                             NULL);
179         free (realm);
180         ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
181         if(ret == 0) {
182             ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c);
183             if(ret)
184                 krb5_warn(context, ret, "converting creds");
185             else {
186                 set_krbtkfile(pwd->pw_uid);
187                 tf_setup(&c, c.pname, c.pinst); 
188             }
189             memset(&c, 0, sizeof(c));
190             krb5_free_creds_contents(context, &cred);
191         } else
192             syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", 
193                    krb5_get_err_text(context, ret));
194             
195         krb5_free_principal(context, mcred.server);
196     }
197     if (!pag_set && k_hasafs()) {
198         k_setpag();
199         pag_set = 1;
200     }
201
202     if (pag_set)
203         krb5_afslog_uid_home(context, ccache, NULL, NULL, 
204                              pwd->pw_uid, pwd->pw_dir);
205 #endif
206 out:
207     if(ret && !quiet)
208         printf ("%s\n", krb5_get_err_text (context, ret));
209     return ret;
210 }
211 #endif
212
213 #ifdef KRB4
214 static int
215 verify_krb4(struct passwd *pwd,
216             char *password,
217             int32_t *exp,
218             int quiet)
219 {
220     int ret = 1;
221     char lrealm[REALM_SZ];
222     
223     if (krb_get_lrealm (lrealm, 1) != KFAILURE) {
224         set_krbtkfile(pwd->pw_uid);
225         ret = krb_verify_user (pwd->pw_name, "", lrealm, password,
226                                KRB_VERIFY_SECURE, NULL);
227         if (ret == KSUCCESS) {
228             if (!pag_set && k_hasafs()) {
229                 k_setpag ();
230                 pag_set = 1;
231             }
232             if (pag_set)
233                 krb_afslog_uid_home (0, 0, pwd->pw_uid, pwd->pw_dir);
234         } else if (!quiet)
235             printf ("%s\n", krb_get_err_text (ret));
236     }
237     return ret;
238 }
239 #endif
240
241 int
242 afs_verify(char *name,
243            char *password,
244            int32_t *exp,
245            int quiet)
246 {
247     int ret = 1;
248     struct passwd *pwd = k_getpwnam (name);
249
250     if(pwd == NULL)
251         return 1;
252
253     if (!pag_set && k_hasafs()) {
254         k_setpag();
255         pag_set=1;
256     }
257
258     if (ret)
259         ret = unix_verify_user (name, password);
260 #ifdef KRB5
261     if (ret)
262         ret = verify_krb5(pwd, password, exp, quiet);
263 #endif
264 #ifdef KRB4
265     if(ret)
266         ret = verify_krb4(pwd, password, exp, quiet);
267 #endif
268     return ret;
269 }
270
271 char *
272 afs_gettktstring (void)
273 {
274     char *ptr;
275     struct passwd *pwd;
276
277     if (!correct_tkfilename) {
278         ptr = getenv("LOGNAME"); 
279         if (ptr != NULL && ((pwd = getpwnam(ptr)) != NULL)) {
280             set_krb5ccname(pwd->pw_uid);
281 #ifdef KRB4
282             set_krbtkfile(pwd->pw_uid);
283             if (!pag_set && k_hasafs()) {
284                 k_setpag();
285                 pag_set=1;
286             }
287 #endif
288         } else {
289             set_spec_krbtkfile();
290         }
291     }
292 #ifdef KRB5
293     esetenv("KRB5CCNAME",krb5ccname,1);
294 #endif
295 #ifdef KRB4
296     esetenv("KRBTKFILE",krbtkfile,1);
297     return krbtkfile;
298 #else
299     return "";
300 #endif
301 }