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