include-afsconfig-before-param-h-20010712
[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, "",
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     osi_audit ( UDPAuthenticateEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_END);
362     return 0;
363
364 abort:
365     COUNT_ABO;
366     ubik_AbortTrans (tt);
367
368 fail:
369     osi_audit ( UDPAuthenticateEvent, code, AUD_STR, name, AUD_STR, inst, AUD_END);
370     return code;
371 }
372
373 afs_int32 UDP_GetTicket (ksoc, pkt, kvno, authDomain, ticket, ticketLen, auth, authLen)
374   int ksoc;
375   struct packet *pkt;
376   afs_int32  kvno;
377   char *authDomain;
378   char *ticket;
379   int   ticketLen;
380   char *auth;
381   int   authLen;
382 {   afs_int32  code;
383     struct ktc_encryptionKey tgskey;
384     char  name[MAXKTCNAMELEN];
385     char  inst[MAXKTCNAMELEN];
386     char  cell[MAXKTCREALMLEN];
387     struct ktc_encryptionKey authSessionKey;
388     afs_int32  host;
389     Date  start;
390     Date  authEnd;
391     Date  now = time(0);
392     int   celllen;
393     int   import;
394
395     char *packet;
396     int   slen;
397     int   byteOrder = pkt->byteOrder;
398     char  sname[MAXKTCNAMELEN];
399     char  sinst[MAXKTCNAMELEN];
400     afs_int32  time_ws;
401     unsigned char life;
402
403     struct ubik_trans *tt;
404     afs_int32  to;
405     struct kaentry caller;
406     struct kaentry server;
407     Date  reqEnd;
408     struct ktc_encryptionKey sessionKey;
409     int   newTicketLen;
410     char  newTicket[MAXKTCTICKETLEN];
411
412     char  cipher[2*MAXKTCTICKETLEN];    /* put encrypted part of answer here */
413     int   cipherLen;
414     struct packet ans;
415
416     COUNT_REQ (UGetTicket);
417
418     if (code = InitAuthServ(&tt, LOCKREAD, this_op)) goto fail;
419     code = ka_LookupKvno (tt, KA_TGS_NAME,
420                           ((strlen(authDomain) > 0) ? authDomain : lrealm),
421                           kvno, &tgskey);
422     if (code) goto abort;
423
424     code = tkt_DecodeTicket (ticket, ticketLen, &tgskey, name, inst, cell,
425                              &authSessionKey, &host, &start, &authEnd);
426     pkt->name = name;
427     pkt->inst = inst;
428     pkt->realm = cell;
429     if (code) {
430       code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */
431       goto abort;
432     }
433     save_principal (udptgsPrincipal, name, inst, cell);
434     code = tkt_CheckTimes (start, authEnd, now);
435     if (code <= 0) {
436       if (code == -1) {
437         code = KERB_ERR_SERVICE_EXP; /* was RXKADEXPIRED */
438         goto abort;
439       }
440       code = KERB_ERR_AUTH_EXP; /* was KANOAUTH */
441       goto abort;
442     }
443     celllen = strlen (cell);
444     import = 0;
445     if ((strlen(authDomain) > 0) && (strcmp (authDomain, lrealm) != 0))
446         import = 1;
447     if (import && (celllen == 0)) {
448       code = KERB_ERR_PKT_VER;  /* was KABADTICKET */
449       goto abort;
450     }
451     if (celllen == 0) {
452         strncpy (cell, lrealm, MAXKTCREALMLEN-1);
453         cell[MAXKTCREALMLEN-1] = 0;
454     };
455
456     if (krb_udp_debug) {
457         printf ("UGetTicket: got ticket from '%s'.'%s'@'%s'\n",
458                 name, inst, cell);
459     }
460
461     code = check_auth (pkt, auth, authLen, &authSessionKey, name, inst, cell);
462     if (code) goto abort;
463
464     /* authenticator and all is OK so read actual request */
465     packet = pkt->rest;
466     getint (time_ws);
467     life = *(unsigned char *)packet++;
468     getstr (sname);
469     getstr (sinst);
470     start = now;
471     reqEnd = life_to_time (start, life);
472     if (krb_udp_debug) {
473         printf ("UGetTicket: request for server '%s'.'%s'\n", sname, sinst);
474     }
475     save_principal (udptgsServerPrincipal, sname, sinst, 0);
476     
477     if (import) {
478         strcpy (caller.userID.name, name);
479         strcpy (caller.userID.instance, inst);
480         caller.max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
481     }
482     else {
483         code = FindBlock(tt, name, inst, &to, &caller);
484         if (code) goto abort;
485         if (to == 0) {
486             ka_PrintUserID ("GetTicket: User ", name, inst, " unknown.\n");
487             code = KERB_ERR_PRINCIPAL_UNKNOWN;  /* KANOENT */
488             goto abort;
489         }
490         if (ntohl(caller.flags) & KAFNOTGS)
491             { code =  KERB_ERR_AUTH_EXP; /* was KABADUSER */
492               goto abort; }
493     }
494
495     code = FindBlock (tt, sname, sinst, &to, &server); /* get server's entry */
496     if (code) goto abort;
497     if (to == 0) {                      /* entry not found */
498         ka_PrintUserID ("GetTicket: Server ", sname, sinst, " unknown.\n");
499         code = KERB_ERR_PRINCIPAL_UNKNOWN; /* KANOENT */
500         goto abort;
501     }
502     code = ubik_EndTrans (tt);
503     if (code) goto fail;
504
505     if (ntohl(server.flags) & KAFNOSEAL) return KABADSERVER;
506
507     code = des_random_key (&sessionKey);
508     if (code) {
509       code = KERB_ERR_NULL_KEY; /* was KANOKEYS */
510       goto fail;
511     }
512
513     reqEnd = umin (umin (reqEnd, authEnd),
514                 umin (start+ntohl(caller.max_ticket_lifetime),
515                       start+ntohl(server.max_ticket_lifetime)));
516
517     code = tkt_MakeTicket (newTicket, &newTicketLen, &server.key,
518                            caller.userID.name, caller.userID.instance, cell,
519                            start, reqEnd, &sessionKey,
520                            htonl(pkt->from.sin_addr.s_addr),
521                            server.userID.name, server.userID.instance);
522     if (code) goto fail;
523
524     cipherLen = sizeof(cipher);
525     code = create_cipher
526         (cipher, &cipherLen, &sessionKey, sname, sinst,
527          start, reqEnd, ntohl(server.key_version),
528          newTicket, newTicketLen, &authSessionKey);
529     if (code) goto fail;
530
531     code = create_reply (&ans, name, inst, start, reqEnd, 0,
532                          cipher, cipherLen);
533     if (code) goto fail;
534
535     code = sendto (ksoc, ans.data, ans.len, 0,
536                    (struct sockaddr *) &pkt->from, sizeof(pkt->from));
537     if (code != ans.len) {
538         perror ("calling sendto");
539         code = -1;
540         goto fail;
541     }
542
543     if (cipherLen != 0) {
544         KALOG(name, inst, sname, sinst, NULL, host, LOG_GETTICKET);
545     }
546     osi_audit ( UDPGetTicketEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_STR, cell, AUD_STR, sname, AUD_STR, sinst, AUD_END);
547     return 0;
548
549 abort:
550     ubik_AbortTrans(tt);
551 fail:
552     osi_audit ( UDPGetTicketEvent, code, AUD_STR, name, AUD_STR, inst, AUD_STR, NULL, AUD_STR, NULL, AUD_STR, NULL, AUD_END);
553     return code;
554 }
555  
556 static err_packet (ksoc, pkt, code, reason)
557   int ksoc;
558   struct packet *pkt;
559   afs_int32  code;
560   char *reason;
561 {   struct packet ans;
562     char *answer = ans.data;
563     int   slen;
564     char  buf[256];
565
566     if (reason == 0) reason = "";
567     snprintf (buf, 255, "code = %d: %s", code, reason);
568
569     if (krb_udp_debug) {
570         printf ("Sending error packet to '%s'.'%s'@'%s' containing %s\n",
571                 pkt->name, pkt->inst, pkt->realm, buf);
572     }
573
574     ans.len = 2 + strlen(pkt->name) + strlen(pkt->inst) + strlen(pkt->realm) +
575         3/* nulls */ + (2 * sizeof(afs_int32)) + strlen (buf) + 1;
576     if (ans.len > sizeof(ans.data)) {
577         printf ("Answer packet too long\n");
578         return;
579     }
580
581     *answer++ = (unsigned char) KRB_PROT_VERSION;
582     *answer++ = (unsigned char) AUTH_MSG_ERR_REPLY;
583     /* always send claiming network byte order */
584     putstr (pkt->name);
585     putstr (pkt->inst);
586     putstr (pkt->realm);
587     putint (pkt->time);
588     if ((code < 0) || (code > KERB_ERR_MAXIMUM)) {
589         /* It could be because of kauth errors so we should return something instead of success!! */
590         code = KDC_GEN_ERR;
591     }
592     putint (code);
593     putstr (buf);
594
595     code = sendto(ksoc, ans.data, ans.len, 0,
596                   (struct sockaddr *) &pkt->from, sizeof(pkt->from));
597     if (code != ans.len) {
598         if (code >= 0)
599             printf ("call to sendto returned %d, sending error packet %d bytes long\n",
600                     code, ans.len);
601         else perror ("err_packet: sendto");
602     }
603 }
604
605 process_udp_auth (ksoc, pkt)
606   int ksoc;
607   struct packet *pkt;
608 {   char *packet = pkt->rest;
609     char  name[MAXKTCNAMELEN];
610     char  inst[MAXKTCNAMELEN];
611     char  realm[MAXKTCREALMLEN];
612     char  sname[MAXKTCNAMELEN];
613     char  sinst[MAXKTCNAMELEN];
614     int   slen;
615     Date  now = time(0);
616     Date  startTime, endTime;
617     unsigned char lifetime;
618     afs_int32  code;
619
620     pkt->name = packet;
621     getstr (name);
622     pkt->inst = packet;
623     getstr (inst);
624     pkt->realm = packet;
625     getstr (realm);
626     if (krb_udp_debug) {
627         printf ("Processing KDC Request from '%s'.'%s'@'%s'\n",
628                 name, inst, realm);
629     }
630
631     if ((strlen(realm) > 0) && (strcmp (realm, lrealm) != 0)) {
632         err_packet (ksoc, pkt, KERB_ERR_NONNULL_REALM,
633                     "null realm name not allowed");
634         return;
635     }
636     bcopy (packet, &startTime, sizeof(startTime));
637     packet += sizeof(startTime);
638     startTime = ktohl (pkt->byteOrder, startTime);
639     pkt->time = startTime;
640     lifetime = *packet++;
641     endTime = life_to_time (startTime, lifetime);
642     code = tkt_CheckTimes (startTime, endTime, now);
643     if (code < 0) {
644         err_packet (ksoc, pkt, KERB_ERR_BAD_LIFETIME,
645                     "requested ticket lifetime invalid");
646         return;
647     }
648     getstr (sname);
649     getstr (sinst);
650     if ((packet - pkt->data) != pkt->len) {
651         err_packet (ksoc, pkt, KERB_ERR_PKT_LENGTH, "packet length inconsistent");
652         return;
653     }
654     pkt->rest = packet;
655     code = UDP_Authenticate (ksoc, &pkt->from, name, inst,
656                              startTime, endTime, sname, sinst);
657     if (code) {
658         if (code == KANOENT) {
659            code = KERB_ERR_PRINCIPAL_UNKNOWN;
660            err_packet (ksoc, pkt, code, (char *)error_message (code));
661         } else if (code == KAPWEXPIRED) {
662             code = KERB_ERR_NAME_EXP;
663             err_packet (ksoc, pkt, code, "password has expired");
664         } else 
665             err_packet (ksoc, pkt, code, (char *)error_message (code));
666     }
667     return;
668 }
669
670 process_udp_appl (ksoc, pkt)
671   int ksoc;
672   struct packet *pkt;
673 {   char *packet = pkt->rest;
674     afs_int32  kvno;
675     char  realm[MAXKTCREALMLEN];
676     char  ticket[MAXKTCTICKETLEN];
677     char  auth[3*MAXKTCNAMELEN+4+5];
678     int   slen;
679     int   ticketLen, authLen;
680     afs_int32  code;
681
682     if (krb_udp_debug) {
683         printf ("Processing APPL Request\n");
684     }
685     kvno = *packet++;
686     getstr (realm);
687     ticketLen = *(unsigned char *)packet++;
688     authLen = *(unsigned char *)packet++;
689     if (ticketLen > sizeof(ticket)) {
690         err_packet (ksoc, pkt, KERB_ERR_TEXT_LENGTH, "ticket too long");
691         return;
692     }
693     bcopy (packet, ticket, ticketLen);
694     packet += ticketLen;
695     if (authLen > sizeof(auth)) {
696         err_packet (ksoc, pkt, KERB_ERR_TEXT_LENGTH, "authenticator too long");
697         return;
698     }
699     bcopy (packet, auth, authLen);
700     pkt->rest = packet + authLen;
701     code = UDP_GetTicket (ksoc, pkt, kvno, realm, ticket, ticketLen, auth, authLen);
702     if (code) {
703         if (code == KANOENT) code = KERB_ERR_PRINCIPAL_UNKNOWN;
704         err_packet (ksoc, pkt, code, (char*)error_message (code));
705         return;
706     }
707 }
708
709 process_udp_request (ksoc, pkt)
710   int ksoc;
711   struct packet *pkt;
712 {   char *packet = pkt->data;
713     unsigned char version, auth_msg_type;
714
715     version = *packet++;
716     if (version != KRB_PROT_VERSION) {
717         err_packet (ksoc, pkt, KERB_ERR_PKT_VER, "packet version number unknown");
718         return;
719     }
720     auth_msg_type = *packet++;
721     pkt->byteOrder = auth_msg_type & 1;
722     pkt->rest = packet;
723     switch (auth_msg_type & ~1) {
724       case AUTH_MSG_KDC_REQUEST:
725         process_udp_auth (ksoc, pkt);
726         break;
727       case AUTH_MSG_APPL_REQUEST:
728         process_udp_appl (ksoc, pkt);
729         break;
730       default:
731         printf ("unknown msg type 0x%x\n", auth_msg_type);
732         err_packet (ksoc, pkt, KERB_ERR_BAD_MSG_TYPE, "message type not supported");
733         return;
734     }
735     return;
736 }
737
738 static SocketListener ()
739 {   fd_set rfds;
740     struct timeval tv;
741     struct packet packet;
742     int fromLen;
743     afs_int32 code;
744
745     printf ("Starting to listen for UDP packets\n");
746     while (1) {
747         FD_ZERO(&rfds);
748         if (sock_kerb  >= 0) FD_SET(sock_kerb, &rfds);
749         if (sock_kerb5 >= 0) FD_SET(sock_kerb5, &rfds);
750
751         tv.tv_sec = 100;
752         tv.tv_usec = 0;
753         /* write and exception fd_set's are null */
754         code = IOMGR_Select(32, &rfds, NULL, NULL, &tv);
755         if (code == 0) { /* timeout */
756             /* printf ("Timeout\n"); */
757             continue;
758         }
759         else if (code < 0) {
760             perror ("calling IOMGR_Select");
761             break;
762         }
763     
764         fromLen = sizeof(packet.from);
765         if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) {
766             code = recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0,
767                             (struct sockaddr *) &packet.from, &fromLen);
768             if (code < 0) {
769                 perror ("calling recvfrom");
770                 break;
771             }
772             packet.len = code;
773             if (krb_udp_debug) {
774                 printf ("Kerb:udp: Got %d bytes from addr %s which are '",
775                         code, afs_inet_ntoa(packet.from.sin_addr.s_addr));
776                 ka_PrintBytes (packet.data, packet.len);
777                 printf ("'\n");
778             }
779             packet.name = packet.inst = packet.realm = "";
780             packet.time = 0;
781             process_udp_request (sock_kerb, &packet);
782         } 
783         if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) {
784             code = recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0,
785                             (struct sockaddr *) &packet.from, &fromLen);
786             if (code < 0) {
787                 perror ("calling recvfrom");
788                 break;
789             }
790             packet.len = code;
791             if (krb_udp_debug) {
792                 printf ("Kerb5:udp: Got %d bytes from addr %s which are '",
793                         code, afs_inet_ntoa(packet.from.sin_addr.s_addr));
794                 ka_PrintBytes (packet.data, packet.len);
795                 printf ("'\n");
796             }
797             packet.name = packet.inst = packet.realm = "";
798             packet.time = 0;
799             process_udp_request (sock_kerb5, &packet);
800         } 
801     }
802 }
803
804 #if MAIN
805
806 #include "AFS_component_version_number.c"
807
808 main ()
809 #else
810 afs_int32 init_krb_udp ()
811 #endif
812 {   struct sockaddr_in taddr;
813     static PROCESS slPid;               /* socket listener pid */
814     static PROCESS checkPid;            /* fiveminute check */
815     afs_int32  code;
816     char*  krb4name;                    /* kerberos version4 service */
817
818 #if MAIN
819     PROCESS junk;
820 #endif
821     struct servent *sp;
822     static int inited = 0;
823     afs_int32 kerb_port;
824
825     if (inited) return -1;
826     inited = 1;
827
828     bzero (&taddr, sizeof(taddr));
829     krb4name = "kerberos4";
830     sp = getservbyname(krb4name, "udp");
831     taddr.sin_family = AF_INET;  /* added for NCR port */
832     if ( !sp )  
833     {
834         /* if kerberos-4 is not available, try "kerberos-iv" */
835         krb4name = "kerberos-iv";
836         sp = getservbyname(krb4name, "udp");
837     }
838     if ( !sp )  
839     {
840         /* if kerberos-iv is not available, try "kerberos" */
841         krb4name = "kerberos";
842         sp = getservbyname(krb4name, "udp");
843     }
844     if (!sp) {
845         fprintf (stderr, 
846           "kerberos/udp is unknown; check /etc/services.  Using port=%d as default\n",
847           KRB_PORT);
848         taddr.sin_port = htons(KRB_PORT);
849     } else {
850         /* copy the port number */
851         fprintf (stderr, "%s/udp port=%hu\n", krb4name, (unsigned short)sp->s_port);
852         taddr.sin_port = sp->s_port;
853     }
854     kerb_port = taddr.sin_port;
855     sock_kerb = socket(AF_INET, SOCK_DGRAM, 0);
856     code = bind(sock_kerb, (struct sockaddr *) &taddr, sizeof(taddr));
857     if (code < 0) {
858         perror ("calling bind");
859         sock_kerb = -1;
860     }
861
862     sp = getservbyname("kerberos5", "udp");
863     if (!sp) {
864         fprintf (stderr, 
865           "kerberos5/udp is unknown; check /etc/services.  Using port=%d as default\n",
866           KRB5_PORT);
867         taddr.sin_port = htons(KRB5_PORT);
868     } else {
869         /* copy the port number */
870         fprintf (stderr, "kerberos5/udp port=%hu\n", (unsigned short)sp->s_port);
871         taddr.sin_port = sp->s_port;
872     }
873     if (taddr.sin_port != kerb_port) { /* a different port */
874        sock_kerb5 = socket(AF_INET, SOCK_DGRAM, 0);
875        code = bind(sock_kerb5, (struct sockaddr *) &taddr, sizeof(taddr));
876        if (code < 0) {
877           perror ("calling bind");
878           sock_kerb5 = -1;
879        }
880     }
881
882     /* Bail out if we can't bind with any port */
883     if ((sock_kerb < 0) && (sock_kerb5 < 0))
884        return -1;
885
886 #if MAIN
887     /* this has already been done */
888     LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
889     IOMGR_Initialize();
890 #endif
891     LWP_CreateProcess(SocketListener, /*stacksize*/16000, LWP_NORMAL_PRIORITY,
892                       0, "Socket Listener", &slPid);
893
894         /* just to close the log every five minutes */
895
896         LWP_CreateProcess(FiveMinuteCheckLWP, 24*1024,
897                  LWP_MAX_PRIORITY - 2, &fiveminutes,
898                  "FiveMinuteChecks", &checkPid);
899
900 #if MAIN
901     initialize_ka_error_table();
902     initialize_rxk_error_table();
903     while (1)                           /* don't just stand there, run it */
904         IOMGR_Sleep (60);
905 #else
906     return 0;
907 #endif
908
909 }
910
911 #if MAIN
912 char *lastOperation;            /* name of last operation */
913 char *lrealm = "REALMNAME";
914 struct kadstats dynamic_statistics;
915
916 static int InitAuthServ (tt, lock, this_op)
917   struct ubik_trans **tt;
918   int                 lock;             /* read or write transaction */
919   int                *this_op;          /* op of RCP routine, for COUNT_ABO */
920 {   int   code = 0;
921
922     *tt = 0;
923     printf ("Calling InitAuthServ\n");
924     return code;
925 }
926
927 static int ubik_EndTrans (tt)
928   struct ubik_trans *tt;
929 {
930     printf ("Calling ubik_EndTrans\n");
931     return 0;
932 }
933
934 static int ubik_AbortTrans (tt)
935   struct ubik_trans *tt;
936 {
937     printf ("Calling ubik_AbortTrans\n");
938     return 0;
939 }
940
941 static int FindBlock (at, aname, ainstance, tentry)
942   struct ubik_trans *at;
943   char              *aname;
944   char              *ainstance;
945   struct kaentry    *tentry;
946 {
947     printf ("Calling FindBlock with '%s'.'%s'\n", aname, ainstance);
948     strcpy (tentry->userID.name, aname);
949     strcpy (tentry->userID.instance, ainstance);
950     tentry->key_version = htonl(17);
951     des_string_to_key ("toa", &tentry->key);
952     tentry->flags = htonl(KAFNORMAL);
953     tentry->user_expiration = htonl(NEVERDATE);
954     tentry->max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
955     return 323232;
956 }
957
958 static int ka_LookupKey (tt, name, inst, kvno, key)
959   struct ubik_trans *tt;
960   char              *name;
961   char              *inst;
962   afs_int32                 *kvno;              /* returned */
963   struct ktc_encryptionKey *key;        /* copied out */
964 {
965     printf ("Calling ka_LookupKey with '%s'.'%s'\n", name, inst);
966     *kvno = 23;
967     des_string_to_key ("applexx", key);
968 }
969
970 static afs_int32 kvno_tgs_key (authDomain, kvno, tgskey)
971   char *authDomain;
972   afs_int32  kvno;
973   struct ktc_encryptionKey *tgskey;
974 {
975     if (strcmp (authDomain, lrealm) != 0)
976         printf ("Called with wrong %s as authDomain\n", authDomain);
977     if (kvno != 23)
978         printf ("kvno_tgs_key: being called with wrong kvno: %d\n", kvno);
979     des_string_to_key ("applexx", tgskey);
980     return 0;
981 }
982
983 save_principal ()
984 {
985 }
986 name_instance_legal ()
987 {
988     return 1;
989 }
990 #endif