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