2 * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 #ifdef HAVE_SYS_TIME_H
53 #ifdef HAVE_SYS_TYPES_H
54 #include <sys/types.h>
69 static unsigned int lifetime
;
70 static time_t local_time
;
72 static krb_principal pr
;
74 static int do_destroy_tickets
= 1;
77 save_tkt(char *user
, char *instance
, char *realm
, void *arg
,
78 int (*key_proc
)(char*, char*, char*, void*, des_cblock
*), KTEXT
*cipp
)
81 memmove(&cip
, *cipp
, sizeof(cip
));
86 store_ticket(KTEXT cip
)
93 int left
= cip
->length
;
99 ptr
= (char *) cip
->dat
;
101 /* extract session key */
102 memmove(session
, ptr
, 8);
106 if (strnlen(ptr
, left
) == left
)
109 /* extract server's name */
110 strcpy(sp
.name
, ptr
);
111 ptr
+= strlen(sp
.name
) + 1;
112 left
-= strlen(sp
.name
) + 1;
114 if (strnlen(ptr
, left
) == left
)
117 /* extract server's instance */
118 strcpy(sp
.instance
, ptr
);
119 ptr
+= strlen(sp
.instance
) + 1;
120 left
-= strlen(sp
.instance
) + 1;
122 if (strnlen(ptr
, left
) == left
)
125 /* extract server's realm */
126 strcpy(sp
.realm
,ptr
);
127 ptr
+= strlen(sp
.realm
) + 1;
128 left
-= strlen(sp
.realm
) + 1;
132 /* extract ticket lifetime, server key version, ticket length */
133 /* be sure to avoid sign extension on lifetime! */
134 lifetime
= (unsigned char) ptr
[0];
135 kvno
= (unsigned char) ptr
[1];
136 tkt
.length
= (unsigned char) ptr
[2];
140 if (tkt
.length
> left
)
143 /* extract ticket itself */
144 memmove(tkt
.dat
, ptr
, tkt
.length
);
148 /* Here is where the time should be verified against the KDC.
149 * Unfortunately everything is sent in host byte order (receiver
150 * makes wrong) , and at this stage there is no way for us to know
151 * which byteorder the KDC has. So we simply ignore the time,
152 * there are no security risks with this, the only thing that can
153 * happen is that we might receive a replayed ticket, which could
154 * at most be useless.
158 /* check KDC time stamp */
159 memmove(&kdc_time
, ptr
, sizeof(kdc_time
));
160 if (swap_bytes
) swap_u_long(kdc_time
);
164 if (abs((int)(local_time
- kdc_time
)) > CLOCK_SKEW
) {
165 return(RD_AP_TIME
); /* XXX should probably be better
170 /* initialize ticket cache */
172 if (tf_create(TKT_FILE
) != KSUCCESS
)
175 if (tf_put_pname(pr
.name
) != KSUCCESS
||
176 tf_put_pinst(pr
.instance
) != KSUCCESS
) {
182 kerror
= tf_save_cred(sp
.name
, sp
.instance
, sp
.realm
, session
,
183 lifetime
, kvno
, &tkt
, local_time
);
190 kauth(char *principal
, char *ticket
)
195 ret
= krb_parse_name(principal
, &pr
);
197 reply(500, "Bad principal: %s.", krb_get_err_text(ret
));
201 krb_get_lrealm(pr
.realm
, 1);
204 cip
.length
= base64_decode(ticket
, &cip
.dat
);
205 if(cip
.length
== -1){
206 reply(500, "Failed to decode data.");
209 ret
= store_ticket(&cip
);
211 reply(500, "Kerberos error: %s.", krb_get_err_text(ret
));
212 memset(&cip
, 0, sizeof(cip
));
215 do_destroy_tickets
= 1;
219 reply(200, "Tickets will be destroyed on exit.");
223 ret
= krb_get_in_tkt (pr
.name
,
226 KRB_TICKET_GRANTING_TICKET
,
229 NULL
, save_tkt
, NULL
);
230 if(ret
!= INTK_BADPW
){
231 reply(500, "Kerberos error: %s.", krb_get_err_text(ret
));
234 if(base64_encode(cip
.dat
, cip
.length
, &p
) < 0) {
235 reply(500, "Out of memory while base64-encoding.");
238 reply(300, "P=%s T=%s", krb_unparse_name(&pr
), p
);
240 memset(&cip
, 0, sizeof(cip
));
245 short_date(int32_t dp
)
248 time_t t
= (time_t)dp
;
250 if (t
== (time_t)(-1L)) return "*** Never *** ";
261 char *file
= tkt_string();
265 char buf1
[128], buf2
[128];
271 err
= tf_init(file
, R_TKT_FIL
);
273 reply(500, "%s", krb_get_err_text(err
));
279 * We must find the realm of the ticket file here before calling
280 * tf_init because since the realm of the ticket file is not
281 * really stored in the principal section of the file, the
282 * routine we use must itself call tf_init and tf_close.
284 err
= krb_get_tf_realm(file
, pr
.realm
);
286 reply(500, "%s", krb_get_err_text(err
));
290 err
= tf_init(file
, R_TKT_FIL
);
292 reply(500, "%s", krb_get_err_text(err
));
296 err
= tf_get_pname(pr
.name
);
298 reply(500, "%s", krb_get_err_text(err
));
301 err
= tf_get_pinst(pr
.instance
);
303 reply(500, "%s", krb_get_err_text(err
));
308 * You may think that this is the obvious place to get the
309 * realm of the ticket file, but it can't be done here as the
310 * routine to do this must open the ticket file. This is why
311 * it was done before tf_init.
314 lreply(200, "Ticket file: %s", tkt_string());
316 lreply(200, "Principal: %s", krb_unparse_name(&pr
));
317 while ((err
= tf_get_cred(&c
)) == KSUCCESS
) {
319 lreply(200, "%-15s %-15s %s",
320 " Issued", " Expires", " Principal (kvno)");
323 strcpy(buf1
, short_date(c
.issue_date
));
324 c
.issue_date
= krb_life_to_time(c
.issue_date
, c
.lifetime
);
325 if (time(0) < (unsigned long) c
.issue_date
)
326 strcpy(buf2
, short_date(c
.issue_date
));
328 strcpy(buf2
, ">>> Expired <<< ");
329 lreply(200, "%s %s %s (%d)", buf1
, buf2
,
330 krb_unparse_name_long(c
.service
, c
.instance
, c
.realm
), c
.kvno
);
332 if (header
&& err
== EOF
) {
333 lreply(200, "No tickets in file.");
339 * Only destroy if we created the tickets
345 if (do_destroy_tickets
)
355 reply(200, "Tickets destroyed");
359 krbtkfile(const char *tkfile
)
361 do_destroy_tickets
= 0;
362 krb_set_tkt_string(tkfile
);
363 reply(200, "Using ticket file %s", tkfile
);
367 afslog(const char *cell
)
371 reply(200, "afslog done");
373 reply(200, "no AFS present");