Sync usage with man page.
[netbsd-mini2440.git] / crypto / dist / heimdal / appl / ftp / ftpd / kauth.c
blobbbd664d590ecf60e53c5203adefabcb742617b2f
1 /*
2 * Copyright (c) 1995 - 1999, 2003 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("$Heimdal: kauth.c 15666 2005-07-19 17:08:11Z lha $"
37 "$NetBSD$");
39 #if defined(KRB4) || defined(KRB5)
41 int do_destroy_tickets = 1;
42 char *k5ccname;
44 #endif
46 #ifdef KRB4
48 static KTEXT_ST cip;
49 static unsigned int lifetime;
50 static time_t local_time;
52 static krb_principal pr;
54 static int
55 save_tkt(const char *user,
56 const char *instance,
57 const char *realm,
58 const void *arg,
59 key_proc_t key_proc,
60 KTEXT *cipp)
62 local_time = time(0);
63 memmove(&cip, *cipp, sizeof(cip));
64 return -1;
67 static int
68 store_ticket(KTEXT cip)
70 char *ptr;
71 des_cblock session;
72 krb_principal sp;
73 unsigned char kvno;
74 KTEXT_ST tkt;
75 int left = cip->length;
76 int len;
77 int kerror;
79 ptr = (char *) cip->dat;
81 /* extract session key */
82 memmove(session, ptr, 8);
83 ptr += 8;
84 left -= 8;
86 len = strnlen(ptr, left);
87 if (len == left)
88 return(INTK_BADPW);
90 /* extract server's name */
91 strlcpy(sp.name, ptr, sizeof(sp.name));
92 ptr += len + 1;
93 left -= len + 1;
95 len = strnlen(ptr, left);
96 if (len == left)
97 return(INTK_BADPW);
99 /* extract server's instance */
100 strlcpy(sp.instance, ptr, sizeof(sp.instance));
101 ptr += len + 1;
102 left -= len + 1;
104 len = strnlen(ptr, left);
105 if (len == left)
106 return(INTK_BADPW);
108 /* extract server's realm */
109 strlcpy(sp.realm, ptr, sizeof(sp.realm));
110 ptr += len + 1;
111 left -= len + 1;
113 if(left < 3)
114 return INTK_BADPW;
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];
120 ptr += 3;
121 left -= 3;
123 if (tkt.length > left)
124 return(INTK_BADPW);
126 /* extract ticket itself */
127 memmove(tkt.dat, ptr, tkt.length);
128 ptr += tkt.length;
129 left -= 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.
140 #if 0
141 /* check KDC time stamp */
143 time_t kdc_time;
145 memmove(&kdc_time, ptr, sizeof(kdc_time));
146 if (swap_bytes) swap_u_long(kdc_time);
148 ptr += 4;
150 if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
151 return(RD_AP_TIME); /* XXX should probably be better
152 code */
155 #endif
157 /* initialize ticket cache */
159 if (tf_create(TKT_FILE) != KSUCCESS)
160 return(INTK_ERR);
162 if (tf_put_pname(pr.name) != KSUCCESS ||
163 tf_put_pinst(pr.instance) != KSUCCESS) {
164 tf_close();
165 return(INTK_ERR);
169 kerror = tf_save_cred(sp.name, sp.instance, sp.realm, session,
170 lifetime, kvno, &tkt, local_time);
171 tf_close();
173 return(kerror);
176 void
177 kauth(char *principal, char *ticket)
179 char *p;
180 int ret;
182 if(get_command_prot() != prot_private) {
183 reply(500, "Request denied (bad protection level)");
184 return;
186 ret = krb_parse_name(principal, &pr);
187 if(ret){
188 reply(500, "Bad principal: %s.", krb_get_err_text(ret));
189 return;
191 if(pr.realm[0] == 0)
192 krb_get_lrealm(pr.realm, 1);
194 if(ticket){
195 cip.length = base64_decode(ticket, &cip.dat);
196 if(cip.length == -1){
197 reply(500, "Failed to decode data.");
198 return;
200 ret = store_ticket(&cip);
201 if(ret){
202 reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
203 memset(&cip, 0, sizeof(cip));
204 return;
206 do_destroy_tickets = 1;
208 if(k_hasafs())
209 krb_afslog(0, 0);
210 reply(200, "Tickets will be destroyed on exit.");
211 return;
214 ret = krb_get_in_tkt (pr.name,
215 pr.instance,
216 pr.realm,
217 KRB_TICKET_GRANTING_TICKET,
218 pr.realm,
219 DEFAULT_TKT_LIFE,
220 NULL, save_tkt, NULL);
221 if(ret != INTK_BADPW){
222 reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
223 return;
225 if(base64_encode(cip.dat, cip.length, &p) < 0) {
226 reply(500, "Out of memory while base64-encoding.");
227 return;
229 reply(300, "P=%s T=%s", krb_unparse_name(&pr), p);
230 free(p);
231 memset(&cip, 0, sizeof(cip));
235 static char *
236 short_date(int32_t dp)
238 char *cp;
239 time_t t = (time_t)dp;
241 if (t == (time_t)(-1L)) return "*** Never *** ";
242 cp = ctime(&t) + 4;
243 cp[15] = '\0';
244 return (cp);
247 void
248 krbtkfile(const char *tkfile)
250 do_destroy_tickets = 0;
251 krb_set_tkt_string(tkfile);
252 reply(200, "Using ticket file %s", tkfile);
255 #endif /* KRB4 */
257 #ifdef KRB5
259 static void
260 dest_cc(void)
262 krb5_context context;
263 krb5_error_code ret;
264 krb5_ccache id;
266 ret = krb5_init_context(&context);
267 if (ret == 0) {
268 if (k5ccname)
269 ret = krb5_cc_resolve(context, k5ccname, &id);
270 else
271 ret = krb5_cc_default (context, &id);
272 if (ret)
273 krb5_free_context(context);
275 if (ret == 0) {
276 krb5_cc_destroy(context, id);
277 krb5_free_context (context);
280 #endif
282 #if defined(KRB4) || defined(KRB5)
285 * Only destroy if we created the tickets
288 void
289 cond_kdestroy(void)
291 if (do_destroy_tickets) {
292 #if KRB4
293 dest_tkt();
294 #endif
295 #if KRB5
296 dest_cc();
297 #endif
298 do_destroy_tickets = 0;
300 afsunlog();
303 void
304 kdestroy(void)
306 #if KRB4
307 dest_tkt();
308 #endif
309 #if KRB5
310 dest_cc();
311 #endif
312 afsunlog();
313 reply(200, "Tickets destroyed");
317 void
318 afslog(const char *cell, int quiet)
320 if(k_hasafs()) {
321 #ifdef KRB5
322 krb5_context context;
323 krb5_error_code ret;
324 krb5_ccache id;
326 ret = krb5_init_context(&context);
327 if (ret == 0) {
328 if (k5ccname)
329 ret = krb5_cc_resolve(context, k5ccname, &id);
330 else
331 ret = krb5_cc_default(context, &id);
332 if (ret)
333 krb5_free_context(context);
335 if (ret == 0) {
336 krb5_afslog(context, id, cell, 0);
337 krb5_cc_close (context, id);
338 krb5_free_context (context);
340 #endif
341 #ifdef KRB4
342 krb_afslog(cell, 0);
343 #endif
344 if (!quiet)
345 reply(200, "afslog done");
346 } else {
347 if (!quiet)
348 reply(200, "no AFS present");
352 void
353 afsunlog(void)
355 if(k_hasafs())
356 k_unlog();
359 #else
360 int ftpd_afslog_placeholder;
361 #endif /* KRB4 || KRB5 */