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