Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / kauth / krb_udp.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /* This file contains the code to handle UDP requests to the authentication
11 server using the MIT Kerberos protocol for obtaining tickets. It will only
12 handle authentication and get ticket requests to provide read-only protocol
13 level compatibility with the standard Kerberos servers. */
14
15 #include <afsconfig.h>
16 #include <afs/param.h>
17 #include <afs/stds.h>
18
19 #include <roken.h>
20
21 #ifdef IGNORE_SOME_GCC_WARNINGS
22 # pragma GCC diagnostic warning "-Wdeprecated-declarations"
23 #endif
24
25 #ifdef AFS_NT40_ENV
26 #include <afs/errmap_nt.h>
27 #endif
28
29 #define HC_DEPRECATED
30 #include <hcrypto/des.h>
31
32 #include <afs/com_err.h>
33 #include <lwp.h>
34 #include <rx/xdr.h>
35 #include <rx/rx.h>
36 #include <rx/rxkad.h>
37 #include <rx/rxkad_convert.h>
38 #include <afs/auth.h>
39 #include <ubik.h>
40
41 #include "kauth.h"
42 #include "kautils.h"
43 #include "kauth_internal.h"
44 #include "kaserver.h"
45 #include "prot.h" /* protocol definitions */
46 #include "kaport.h"
47 #include "afs/audit.h"
48 #include "kalog.h"
49 #include "kadatabase.h"
50
51 /* my kerberos error codes */
52 #define KERB_ERR_BAD_MSG_TYPE 99
53 #define KERB_ERR_BAD_LIFETIME 98
54 #define KERB_ERR_NONNULL_REALM 97
55 #define KERB_ERR_PKT_LENGTH 96
56 #define KERB_ERR_TEXT_LENGTH 95
57 #ifndef KDC_GEN_ERR
58 #define KDC_GEN_ERR 20
59 #endif
60
61 #ifndef AFS_NT40_ENV
62 #define closesocket close
63 #endif
64
65 int krb_udp_debug = 0;
66
67 static int sock_kerb = -1; /* the socket we're using */
68 static int sock_kerb5 = -1; /* the socket we're using */
69
70 struct packet {
71 int len;
72 struct sockaddr_in from;
73 int byteOrder;
74 char *name;
75 char *inst;
76 char *realm;
77 Date time;
78 char *rest; /* remaining bytes of packet */
79 char data[MAX_PKT_LEN];
80 };
81
82 extern char *lastOperation;
83 extern char lrealm[];
84
85 char udpAuthPrincipal[256];
86 char udptgsPrincipal[256];
87 char udptgsServerPrincipal[256];
88
89 #define putstr(name) if ((slen = strlen(name)) >= MAXKTCNAMELEN) return -1;\
90 else strcpy (answer, name), answer += slen+1
91 #define putint(num) num = htonl(num), \
92 memcpy(answer, &num, sizeof(afs_int32)), \
93 answer += sizeof(afs_int32)
94
95 #define getstr(name) if ((slen = strlen(packet)) >= sizeof(name)) return -1;\
96 strcpy (name, packet), packet += slen+1
97 #define getint(num) memcpy(&num, packet, sizeof(afs_int32)), \
98 num = ktohl (byteOrder, num), \
99 packet += sizeof(afs_int32)
100
101 /* this is just to close the log every five minutes to rm works */
102
103 int fiveminutes = 300;
104
105 static void *
106 FiveMinuteCheckLWP(void *unused)
107 {
108
109 printf("start 5 min check lwp\n");
110
111 while (1) {
112 IOMGR_Sleep(fiveminutes);
113 /* close the log so it can be removed */
114 ReOpenLog(); /* no trunc, just append */
115 }
116 AFS_UNREACHED(return(NULL));
117 }
118
119
120 static afs_int32
121 create_cipher(char *cipher, int *cipherLen,
122 struct ktc_encryptionKey *sessionKey, char *sname,
123 char *sinst, Date start, Date end, afs_int32 kvno,
124 char *ticket, int ticketLen, struct ktc_encryptionKey *key)
125 {
126 char *answer;
127 int slen;
128 unsigned char life = time_to_life(start, end);
129 int len;
130 DES_key_schedule schedule;
131 afs_int32 code;
132
133 answer = cipher;
134 len =
135 sizeof(*sessionKey) + strlen(sname) + strlen(sinst) + strlen(lrealm) +
136 3 /*nulls */ + 3 + ticketLen + sizeof(Date);
137 if (len > *cipherLen)
138 return KAANSWERTOOLONG;
139 if (ticketLen > 255)
140 return KAANSWERTOOLONG;
141 if (kvno > 255)
142 return KAANSWERTOOLONG;
143
144 memcpy(answer, sessionKey, sizeof(*sessionKey));
145 answer += sizeof(*sessionKey);
146 putstr(sname);
147 putstr(sinst);
148 putstr(lrealm);
149 *answer++ = life;
150 *answer++ = (unsigned char)kvno;
151 *answer++ = (unsigned char)ticketLen;
152 memcpy(answer, ticket, ticketLen);
153 answer += ticketLen;
154 putint(start);
155
156 if (krb_udp_debug) {
157 printf("Printing ticket (%d) and date: ", ticketLen);
158 ka_PrintBytes(ticket, ticketLen);
159 ka_PrintBytes(answer - 4, 4);
160 printf("\n");
161 }
162
163 if ((code = DES_key_sched(ktc_to_cblock(key), &schedule)))
164 printf("In KAAuthenticate: key_sched returned %d\n", code);
165 DES_pcbc_encrypt(cipher, cipher, len, &schedule, ktc_to_cblockptr(key), ENCRYPT);
166 *cipherLen = round_up_to_ebs(len);
167
168 if (krb_udp_debug) {
169 printf("Printing cipher (%d): ", *cipherLen);
170 ka_PrintBytes(cipher, *cipherLen);
171 printf("\n");
172 }
173 return 0;
174 }
175
176 static afs_int32
177 create_reply(struct packet *ans, char *name, char *inst, Date startTime,
178 Date endTime, afs_int32 kvno, char *cipher, int cipherLen)
179 {
180 char *answer = ans->data;
181 int slen;
182
183 ans->len = 2 + strlen(name) + strlen(inst) + 3 /*nulls */ +
184 sizeof(afs_int32) + 1 /*ntkts */ + sizeof(afs_int32) + 1 /*kvno */ +
185 sizeof(short) + cipherLen;
186 if (ans->len > sizeof(ans->data))
187 return KAANSWERTOOLONG;
188 if (kvno > 255)
189 return KAANSWERTOOLONG;
190
191 *answer++ = (unsigned char)KRB_PROT_VERSION;
192 *answer++ = (unsigned char)AUTH_MSG_KDC_REPLY;
193 /* always send claiming network byte order */
194 putstr(name);
195 putstr(inst);
196 putstr("");
197 putint(startTime);
198 *answer++ = 1; /* undocumented number of tickets! */
199 putint(endTime);
200 *answer++ = (unsigned char)kvno;
201 {
202 short w = (short)cipherLen;
203 w = htons(w);
204 memcpy(answer, &w, sizeof(short));
205 answer += sizeof(short);
206 }
207 memcpy(answer, cipher, cipherLen);
208 return 0;
209 }
210
211 static afs_int32
212 check_auth(struct packet *pkt, char *auth, int authLen,
213 struct ktc_encryptionKey *key, char *name, char *inst,
214 char *cell)
215 {
216 char *packet;
217 DES_key_schedule schedule;
218 afs_int32 cksum;
219 afs_int32 time_sec;
220 int byteOrder = pkt->byteOrder;
221
222 DES_key_sched(ktc_to_cblock(key), &schedule);
223 DES_pcbc_encrypt(auth, auth, authLen, &schedule, ktc_to_cblockptr(key), DECRYPT);
224 packet = auth;
225 if (strcmp(packet, name) != 0)
226 return KABADTICKET;
227 packet += strlen(packet) + 1;
228 if (strcmp(packet, inst) != 0)
229 return KABADTICKET;
230 packet += strlen(packet) + 1;
231 if (strcmp(packet, cell) != 0)
232 return KABADTICKET;
233 packet += strlen(packet) + 1;
234 getint(cksum);
235 /* Comments in the original IBM source suggest this byte was/is "time_msec" */
236 packet++;
237 getint(time_sec);
238 if ((packet - auth) > authLen)
239 return KABADTICKET;
240 return 0;
241 }
242
243 afs_int32
244 UDP_Authenticate(int ksoc, struct sockaddr_in *client, char *name,
245 char *inst, Date startTime, Date endTime, char *sname,
246 char *sinst)
247 {
248 struct ubik_trans *tt;
249 afs_int32 to; /* offset of block */
250 struct kaentry tentry;
251 afs_int32 tgskvno; /* key version of service key */
252 struct ktc_encryptionKey tgskey; /* service key for encrypting ticket */
253 int tgt;
254 Date now = time(0);
255 afs_int32 code;
256
257 char ticket[MAXKTCTICKETLEN]; /* our copy of the ticket */
258 int ticketLen;
259 struct ktc_encryptionKey sessionKey; /* we have to invent a session key */
260
261 char cipher[2 * MAXKTCTICKETLEN]; /* put encrypted part of answer here */
262 int cipherLen;
263 struct packet ans;
264
265 COUNT_REQ(UAuthenticate);
266 if (!name_instance_legal(name, inst))
267 return KERB_ERR_NAME_EXP; /* KABADNAME */
268 if ((code = InitAuthServ(&tt, LOCKREAD, this_op)))
269 return code;
270
271 code = FindBlock(tt, name, inst, &to, &tentry);
272 if (code)
273 goto abort;
274 if (to) { /* if user exists check other stuff */
275 afs_int32 sto;
276 struct kaentry sentry;
277
278 unsigned char misc_auth_bytes[4];
279 afs_uint32 temp; /* unsigned for safety */
280 afs_uint32 pwexpires;
281
282 save_principal(udpAuthPrincipal, name, inst, 0);
283
284 tgt = ((strcmp(sname, KA_TGS_NAME) == 0)
285 && (strcmp(sinst, lrealm) == 0));
286 if ((ntohl(tentry.user_expiration) < now)
287 || (tgt && (ntohl(tentry.flags) & KAFNOTGS))) {
288 code = KERB_ERR_NAME_EXP; /* KABADUSER */
289 goto abort;
290 }
291 code = FindBlock(tt, KA_TGS_NAME, lrealm, &sto, &sentry);
292 if (code)
293 goto abort;
294 if (sto == 0) {
295 code = KANOENT;
296 goto abort;
297 }
298 if ((ntohl(sentry.user_expiration) < now)) {
299 code = KERB_ERR_NAME_EXP; /* XXX Could use another error code XXX */
300 goto abort;
301 }
302 if (check_ka_skew(startTime, now, KTC_TIME_UNCERTAINTY)) {
303 code = KERB_ERR_SERVICE_EXP; /* was KABADREQUEST */
304 goto abort;
305 }
306
307 memcpy(&temp, tentry.misc_auth_bytes, sizeof(afs_uint32));
308 temp = ntohl(temp);
309 unpack_long(temp, misc_auth_bytes);
310 pwexpires = misc_auth_bytes[0];
311 if (pwexpires) {
312 pwexpires =
313 ntohl(tentry.change_password_time) +
314 24 * 60 * 60 * pwexpires;
315 if (pwexpires < now) {
316 code = KERB_ERR_AUTH_EXP; /* was KAPWEXPIRED */
317 goto abort;
318 }
319 }
320
321 /* make the ticket */
322 code = DES_new_random_key(ktc_to_cblock(&sessionKey));
323 if (code) {
324 code = KERB_ERR_NULL_KEY; /* was KANOKEYS */
325 goto abort;
326 }
327 endTime =
328 umin(endTime, startTime + ntohl(tentry.max_ticket_lifetime));
329 if ((code = ka_LookupKey(tt, sname, sinst, &tgskvno, &tgskey))
330 || (code =
331 tkt_MakeTicket(ticket, &ticketLen, &tgskey, name, inst,
332 lrealm, startTime, endTime, &sessionKey,
333 htonl(client->sin_addr.s_addr), sname, sinst)))
334 goto abort;
335
336 cipherLen = sizeof(cipher);
337 code =
338 create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst,
339 startTime, endTime, tgskvno, ticket, ticketLen,
340 &tentry.key);
341 if (code)
342 goto abort;
343 } else { /* no such user */
344 cipherLen = 0;
345 tentry.key_version = 0;
346 }
347 code = ubik_EndTrans(tt);
348 if (code)
349 goto fail;
350
351 code =
352 create_reply(&ans, name, inst, startTime, endTime,
353 ntohl(tentry.key_version), cipher, cipherLen);
354 if (code)
355 goto fail;
356
357 if (krb_udp_debug) {
358 printf("Sending %d bytes ending in: ", ans.len);
359 ka_PrintBytes(ans.data + ans.len - 8, 8);
360 printf("\n");
361 }
362
363 code =
364 sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)client,
365 sizeof(*client));
366 if (code != ans.len) {
367 perror("calling sendto");
368 code = -1;
369 goto fail;
370 }
371 KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr,
372 LOG_AUTHENTICATE);
373
374 if (cipherLen != 0) {
375 KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr,
376 LOG_TGTREQUEST);
377 }
378 osi_audit(UDPAuthenticateEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_END);
379 return 0;
380
381 abort:
382 COUNT_ABO;
383 ubik_AbortTrans(tt);
384
385 fail:
386 osi_audit(UDPAuthenticateEvent, code, AUD_STR, name, AUD_STR, inst,
387 AUD_END);
388 return code;
389 }
390
391 afs_int32
392 UDP_GetTicket(int ksoc, struct packet *pkt, afs_int32 kvno,
393 char *authDomain, char *ticket, int ticketLen, char *auth,
394 int authLen)
395 {
396 afs_int32 code;
397 struct ktc_encryptionKey tgskey;
398 char name[MAXKTCNAMELEN];
399 char inst[MAXKTCNAMELEN];
400 char cell[MAXKTCREALMLEN];
401 struct ktc_encryptionKey authSessionKey;
402 afs_int32 host;
403 Date start;
404 Date authEnd;
405 Date now = time(0);
406 int celllen;
407 int import;
408
409 char *packet;
410 int slen;
411 int byteOrder = pkt->byteOrder;
412 char sname[MAXKTCNAMELEN];
413 char sinst[MAXKTCNAMELEN];
414 afs_int32 time_ws;
415 unsigned char life;
416
417 struct ubik_trans *tt;
418 afs_int32 to;
419 struct kaentry caller;
420 struct kaentry server;
421 Date reqEnd;
422 struct ktc_encryptionKey sessionKey;
423 int newTicketLen;
424 char newTicket[MAXKTCTICKETLEN];
425
426 char cipher[2 * MAXKTCTICKETLEN]; /* put encrypted part of answer here */
427 int cipherLen;
428 struct packet ans;
429
430 COUNT_REQ(UGetTicket);
431
432 if ((code = InitAuthServ(&tt, LOCKREAD, this_op)))
433 goto fail;
434 code =
435 ka_LookupKvno(tt, KA_TGS_NAME,
436 ((strlen(authDomain) > 0) ? authDomain : lrealm), kvno,
437 &tgskey);
438 if (code)
439 goto abort;
440
441 code =
442 tkt_DecodeTicket(ticket, ticketLen, &tgskey, name, inst, cell,
443 &authSessionKey, &host, &start, &authEnd);
444 pkt->name = name;
445 pkt->inst = inst;
446 pkt->realm = cell;
447 if (code) {
448 code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */
449 goto abort;
450 }
451 save_principal(udptgsPrincipal, name, inst, cell);
452 code = tkt_CheckTimes(start, authEnd, now);
453 if (code <= 0) {
454 if (code == -1) {
455 code = KERB_ERR_SERVICE_EXP; /* was RXKADEXPIRED */
456 goto abort;
457 }
458 code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */
459 goto abort;
460 }
461 celllen = strlen(cell);
462 import = 0;
463 if ((strlen(authDomain) > 0) && (strcmp(authDomain, lrealm) != 0))
464 import = 1;
465 if (import && (celllen == 0)) {
466 code = KERB_ERR_PKT_VER; /* was KABADTICKET */
467 goto abort;
468 }
469 if (celllen == 0) {
470 strncpy(cell, lrealm, MAXKTCREALMLEN - 1);
471 cell[MAXKTCREALMLEN - 1] = 0;
472 };
473
474 if (!krb4_cross && strcmp(lrealm, cell) != 0) {
475 code = KERB_ERR_PRINCIPAL_UNKNOWN;
476 goto abort;
477 }
478
479 if (krb_udp_debug) {
480 printf("UGetTicket: got ticket from '%s'.'%s'@'%s'\n", name, inst,
481 cell);
482 }
483
484 code = check_auth(pkt, auth, authLen, &authSessionKey, name, inst, cell);
485 if (code)
486 goto abort;
487
488 /* authenticator and all is OK so read actual request */
489 packet = pkt->rest;
490 getint(time_ws);
491 life = *(unsigned char *)packet++;
492 getstr(sname);
493 getstr(sinst);
494 start = now;
495 reqEnd = life_to_time(start, life);
496 if (krb_udp_debug) {
497 printf("UGetTicket: request for server '%s'.'%s'\n", sname, sinst);
498 }
499 save_principal(udptgsServerPrincipal, sname, sinst, 0);
500
501 if (import) {
502 strcpy(caller.userID.name, name);
503 strcpy(caller.userID.instance, inst);
504 caller.max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
505 } else {
506 code = FindBlock(tt, name, inst, &to, &caller);
507 if (code)
508 goto abort;
509 if (to == 0) {
510 ka_PrintUserID("GetTicket: User ", name, inst, " unknown.\n");
511 code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */
512 goto abort;
513 }
514 if (ntohl(caller.flags) & KAFNOTGS) {
515 code = KERB_ERR_AUTH_EXP; /* was KABADUSER */
516 goto abort;
517 }
518 }
519
520 code = FindBlock(tt, sname, sinst, &to, &server); /* get server's entry */
521 if (code)
522 goto abort;
523 if (to == 0) { /* entry not found */
524 ka_PrintUserID("GetTicket: Server ", sname, sinst, " unknown.\n");
525 code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */
526 goto abort;
527 }
528 code = ubik_EndTrans(tt);
529 if (code)
530 goto fail;
531
532 if (ntohl(server.flags) & KAFNOSEAL)
533 return KABADSERVER;
534
535 code = DES_new_random_key(ktc_to_cblock(&sessionKey));
536 if (code) {
537 code = KERB_ERR_NULL_KEY; /* was KANOKEYS */
538 goto fail;
539 }
540
541 reqEnd =
542 umin(umin(reqEnd, authEnd),
543 umin(start + ntohl(caller.max_ticket_lifetime),
544 start + ntohl(server.max_ticket_lifetime)));
545
546 code =
547 tkt_MakeTicket(newTicket, &newTicketLen, &server.key,
548 caller.userID.name, caller.userID.instance, cell,
549 start, reqEnd, &sessionKey,
550 htonl(pkt->from.sin_addr.s_addr), server.userID.name,
551 server.userID.instance);
552 if (code)
553 goto fail;
554
555 cipherLen = sizeof(cipher);
556 code =
557 create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst, start,
558 reqEnd, ntohl(server.key_version), newTicket,
559 newTicketLen, &authSessionKey);
560 if (code)
561 goto fail;
562
563 code =
564 create_reply(&ans, name, inst, start, reqEnd, 0, cipher, cipherLen);
565 if (code)
566 goto fail;
567
568 code =
569 sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from,
570 sizeof(pkt->from));
571 if (code != ans.len) {
572 perror("calling sendto");
573 code = -1;
574 goto fail;
575 }
576
577 if (cipherLen != 0) {
578 KALOG(name, inst, sname, sinst, NULL, host, LOG_GETTICKET);
579 }
580 osi_audit(UDPGetTicketEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_STR,
581 cell, AUD_STR, sname, AUD_STR, sinst, AUD_END);
582 return 0;
583
584 abort:
585 ubik_AbortTrans(tt);
586 fail:
587 osi_audit(UDPGetTicketEvent, code, AUD_STR, name, AUD_STR, inst, AUD_STR,
588 NULL, AUD_STR, NULL, AUD_STR, NULL, AUD_END);
589 return code;
590 }
591
592 static int
593 err_packet(int ksoc, struct packet *pkt, afs_int32 code, char *reason)
594 {
595 struct packet ans;
596 char *answer = ans.data;
597 int slen;
598 char buf[256];
599
600 if (reason == 0)
601 reason = "";
602 snprintf(buf, 255, "code = %d: %s", code, reason);
603
604 if (krb_udp_debug) {
605 printf("Sending error packet to '%s'.'%s'@'%s' containing %s\n",
606 pkt->name, pkt->inst, pkt->realm, buf);
607 }
608
609 ans.len =
610 2 + strlen(pkt->name) + strlen(pkt->inst) + strlen(pkt->realm) +
611 3 /* nulls */ + (2 * sizeof(afs_int32)) + strlen(buf) + 1;
612 if (ans.len > sizeof(ans.data)) {
613 printf("Answer packet too long\n");
614 return -1;
615 }
616
617 *answer++ = (unsigned char)KRB_PROT_VERSION;
618 *answer++ = (unsigned char)AUTH_MSG_ERR_REPLY;
619 /* always send claiming network byte order */
620 putstr(pkt->name);
621 putstr(pkt->inst);
622 putstr(pkt->realm);
623 putint(pkt->time);
624 if ((code < 0) || (code > KERB_ERR_MAXIMUM)) {
625 /* It could be because of kauth errors so we should return something instead of success!! */
626 code = KDC_GEN_ERR;
627 }
628 putint(code);
629 putstr(buf);
630
631 code =
632 sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from,
633 sizeof(pkt->from));
634 if (code != ans.len) {
635 if (code >= 0)
636 printf
637 ("call to sendto returned %d, sending error packet %d bytes long\n",
638 code, ans.len);
639 else
640 perror("err_packet: sendto");
641 }
642 return 0;
643 }
644
645 int
646 process_udp_auth(int ksoc, struct packet *pkt)
647 {
648 char *packet = pkt->rest;
649 char name[MAXKTCNAMELEN];
650 char inst[MAXKTCNAMELEN];
651 char realm[MAXKTCREALMLEN];
652 char sname[MAXKTCNAMELEN];
653 char sinst[MAXKTCNAMELEN];
654 int slen;
655 Date now = time(0);
656 Date startTime, endTime;
657 unsigned char lifetime;
658 afs_int32 code;
659
660 pkt->name = packet;
661 getstr(name);
662 pkt->inst = packet;
663 getstr(inst);
664 pkt->realm = packet;
665 getstr(realm);
666 if (krb_udp_debug) {
667 printf("Processing KDC Request from '%s'.'%s'@'%s'\n", name, inst,
668 realm);
669 }
670
671 if ((strlen(realm) > 0) && (strcmp(realm, lrealm) != 0)) {
672 err_packet(ksoc, pkt, KERB_ERR_NONNULL_REALM,
673 "null realm name not allowed");
674 return -1;
675 }
676 memcpy(&startTime, packet, sizeof(startTime));
677 packet += sizeof(startTime);
678 startTime = ktohl(pkt->byteOrder, startTime);
679 pkt->time = startTime;
680 lifetime = *packet++;
681 endTime = life_to_time(startTime, lifetime);
682 code = tkt_CheckTimes(startTime, endTime, now);
683 if (code < 0) {
684 err_packet(ksoc, pkt, KERB_ERR_BAD_LIFETIME,
685 "requested ticket lifetime invalid");
686 return -1;
687 }
688 getstr(sname);
689 getstr(sinst);
690 if ((packet - pkt->data) != pkt->len) {
691 err_packet(ksoc, pkt, KERB_ERR_PKT_LENGTH,
692 "packet length inconsistent");
693 return -1;
694 }
695 pkt->rest = packet;
696 code =
697 UDP_Authenticate(ksoc, &pkt->from, name, inst, startTime, endTime,
698 sname, sinst);
699 if (code) {
700 if (code == KANOENT) {
701 code = KERB_ERR_PRINCIPAL_UNKNOWN;
702 err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
703 } else if (code == KAPWEXPIRED) {
704 code = KERB_ERR_NAME_EXP;
705 err_packet(ksoc, pkt, code, "password has expired");
706 } else
707 err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
708 }
709 return 0;
710 }
711
712 int
713 process_udp_appl(int ksoc, struct packet *pkt)
714 {
715 char *packet = pkt->rest;
716 afs_int32 kvno;
717 char realm[MAXKTCREALMLEN];
718 char ticket[MAXKTCTICKETLEN];
719 char auth[3 * MAXKTCNAMELEN + 4 + 5];
720 int slen;
721 int ticketLen, authLen;
722 afs_int32 code;
723
724 if (krb_udp_debug) {
725 printf("Processing APPL Request\n");
726 }
727 kvno = *packet++;
728 getstr(realm);
729 ticketLen = *(unsigned char *)packet++;
730 authLen = *(unsigned char *)packet++;
731 if (ticketLen > sizeof(ticket)) {
732 err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "ticket too long");
733 return -1;
734 }
735 memcpy(ticket, packet, ticketLen);
736 packet += ticketLen;
737 if (authLen > sizeof(auth)) {
738 err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "authenticator too long");
739 return -1;
740 }
741 memcpy(auth, packet, authLen);
742 pkt->rest = packet + authLen;
743 code =
744 UDP_GetTicket(ksoc, pkt, kvno, realm, ticket, ticketLen, auth,
745 authLen);
746 if (code) {
747 if (code == KANOENT)
748 code = KERB_ERR_PRINCIPAL_UNKNOWN;
749 err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
750 return -1;
751 }
752 return 0;
753 }
754
755 void
756 process_udp_request(int ksoc, struct packet *pkt)
757 {
758 char *packet = pkt->data;
759 unsigned char version, auth_msg_type;
760
761 version = *packet++;
762 if (version != KRB_PROT_VERSION) {
763 err_packet(ksoc, pkt, KERB_ERR_PKT_VER,
764 "packet version number unknown");
765 return;
766 }
767 auth_msg_type = *packet++;
768 pkt->byteOrder = auth_msg_type & 1;
769 pkt->rest = packet;
770 switch (auth_msg_type & ~1) {
771 case AUTH_MSG_KDC_REQUEST:
772 process_udp_auth(ksoc, pkt);
773 break;
774 case AUTH_MSG_APPL_REQUEST:
775 process_udp_appl(ksoc, pkt);
776 break;
777 default:
778 printf("unknown msg type 0x%x\n", auth_msg_type);
779 err_packet(ksoc, pkt, KERB_ERR_BAD_MSG_TYPE,
780 "message type not supported");
781 return;
782 }
783 return;
784 }
785
786 static void *
787 SocketListener(void *unused)
788 {
789 fd_set rfds;
790 struct timeval tv;
791 struct packet packet;
792 socklen_t fromLen;
793 afs_int32 code;
794 char hoststr[16];
795
796 printf("Starting to listen for UDP packets\n");
797 while (1) {
798 FD_ZERO(&rfds);
799 if (sock_kerb >= 0)
800 FD_SET(sock_kerb, &rfds);
801 if (sock_kerb5 >= 0)
802 FD_SET(sock_kerb5, &rfds);
803
804 tv.tv_sec = 100;
805 tv.tv_usec = 0;
806 /* write and exception fd_set's are null */
807 code = IOMGR_Select(32, &rfds, NULL, NULL, &tv);
808 if (code == 0) { /* timeout */
809 /* printf ("Timeout\n"); */
810 continue;
811 } else if (code < 0) {
812 perror("calling IOMGR_Select");
813 break;
814 }
815
816 fromLen = sizeof(packet.from);
817 if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) {
818 code =
819 recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0,
820 (struct sockaddr *)&packet.from, &fromLen);
821 if (code < 0) {
822 if (errno == EAGAIN || errno == ECONNREFUSED)
823 goto try_kerb5;
824 perror("calling recvfrom");
825 break;
826 }
827 packet.len = code;
828 if (krb_udp_debug) {
829 printf("Kerb:udp: Got %d bytes from addr %s which are '",
830 code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
831 ka_PrintBytes(packet.data, packet.len);
832 printf("'\n");
833 }
834 packet.name = packet.inst = packet.realm = "";
835 packet.time = 0;
836 process_udp_request(sock_kerb, &packet);
837 }
838 try_kerb5:
839 if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) {
840 code =
841 recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0,
842 (struct sockaddr *)&packet.from, &fromLen);
843 if (code < 0) {
844 if (errno == EAGAIN || errno == ECONNREFUSED)
845 continue;
846 perror("calling recvfrom");
847 break;
848 }
849 packet.len = code;
850 if (krb_udp_debug) {
851 printf("Kerb5:udp: Got %d bytes from addr %s which are '",
852 code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
853 ka_PrintBytes(packet.data, packet.len);
854 printf("'\n");
855 }
856 packet.name = packet.inst = packet.realm = "";
857 packet.time = 0;
858 process_udp_request(sock_kerb5, &packet);
859 }
860 }
861 if (sock_kerb >= 0) {
862 closesocket(sock_kerb);
863 sock_kerb = -1;
864 }
865 if (sock_kerb5 >= 0) {
866 closesocket(sock_kerb5);
867 sock_kerb5 = -1;
868 }
869 printf("UDP SocketListener exiting due to error\n");
870
871 return NULL;
872 }
873
874 #if MAIN
875
876 #include "AFS_component_version_number.c"
877
878 int
879 main(int, char **)
880 #else
881 afs_int32
882 init_krb_udp(void)
883 #endif
884 {
885 struct sockaddr_in taddr;
886 static PROCESS slPid; /* socket listener pid */
887 static PROCESS checkPid; /* fiveminute check */
888 afs_int32 code;
889 char *krb4name; /* kerberos version4 service */
890
891 #if MAIN
892 PROCESS junk;
893 #endif
894 struct servent *sp;
895 static int inited = 0;
896 afs_int32 kerb_port;
897
898 if (inited)
899 return -1;
900 inited = 1;
901
902 memset(&taddr, 0, sizeof(taddr));
903 krb4name = "kerberos4";
904 sp = getservbyname(krb4name, "udp");
905 taddr.sin_family = AF_INET; /* added for NCR port */
906 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
907 taddr.sin_len = sizeof(struct sockaddr_in);
908 #endif
909 if (!sp) {
910 /* if kerberos-4 is not available, try "kerberos-iv" */
911 krb4name = "kerberos-iv";
912 sp = getservbyname(krb4name, "udp");
913 }
914 if (!sp) {
915 /* if kerberos-iv is not available, try "kerberos" */
916 krb4name = "kerberos";
917 sp = getservbyname(krb4name, "udp");
918 }
919 if (!sp) {
920 fprintf(stderr,
921 "kerberos/udp is unknown; check /etc/services. Using port=%d as default\n",
922 KRB_PORT);
923 taddr.sin_port = htons(KRB_PORT);
924 } else {
925 /* copy the port number */
926 fprintf(stderr, "%s/udp port=%hu\n", krb4name,
927 (unsigned short)sp->s_port);
928 taddr.sin_port = sp->s_port;
929 }
930 kerb_port = taddr.sin_port;
931 sock_kerb = socket(AF_INET, SOCK_DGRAM, 0);
932 code = bind(sock_kerb, (struct sockaddr *)&taddr, sizeof(taddr));
933 if (code < 0) {
934 perror("calling bind");
935 sock_kerb = -1;
936 }
937
938 sp = getservbyname("kerberos5", "udp");
939 if (!sp) {
940 fprintf(stderr,
941 "kerberos5/udp is unknown; check /etc/services. Using port=%d as default\n",
942 KRB5_PORT);
943 taddr.sin_port = htons(KRB5_PORT);
944 } else {
945 /* copy the port number */
946 fprintf(stderr, "kerberos5/udp port=%hu\n",
947 (unsigned short)sp->s_port);
948 taddr.sin_port = sp->s_port;
949 }
950 if (taddr.sin_port != kerb_port) { /* a different port */
951 sock_kerb5 = socket(AF_INET, SOCK_DGRAM, 0);
952 code = bind(sock_kerb5, (struct sockaddr *)&taddr, sizeof(taddr));
953 if (code < 0) {
954 perror("calling bind");
955 sock_kerb5 = -1;
956 }
957 }
958
959 /* Bail out if we can't bind with any port */
960 if ((sock_kerb < 0) && (sock_kerb5 < 0))
961 return -1;
962
963 #if MAIN
964 /* this has already been done */
965 LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
966 IOMGR_Initialize();
967 #endif
968 LWP_CreateProcess(SocketListener, /*stacksize */ 16000,
969 LWP_NORMAL_PRIORITY, (void *)0, "Socket Listener",
970 &slPid);
971
972 /* just to close the log every five minutes */
973
974 LWP_CreateProcess(FiveMinuteCheckLWP, 24 * 1024, LWP_MAX_PRIORITY - 2,
975 (void *)&fiveminutes, "FiveMinuteChecks", &checkPid);
976
977 #if MAIN
978 initialize_ka_error_table();
979 initialize_rxk_error_table();
980 while (1) /* don't just stand there, run it */
981 IOMGR_Sleep(60);
982 #else
983 return 0;
984 #endif
985
986 }
987
988 #if MAIN
989 char *lastOperation; /* name of last operation */
990 char *lrealm = "REALMNAME";
991 struct kadstats dynamic_statistics;
992
993 static int
994 InitAuthServ(tt, lock, this_op)
995 struct ubik_trans **tt;
996 int lock; /* read or write transaction */
997 int *this_op; /* op of RCP routine, for COUNT_ABO */
998 {
999 int code = 0;
1000
1001 *tt = 0;
1002 printf("Calling InitAuthServ\n");
1003 return code;
1004 }
1005
1006 static int
1007 ubik_EndTrans(tt)
1008 struct ubik_trans *tt;
1009 {
1010 printf("Calling ubik_EndTrans\n");
1011 return 0;
1012 }
1013
1014 static int
1015 ubik_AbortTrans(tt)
1016 struct ubik_trans *tt;
1017 {
1018 printf("Calling ubik_AbortTrans\n");
1019 return 0;
1020 }
1021
1022 static int
1023 FindBlock(at, aname, ainstance, tentry)
1024 struct ubik_trans *at;
1025 char *aname;
1026 char *ainstance;
1027 struct kaentry *tentry;
1028 {
1029 printf("Calling FindBlock with '%s'.'%s'\n", aname, ainstance);
1030 strcpy(tentry->userID.name, aname);
1031 strcpy(tentry->userID.instance, ainstance);
1032 tentry->key_version = htonl(17);
1033 DES_string_to_key("toa", &tentry->key);
1034 tentry->flags = htonl(KAFNORMAL);
1035 tentry->user_expiration = htonl(NEVERDATE);
1036 tentry->max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
1037 return 323232;
1038 }
1039
1040 static int
1041 ka_LookupKey(tt, name, inst, kvno, key)
1042 struct ubik_trans *tt;
1043 char *name;
1044 char *inst;
1045 afs_int32 *kvno; /* returned */
1046 struct ktc_encryptionKey *key; /* copied out */
1047 {
1048 printf("Calling ka_LookupKey with '%s'.'%s'\n", name, inst);
1049 *kvno = 23;
1050 DES_string_to_key("applexx", key);
1051 }
1052
1053 static afs_int32
1054 kvno_tgs_key(authDomain, kvno, tgskey)
1055 char *authDomain;
1056 afs_int32 kvno;
1057 struct ktc_encryptionKey *tgskey;
1058 {
1059 if (strcmp(authDomain, lrealm) != 0)
1060 printf("Called with wrong %s as authDomain\n", authDomain);
1061 if (kvno != 23)
1062 printf("kvno_tgs_key: being called with wrong kvno: %d\n", kvno);
1063 DES_string_to_key("applexx", tgskey);
1064 return 0;
1065 }
1066
1067 save_principal()
1068 {
1069 }
1070
1071 name_instance_legal()
1072 {
1073 return 1;
1074 }
1075 #endif