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