2 * Copyright (c) 1995 - 1999, 2003 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. 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
34 #include "ftpd_locl.h"
36 __RCSID("$Heimdal: kauth.c 15666 2005-07-19 17:08:11Z lha $"
39 #if defined(KRB4) || defined(KRB5)
41 int do_destroy_tickets
= 1;
49 static unsigned int lifetime
;
50 static time_t local_time
;
52 static krb_principal pr
;
55 save_tkt(const char *user
,
63 memmove(&cip
, *cipp
, sizeof(cip
));
68 store_ticket(KTEXT cip
)
75 int left
= cip
->length
;
79 ptr
= (char *) cip
->dat
;
81 /* extract session key */
82 memmove(session
, ptr
, 8);
86 len
= strnlen(ptr
, left
);
90 /* extract server's name */
91 strlcpy(sp
.name
, ptr
, sizeof(sp
.name
));
95 len
= strnlen(ptr
, left
);
99 /* extract server's instance */
100 strlcpy(sp
.instance
, ptr
, sizeof(sp
.instance
));
104 len
= strnlen(ptr
, left
);
108 /* extract server's realm */
109 strlcpy(sp
.realm
, ptr
, sizeof(sp
.realm
));
115 /* extract ticket lifetime, server key version, ticket length */
116 /* be sure to avoid sign extension on lifetime! */
117 lifetime
= (unsigned char) ptr
[0];
118 kvno
= (unsigned char) ptr
[1];
119 tkt
.length
= (unsigned char) ptr
[2];
123 if (tkt
.length
> left
)
126 /* extract ticket itself */
127 memmove(tkt
.dat
, ptr
, tkt
.length
);
131 /* Here is where the time should be verified against the KDC.
132 * Unfortunately everything is sent in host byte order (receiver
133 * makes wrong) , and at this stage there is no way for us to know
134 * which byteorder the KDC has. So we simply ignore the time,
135 * there are no security risks with this, the only thing that can
136 * happen is that we might receive a replayed ticket, which could
137 * at most be useless.
141 /* check KDC time stamp */
145 memmove(&kdc_time
, ptr
, sizeof(kdc_time
));
146 if (swap_bytes
) swap_u_long(kdc_time
);
150 if (abs((int)(local_time
- kdc_time
)) > CLOCK_SKEW
) {
151 return(RD_AP_TIME
); /* XXX should probably be better
157 /* initialize ticket cache */
159 if (tf_create(TKT_FILE
) != KSUCCESS
)
162 if (tf_put_pname(pr
.name
) != KSUCCESS
||
163 tf_put_pinst(pr
.instance
) != KSUCCESS
) {
169 kerror
= tf_save_cred(sp
.name
, sp
.instance
, sp
.realm
, session
,
170 lifetime
, kvno
, &tkt
, local_time
);
177 kauth(char *principal
, char *ticket
)
182 if(get_command_prot() != prot_private
) {
183 reply(500, "Request denied (bad protection level)");
186 ret
= krb_parse_name(principal
, &pr
);
188 reply(500, "Bad principal: %s.", krb_get_err_text(ret
));
192 krb_get_lrealm(pr
.realm
, 1);
195 cip
.length
= base64_decode(ticket
, &cip
.dat
);
196 if(cip
.length
== -1){
197 reply(500, "Failed to decode data.");
200 ret
= store_ticket(&cip
);
202 reply(500, "Kerberos error: %s.", krb_get_err_text(ret
));
203 memset(&cip
, 0, sizeof(cip
));
206 do_destroy_tickets
= 1;
210 reply(200, "Tickets will be destroyed on exit.");
214 ret
= krb_get_in_tkt (pr
.name
,
217 KRB_TICKET_GRANTING_TICKET
,
220 NULL
, save_tkt
, NULL
);
221 if(ret
!= INTK_BADPW
){
222 reply(500, "Kerberos error: %s.", krb_get_err_text(ret
));
225 if(base64_encode(cip
.dat
, cip
.length
, &p
) < 0) {
226 reply(500, "Out of memory while base64-encoding.");
229 reply(300, "P=%s T=%s", krb_unparse_name(&pr
), p
);
231 memset(&cip
, 0, sizeof(cip
));
236 short_date(int32_t dp
)
239 time_t t
= (time_t)dp
;
241 if (t
== (time_t)(-1L)) return "*** Never *** ";
248 krbtkfile(const char *tkfile
)
250 do_destroy_tickets
= 0;
251 krb_set_tkt_string(tkfile
);
252 reply(200, "Using ticket file %s", tkfile
);
262 krb5_context context
;
266 ret
= krb5_init_context(&context
);
269 ret
= krb5_cc_resolve(context
, k5ccname
, &id
);
271 ret
= krb5_cc_default (context
, &id
);
273 krb5_free_context(context
);
276 krb5_cc_destroy(context
, id
);
277 krb5_free_context (context
);
282 #if defined(KRB4) || defined(KRB5)
285 * Only destroy if we created the tickets
291 if (do_destroy_tickets
) {
298 do_destroy_tickets
= 0;
313 reply(200, "Tickets destroyed");
318 afslog(const char *cell
, int quiet
)
322 krb5_context context
;
326 ret
= krb5_init_context(&context
);
329 ret
= krb5_cc_resolve(context
, k5ccname
, &id
);
331 ret
= krb5_cc_default(context
, &id
);
333 krb5_free_context(context
);
336 krb5_afslog(context
, id
, cell
, 0);
337 krb5_cc_close (context
, id
);
338 krb5_free_context (context
);
345 reply(200, "afslog done");
348 reply(200, "no AFS present");
360 int ftpd_afslog_placeholder
;
361 #endif /* KRB4 || KRB5 */