death to trailing whitespace
[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     char hoststr[16];
799
800     printf("Starting to listen for UDP packets\n");
801     while (1) {
802         FD_ZERO(&rfds);
803         if (sock_kerb >= 0)
804             FD_SET(sock_kerb, &rfds);
805         if (sock_kerb5 >= 0)
806             FD_SET(sock_kerb5, &rfds);
807
808         tv.tv_sec = 100;
809         tv.tv_usec = 0;
810         /* write and exception fd_set's are null */
811         code = IOMGR_Select(32, &rfds, NULL, NULL, &tv);
812         if (code == 0) {        /* timeout */
813             /* printf ("Timeout\n"); */
814             continue;
815         } else if (code < 0) {
816             perror("calling IOMGR_Select");
817             break;
818         }
819
820         fromLen = sizeof(packet.from);
821         if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) {
822             code =
823                 recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0,
824                          (struct sockaddr *)&packet.from, &fromLen);
825             if (code < 0) {
826                 if (errno == EAGAIN || errno == ECONNREFUSED)
827                     goto try_kerb5;
828                 perror("calling recvfrom");
829                 break;
830             }
831             packet.len = code;
832             if (krb_udp_debug) {
833                 printf("Kerb:udp: Got %d bytes from addr %s which are '",
834                        code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
835                 ka_PrintBytes(packet.data, packet.len);
836                 printf("'\n");
837             }
838             packet.name = packet.inst = packet.realm = "";
839             packet.time = 0;
840             process_udp_request(sock_kerb, &packet);
841         }
842       try_kerb5:
843         if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) {
844             code =
845                 recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0,
846                          (struct sockaddr *)&packet.from, &fromLen);
847             if (code < 0) {
848                 if (errno == EAGAIN || errno == ECONNREFUSED)
849                     continue;
850                 perror("calling recvfrom");
851                 break;
852             }
853             packet.len = code;
854             if (krb_udp_debug) {
855                 printf("Kerb5:udp: Got %d bytes from addr %s which are '",
856                        code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
857                 ka_PrintBytes(packet.data, packet.len);
858                 printf("'\n");
859             }
860             packet.name = packet.inst = packet.realm = "";
861             packet.time = 0;
862             process_udp_request(sock_kerb5, &packet);
863         }
864     }
865     if (sock_kerb >= 0) {
866         closesocket(sock_kerb);
867         sock_kerb = -1;
868     }
869     if (sock_kerb5 >= 0) {
870         closesocket(sock_kerb5);
871         sock_kerb5 = -1;
872     }
873     printf("UDP SocketListener exiting due to error\n");
874
875     return NULL;
876 }
877
878 #if MAIN
879
880 #include "AFS_component_version_number.c"
881
882 int
883 main(int, char **)
884 #else
885 afs_int32
886 init_krb_udp(void)
887 #endif
888 {
889     struct sockaddr_in taddr;
890     static PROCESS slPid;       /* socket listener pid */
891     static PROCESS checkPid;    /* fiveminute check */
892     afs_int32 code;
893     char *krb4name;             /* kerberos version4 service */
894
895 #if MAIN
896     PROCESS junk;
897 #endif
898     struct servent *sp;
899     static int inited = 0;
900     afs_int32 kerb_port;
901
902     if (inited)
903         return -1;
904     inited = 1;
905
906     memset(&taddr, 0, sizeof(taddr));
907     krb4name = "kerberos4";
908     sp = getservbyname(krb4name, "udp");
909     taddr.sin_family = AF_INET; /* added for NCR port */
910 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
911     taddr.sin_len = sizeof(struct sockaddr_in);
912 #endif
913     if (!sp) {
914         /* if kerberos-4 is not available, try "kerberos-iv" */
915         krb4name = "kerberos-iv";
916         sp = getservbyname(krb4name, "udp");
917     }
918     if (!sp) {
919         /* if kerberos-iv is not available, try "kerberos" */
920         krb4name = "kerberos";
921         sp = getservbyname(krb4name, "udp");
922     }
923     if (!sp) {
924         fprintf(stderr,
925                 "kerberos/udp is unknown; check /etc/services.  Using port=%d as default\n",
926                 KRB_PORT);
927         taddr.sin_port = htons(KRB_PORT);
928     } else {
929         /* copy the port number */
930         fprintf(stderr, "%s/udp port=%hu\n", krb4name,
931                 (unsigned short)sp->s_port);
932         taddr.sin_port = sp->s_port;
933     }
934     kerb_port = taddr.sin_port;
935     sock_kerb = socket(AF_INET, SOCK_DGRAM, 0);
936     code = bind(sock_kerb, (struct sockaddr *)&taddr, sizeof(taddr));
937     if (code < 0) {
938         perror("calling bind");
939         sock_kerb = -1;
940     }
941
942     sp = getservbyname("kerberos5", "udp");
943     if (!sp) {
944         fprintf(stderr,
945                 "kerberos5/udp is unknown; check /etc/services.  Using port=%d as default\n",
946                 KRB5_PORT);
947         taddr.sin_port = htons(KRB5_PORT);
948     } else {
949         /* copy the port number */
950         fprintf(stderr, "kerberos5/udp port=%hu\n",
951                 (unsigned short)sp->s_port);
952         taddr.sin_port = sp->s_port;
953     }
954     if (taddr.sin_port != kerb_port) {  /* a different port */
955         sock_kerb5 = socket(AF_INET, SOCK_DGRAM, 0);
956         code = bind(sock_kerb5, (struct sockaddr *)&taddr, sizeof(taddr));
957         if (code < 0) {
958             perror("calling bind");
959             sock_kerb5 = -1;
960         }
961     }
962
963     /* Bail out if we can't bind with any port */
964     if ((sock_kerb < 0) && (sock_kerb5 < 0))
965         return -1;
966
967 #if MAIN
968     /* this has already been done */
969     LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
970     IOMGR_Initialize();
971 #endif
972     LWP_CreateProcess(SocketListener, /*stacksize */ 16000,
973                       LWP_NORMAL_PRIORITY, (void *)0, "Socket Listener",
974                       &slPid);
975
976     /* just to close the log every five minutes */
977
978     LWP_CreateProcess(FiveMinuteCheckLWP, 24 * 1024, LWP_MAX_PRIORITY - 2,
979                       (void *)&fiveminutes, "FiveMinuteChecks", &checkPid);
980
981 #if MAIN
982     initialize_ka_error_table();
983     initialize_rxk_error_table();
984     while (1)                   /* don't just stand there, run it */
985         IOMGR_Sleep(60);
986 #else
987     return 0;
988 #endif
989
990 }
991
992 #if MAIN
993 char *lastOperation;            /* name of last operation */
994 char *lrealm = "REALMNAME";
995 struct kadstats dynamic_statistics;
996
997 static int
998 InitAuthServ(tt, lock, this_op)
999      struct ubik_trans **tt;
1000      int lock;                  /* read or write transaction */
1001      int *this_op;              /* op of RCP routine, for COUNT_ABO */
1002 {
1003     int code = 0;
1004
1005     *tt = 0;
1006     printf("Calling InitAuthServ\n");
1007     return code;
1008 }
1009
1010 static int
1011 ubik_EndTrans(tt)
1012      struct ubik_trans *tt;
1013 {
1014     printf("Calling ubik_EndTrans\n");
1015     return 0;
1016 }
1017
1018 static int
1019 ubik_AbortTrans(tt)
1020      struct ubik_trans *tt;
1021 {
1022     printf("Calling ubik_AbortTrans\n");
1023     return 0;
1024 }
1025
1026 static int
1027 FindBlock(at, aname, ainstance, tentry)
1028      struct ubik_trans *at;
1029      char *aname;
1030      char *ainstance;
1031      struct kaentry *tentry;
1032 {
1033     printf("Calling FindBlock with '%s'.'%s'\n", aname, ainstance);
1034     strcpy(tentry->userID.name, aname);
1035     strcpy(tentry->userID.instance, ainstance);
1036     tentry->key_version = htonl(17);
1037     des_string_to_key("toa", &tentry->key);
1038     tentry->flags = htonl(KAFNORMAL);
1039     tentry->user_expiration = htonl(NEVERDATE);
1040     tentry->max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
1041     return 323232;
1042 }
1043
1044 static int
1045 ka_LookupKey(tt, name, inst, kvno, key)
1046      struct ubik_trans *tt;
1047      char *name;
1048      char *inst;
1049      afs_int32 *kvno;           /* returned */
1050      struct ktc_encryptionKey *key;     /* copied out */
1051 {
1052     printf("Calling ka_LookupKey with '%s'.'%s'\n", name, inst);
1053     *kvno = 23;
1054     des_string_to_key("applexx", key);
1055 }
1056
1057 static afs_int32
1058 kvno_tgs_key(authDomain, kvno, tgskey)
1059      char *authDomain;
1060      afs_int32 kvno;
1061      struct ktc_encryptionKey *tgskey;
1062 {
1063     if (strcmp(authDomain, lrealm) != 0)
1064         printf("Called with wrong %s as authDomain\n", authDomain);
1065     if (kvno != 23)
1066         printf("kvno_tgs_key: being called with wrong kvno: %d\n", kvno);
1067     des_string_to_key("applexx", tgskey);
1068     return 0;
1069 }
1070
1071 save_principal()
1072 {
1073 }
1074
1075 name_instance_legal()
1076 {
1077     return 1;
1078 }
1079 #endif