remove gcc34
[dragonfly.git] / crypto / heimdal-0.6.3 / appl / ftp / ftpd / kauth.c
blobdad4de540152479e57435063ffa06e24a6ffb593
1 /*
2 * Copyright (c) 1995, 1996, 1997, 1998 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.
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.
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.
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.
34 #include "ftpd_locl.h"
36 RCSID("$Id: kauth.c,v 1.25 1999/12/02 16:58:31 joda Exp $");
38 static KTEXT_ST cip;
39 static unsigned int lifetime;
40 static time_t local_time;
42 static krb_principal pr;
44 static int do_destroy_tickets = 1;
46 static int
47 save_tkt(const char *user,
48 const char *instance,
49 const char *realm,
50 const void *arg,
51 key_proc_t key_proc,
52 KTEXT *cipp)
54 local_time = time(0);
55 memmove(&cip, *cipp, sizeof(cip));
56 return -1;
59 static int
60 store_ticket(KTEXT cip)
62 char *ptr;
63 des_cblock session;
64 krb_principal sp;
65 unsigned char kvno;
66 KTEXT_ST tkt;
67 int left = cip->length;
68 int len;
69 int kerror;
71 ptr = (char *) cip->dat;
73 /* extract session key */
74 memmove(session, ptr, 8);
75 ptr += 8;
76 left -= 8;
78 len = strnlen(ptr, left);
79 if (len == left)
80 return(INTK_BADPW);
82 /* extract server's name */
83 strlcpy(sp.name, ptr, sizeof(sp.name));
84 ptr += len + 1;
85 left -= len + 1;
87 len = strnlen(ptr, left);
88 if (len == left)
89 return(INTK_BADPW);
91 /* extract server's instance */
92 strlcpy(sp.instance, ptr, sizeof(sp.instance));
93 ptr += len + 1;
94 left -= len + 1;
96 len = strnlen(ptr, left);
97 if (len == left)
98 return(INTK_BADPW);
100 /* extract server's realm */
101 strlcpy(sp.realm, ptr, sizeof(sp.realm));
102 ptr += len + 1;
103 left -= len + 1;
105 if(left < 3)
106 return INTK_BADPW;
107 /* extract ticket lifetime, server key version, ticket length */
108 /* be sure to avoid sign extension on lifetime! */
109 lifetime = (unsigned char) ptr[0];
110 kvno = (unsigned char) ptr[1];
111 tkt.length = (unsigned char) ptr[2];
112 ptr += 3;
113 left -= 3;
115 if (tkt.length > left)
116 return(INTK_BADPW);
118 /* extract ticket itself */
119 memmove(tkt.dat, ptr, tkt.length);
120 ptr += tkt.length;
121 left -= tkt.length;
123 /* Here is where the time should be verified against the KDC.
124 * Unfortunately everything is sent in host byte order (receiver
125 * makes wrong) , and at this stage there is no way for us to know
126 * which byteorder the KDC has. So we simply ignore the time,
127 * there are no security risks with this, the only thing that can
128 * happen is that we might receive a replayed ticket, which could
129 * at most be useless.
132 #if 0
133 /* check KDC time stamp */
135 time_t kdc_time;
137 memmove(&kdc_time, ptr, sizeof(kdc_time));
138 if (swap_bytes) swap_u_long(kdc_time);
140 ptr += 4;
142 if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
143 return(RD_AP_TIME); /* XXX should probably be better
144 code */
147 #endif
149 /* initialize ticket cache */
151 if (tf_create(TKT_FILE) != KSUCCESS)
152 return(INTK_ERR);
154 if (tf_put_pname(pr.name) != KSUCCESS ||
155 tf_put_pinst(pr.instance) != KSUCCESS) {
156 tf_close();
157 return(INTK_ERR);
161 kerror = tf_save_cred(sp.name, sp.instance, sp.realm, session,
162 lifetime, kvno, &tkt, local_time);
163 tf_close();
165 return(kerror);
168 void
169 kauth(char *principal, char *ticket)
171 char *p;
172 int ret;
174 if(get_command_prot() != prot_private) {
175 reply(500, "Request denied (bad protection level)");
176 return;
178 ret = krb_parse_name(principal, &pr);
179 if(ret){
180 reply(500, "Bad principal: %s.", krb_get_err_text(ret));
181 return;
183 if(pr.realm[0] == 0)
184 krb_get_lrealm(pr.realm, 1);
186 if(ticket){
187 cip.length = base64_decode(ticket, &cip.dat);
188 if(cip.length == -1){
189 reply(500, "Failed to decode data.");
190 return;
192 ret = store_ticket(&cip);
193 if(ret){
194 reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
195 memset(&cip, 0, sizeof(cip));
196 return;
198 do_destroy_tickets = 1;
200 if(k_hasafs())
201 krb_afslog(0, 0);
202 reply(200, "Tickets will be destroyed on exit.");
203 return;
206 ret = krb_get_in_tkt (pr.name,
207 pr.instance,
208 pr.realm,
209 KRB_TICKET_GRANTING_TICKET,
210 pr.realm,
211 DEFAULT_TKT_LIFE,
212 NULL, save_tkt, NULL);
213 if(ret != INTK_BADPW){
214 reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
215 return;
217 if(base64_encode(cip.dat, cip.length, &p) < 0) {
218 reply(500, "Out of memory while base64-encoding.");
219 return;
221 reply(300, "P=%s T=%s", krb_unparse_name(&pr), p);
222 free(p);
223 memset(&cip, 0, sizeof(cip));
227 static char *
228 short_date(int32_t dp)
230 char *cp;
231 time_t t = (time_t)dp;
233 if (t == (time_t)(-1L)) return "*** Never *** ";
234 cp = ctime(&t) + 4;
235 cp[15] = '\0';
236 return (cp);
239 void
240 klist(void)
242 int err;
244 char *file = tkt_string();
246 krb_principal pr;
248 char buf1[128], buf2[128];
249 int header = 1;
250 CREDENTIALS c;
254 err = tf_init(file, R_TKT_FIL);
255 if(err != KSUCCESS){
256 reply(500, "%s", krb_get_err_text(err));
257 return;
259 tf_close();
262 * We must find the realm of the ticket file here before calling
263 * tf_init because since the realm of the ticket file is not
264 * really stored in the principal section of the file, the
265 * routine we use must itself call tf_init and tf_close.
267 err = krb_get_tf_realm(file, pr.realm);
268 if(err != KSUCCESS){
269 reply(500, "%s", krb_get_err_text(err));
270 return;
273 err = tf_init(file, R_TKT_FIL);
274 if(err != KSUCCESS){
275 reply(500, "%s", krb_get_err_text(err));
276 return;
279 err = tf_get_pname(pr.name);
280 if(err != KSUCCESS){
281 reply(500, "%s", krb_get_err_text(err));
282 return;
284 err = tf_get_pinst(pr.instance);
285 if(err != KSUCCESS){
286 reply(500, "%s", krb_get_err_text(err));
287 return;
291 * You may think that this is the obvious place to get the
292 * realm of the ticket file, but it can't be done here as the
293 * routine to do this must open the ticket file. This is why
294 * it was done before tf_init.
297 lreply(200, "Ticket file: %s", tkt_string());
299 lreply(200, "Principal: %s", krb_unparse_name(&pr));
300 while ((err = tf_get_cred(&c)) == KSUCCESS) {
301 if (header) {
302 lreply(200, "%-15s %-15s %s",
303 " Issued", " Expires", " Principal (kvno)");
304 header = 0;
306 strlcpy(buf1, short_date(c.issue_date), sizeof(buf1));
307 c.issue_date = krb_life_to_time(c.issue_date, c.lifetime);
308 if (time(0) < (unsigned long) c.issue_date)
309 strlcpy(buf2, short_date(c.issue_date), sizeof(buf2));
310 else
311 strlcpy(buf2, ">>> Expired <<< ", sizeof(buf2));
312 lreply(200, "%s %s %s (%d)", buf1, buf2,
313 krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno);
315 if (header && err == EOF) {
316 lreply(200, "No tickets in file.");
318 reply(200, " ");
322 * Only destroy if we created the tickets
325 void
326 cond_kdestroy(void)
328 if (do_destroy_tickets)
329 dest_tkt();
330 afsunlog();
333 void
334 kdestroy(void)
336 dest_tkt();
337 afsunlog();
338 reply(200, "Tickets destroyed");
341 void
342 krbtkfile(const char *tkfile)
344 do_destroy_tickets = 0;
345 krb_set_tkt_string(tkfile);
346 reply(200, "Using ticket file %s", tkfile);
349 void
350 afslog(const char *cell)
352 if(k_hasafs()) {
353 krb_afslog(cell, 0);
354 reply(200, "afslog done");
355 } else {
356 reply(200, "no AFS present");
360 void
361 afsunlog(void)
363 if(k_hasafs())
364 k_unlog();