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