816ebd416bad6ea1b0699e26dec3884ab61bee8b
[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                     memcpy(answer, &num, 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) memcpy(&num, packet, 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
104         printf("start 5 min check lwp\n");
105
106         while(1)
107         {
108             IOMGR_Sleep(fiveminutes);
109             /* close the log so it can be removed */
110             ReOpenLog(AFSDIR_SERVER_KALOG_FILEPATH);/* no trunc, just append */
111         }
112 }
113
114
115 static afs_int32 create_cipher (cipher, cipherLen, sessionKey, sname, sinst,
116                            start, end, kvno, ticket, ticketLen, key)
117   char *cipher;
118   int  *cipherLen;
119   struct ktc_encryptionKey *sessionKey;
120   char *sname;
121   char *sinst;
122   Date  start, end;
123   afs_int32  kvno;
124   char *ticket;
125   int   ticketLen;
126   struct ktc_encryptionKey *key;
127 {   char *answer;
128     int   slen;
129     unsigned char life = time_to_life (start, end);
130     int   len;
131     des_key_schedule schedule;
132     afs_int32  code;
133
134     answer = cipher;
135     len = sizeof(*sessionKey) + strlen(sname) + strlen(sinst) +
136         strlen(lrealm) + 3/*nulls*/ + 3 + ticketLen + sizeof(Date);
137     if (len > *cipherLen) return KAANSWERTOOLONG;
138     if (ticketLen > 255) return KAANSWERTOOLONG;
139     if (kvno > 255) return KAANSWERTOOLONG;
140
141     memcpy(answer, sessionKey, sizeof(*sessionKey));
142     answer += sizeof(*sessionKey);
143     putstr (sname);
144     putstr (sinst);
145     putstr (lrealm);
146     *answer++ = life;
147     *answer++ = (unsigned char) kvno;
148     *answer++ = (unsigned char) ticketLen;
149     memcpy(answer, ticket, ticketLen);
150     answer += ticketLen;
151     putint (start);
152
153     if (krb_udp_debug) {
154         printf ("Printing ticket (%d) and date: ", ticketLen);
155         ka_PrintBytes (ticket, ticketLen);
156         ka_PrintBytes (answer-4, 4);
157         printf ("\n");
158     }
159
160     if (code = des_key_sched (key, schedule))
161         printf ("In KAAuthenticate: key_sched returned %d\n", code);
162     des_pcbc_encrypt (cipher, cipher, len, schedule, key, ENCRYPT);
163     *cipherLen = round_up_to_ebs (len);
164
165     if (krb_udp_debug) {
166         printf ("Printing cipher (%d): ", *cipherLen);
167         ka_PrintBytes (cipher, *cipherLen);
168         printf ("\n");
169     }
170     return 0;
171 }
172
173 static afs_int32 create_reply (ans, name, inst, startTime, endTime, kvno,
174                           cipher, cipherLen)
175   struct packet *ans;
176   char *name;
177   char *inst;
178   Date  startTime, endTime;
179   afs_int32  kvno;
180   char *cipher;
181   int   cipherLen;
182 {   char *answer = ans->data;
183     int   slen;
184
185     ans->len = 2 + strlen(name) + strlen(inst) + 3/*nulls*/ +
186         sizeof(afs_int32) + 1/*ntkts*/ + sizeof(afs_int32) + 1/*kvno*/ +
187         sizeof(short) + cipherLen;
188     if (ans->len > sizeof(ans->data)) return KAANSWERTOOLONG;
189     if (kvno > 255) return KAANSWERTOOLONG;
190         
191     *answer++ = (unsigned char) KRB_PROT_VERSION;
192     *answer++ = (unsigned char) AUTH_MSG_KDC_REPLY;
193     /* always send claiming network byte order */
194     putstr (name);
195     putstr (inst);
196     putstr ("");
197     putint (startTime);
198     *answer++ = 1;                      /* undocumented number of tickets! */
199     putint (endTime);
200     *answer++ = (unsigned char) kvno;
201     {   short w = (short) cipherLen;
202         w = htons(w);
203         memcpy(answer, &w, sizeof(short));
204         answer += sizeof(short);
205     }
206     memcpy(answer, cipher, cipherLen);
207     return 0;
208 }
209
210 static afs_int32 check_auth (pkt, auth, authLen, key, name, inst, cell)
211   struct packet *pkt;
212   char *auth;
213   int   authLen;
214   struct ktc_encryptionKey *key;
215   char *name;
216   char *inst;
217   char *cell;
218 {   char *packet;
219     des_key_schedule schedule;
220     afs_int32  cksum;
221     /* unsigned char time_msec; */
222     afs_int32  time_sec;
223     int   byteOrder = pkt->byteOrder;
224
225     des_key_sched (key, schedule);
226     des_pcbc_encrypt (auth, auth, authLen, schedule, key, DECRYPT);
227     packet = auth;
228     if (strcmp (packet, name) != 0) return KABADTICKET;
229     packet += strlen (packet) + 1;
230     if (strcmp (packet, inst) != 0) return KABADTICKET;
231     packet += strlen (packet) + 1;
232     if (strcmp (packet, cell) != 0) return KABADTICKET;
233     packet += strlen (packet) + 1;
234     getint (cksum);
235     /* time_msec = */ *(unsigned char *)packet++;
236     getint (time_sec);
237     if ((packet-auth) > authLen) return KABADTICKET;
238     return 0;
239 }
240
241 afs_int32 UDP_Authenticate (ksoc, client, name, inst, startTime, endTime, sname, sinst)
242   int ksoc;
243   struct sockaddr_in *client;
244   char *name;
245   char *inst;
246   Date  startTime;
247   Date  endTime;
248   char *sname;
249   char *sinst;
250 {   struct ubik_trans *tt;
251     afs_int32  to;                              /* offset of block */
252     struct kaentry tentry;
253     afs_int32  tgskvno;                 /* key version of service key */
254     struct ktc_encryptionKey tgskey;    /* service key for encrypting ticket */
255     int   tgt;
256     Date  now = time(0);
257     afs_int32  code;
258
259     char  ticket[MAXKTCTICKETLEN];      /* our copy of the ticket */
260     int   ticketLen;
261     struct ktc_encryptionKey sessionKey; /* we have to invent a session key */
262
263     char  cipher[2*MAXKTCTICKETLEN];    /* put encrypted part of answer here */
264     int   cipherLen;
265     struct packet ans;
266
267     COUNT_REQ (UAuthenticate);
268     if (!name_instance_legal (name, inst)) return KERB_ERR_NAME_EXP;    /* KABADNAME */
269     if (code = InitAuthServ (&tt, LOCKREAD, this_op)) return code;
270     
271     code = FindBlock (tt, name, inst, &to, &tentry);
272     if (code) goto abort;
273     if (to) {                           /* if user exists check other stuff */
274         afs_int32 sto;
275         struct kaentry sentry;
276         save_principal (udpAuthPrincipal, name, inst, 0);
277         
278         tgt = ((strcmp (sname, KA_TGS_NAME) == 0) &&
279                (strcmp (sinst, lrealm) == 0));
280         if ((ntohl(tentry.user_expiration) < now) ||
281             (tgt && (ntohl(tentry.flags) & KAFNOTGS))) {
282             code = KERB_ERR_NAME_EXP;   /* KABADUSER */
283             goto abort;
284         }
285         code = FindBlock (tt, KA_TGS_NAME, lrealm, &sto, &sentry);
286         if (code) goto abort;
287         if (sto == 0) {code = KANOENT; goto abort; }
288         if ((ntohl(sentry.user_expiration) < now)) {
289             code = KERB_ERR_NAME_EXP;   /* XXX Could use another error code XXX */
290             goto abort;
291         }
292         if (abs (startTime - now) > KTC_TIME_UNCERTAINTY) {
293             code = KERB_ERR_SERVICE_EXP;        /* was KABADREQUEST */
294             goto abort;
295         }
296         
297         if (tentry.misc_auth_bytes) {
298           unsigned char misc_auth_bytes[4];
299           afs_uint32 temp;        /* unsigned for safety */
300           afs_uint32 pwexpires;
301           
302           temp = ntohl(*((afs_int32 *)(tentry.misc_auth_bytes)));
303           unpack_long(temp, misc_auth_bytes);
304           pwexpires = misc_auth_bytes[0];
305           if (pwexpires) {
306             pwexpires= ntohl(tentry.change_password_time) + 24*60*60*pwexpires;
307             if ( pwexpires < now ) {
308               code = KERB_ERR_AUTH_EXP; /* was KAPWEXPIRED */
309               goto abort;
310             }
311           }
312         }
313
314         /* make the ticket */
315         code = des_random_key (&sessionKey);
316         if (code) {
317             code = KERB_ERR_NULL_KEY;   /* was KANOKEYS */
318             goto abort;
319         }
320         endTime = umin (endTime,
321                         startTime + ntohl(tentry.max_ticket_lifetime));
322         if ((code = ka_LookupKey (tt, sname, sinst, &tgskvno, &tgskey)) ||
323             (code = tkt_MakeTicket (ticket, &ticketLen, &tgskey,
324                                     name, inst, lrealm,
325                                     startTime, endTime, &sessionKey,
326                                     htonl(client->sin_addr.s_addr), sname, sinst)))
327             goto abort;
328
329         cipherLen = sizeof(cipher);
330         code = create_cipher
331             (cipher, &cipherLen, &sessionKey, sname, sinst,
332              startTime, endTime, tgskvno, ticket, ticketLen, &tentry.key);
333         if (code) goto abort;
334     } else { /* no such user */
335         cipherLen = 0;
336         tentry.key_version = 0;
337     }
338     code = ubik_EndTrans(tt);
339     if (code) 
340       goto fail;
341
342     code = create_reply (&ans, name, inst, startTime, endTime,
343                          ntohl(tentry.key_version), cipher, cipherLen);
344     if (code) 
345        goto fail;
346
347     if (krb_udp_debug) {
348         printf ("Sending %d bytes ending in: ", ans.len);
349         ka_PrintBytes (ans.data+ans.len-8, 8);
350         printf ("\n");
351     }
352
353     code = sendto (ksoc, ans.data, ans.len, 0,
354                    (struct sockaddr *) client, sizeof(*client));
355     if (code != ans.len) {
356         perror ("calling sendto");
357         code = -1;
358         goto fail;
359     }
360     KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr, LOG_AUTHENTICATE);
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 int 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 -1;
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     return 0;
604 }
605
606 int
607 process_udp_auth (ksoc, pkt)
608   int ksoc;
609   struct packet *pkt;
610 {   char *packet = pkt->rest;
611     char  name[MAXKTCNAMELEN];
612     char  inst[MAXKTCNAMELEN];
613     char  realm[MAXKTCREALMLEN];
614     char  sname[MAXKTCNAMELEN];
615     char  sinst[MAXKTCNAMELEN];
616     int   slen;
617     Date  now = time(0);
618     Date  startTime, endTime;
619     unsigned char lifetime;
620     afs_int32  code;
621
622     pkt->name = packet;
623     getstr (name);
624     pkt->inst = packet;
625     getstr (inst);
626     pkt->realm = packet;
627     getstr (realm);
628     if (krb_udp_debug) {
629         printf ("Processing KDC Request from '%s'.'%s'@'%s'\n",
630                 name, inst, realm);
631     }
632
633     if ((strlen(realm) > 0) && (strcmp (realm, lrealm) != 0)) {
634         err_packet (ksoc, pkt, KERB_ERR_NONNULL_REALM,
635                     "null realm name not allowed");
636         return -1;
637     }
638     memcpy(&startTime, packet, sizeof(startTime));
639     packet += sizeof(startTime);
640     startTime = ktohl (pkt->byteOrder, startTime);
641     pkt->time = startTime;
642     lifetime = *packet++;
643     endTime = life_to_time (startTime, lifetime);
644     code = tkt_CheckTimes (startTime, endTime, now);
645     if (code < 0) {
646         err_packet (ksoc, pkt, KERB_ERR_BAD_LIFETIME,
647                     "requested ticket lifetime invalid");
648         return -1;
649     }
650     getstr (sname);
651     getstr (sinst);
652     if ((packet - pkt->data) != pkt->len) {
653         err_packet (ksoc, pkt, KERB_ERR_PKT_LENGTH, "packet length inconsistent");
654         return -1;
655     }
656     pkt->rest = packet;
657     code = UDP_Authenticate (ksoc, &pkt->from, name, inst,
658                              startTime, endTime, sname, sinst);
659     if (code) {
660         if (code == KANOENT) {
661            code = KERB_ERR_PRINCIPAL_UNKNOWN;
662            err_packet (ksoc, pkt, code, (char *)error_message (code));
663         } else if (code == KAPWEXPIRED) {
664             code = KERB_ERR_NAME_EXP;
665             err_packet (ksoc, pkt, code, "password has expired");
666         } else 
667             err_packet (ksoc, pkt, code, (char *)error_message (code));
668     }
669     return 0;
670 }
671
672 int
673 process_udp_appl (ksoc, pkt)
674   int ksoc;
675   struct packet *pkt;
676 {   char *packet = pkt->rest;
677     afs_int32  kvno;
678     char  realm[MAXKTCREALMLEN];
679     char  ticket[MAXKTCTICKETLEN];
680     char  auth[3*MAXKTCNAMELEN+4+5];
681     int   slen;
682     int   ticketLen, authLen;
683     afs_int32  code;
684
685     if (krb_udp_debug) {
686         printf ("Processing APPL Request\n");
687     }
688     kvno = *packet++;
689     getstr (realm);
690     ticketLen = *(unsigned char *)packet++;
691     authLen = *(unsigned char *)packet++;
692     if (ticketLen > sizeof(ticket)) {
693         err_packet (ksoc, pkt, KERB_ERR_TEXT_LENGTH, "ticket too long");
694         return -1;
695     }
696     memcpy(ticket, packet, ticketLen);
697     packet += ticketLen;
698     if (authLen > sizeof(auth)) {
699         err_packet (ksoc, pkt, KERB_ERR_TEXT_LENGTH, "authenticator too long");
700         return -1;
701     }
702     memcpy(auth, packet, authLen);
703     pkt->rest = packet + authLen;
704     code = UDP_GetTicket (ksoc, pkt, kvno, realm, ticket, ticketLen, auth, authLen);
705     if (code) {
706         if (code == KANOENT) code = KERB_ERR_PRINCIPAL_UNKNOWN;
707         err_packet (ksoc, pkt, code, (char*)error_message (code));
708         return -1;
709     }
710     return 0;
711 }
712
713 void
714 process_udp_request (ksoc, pkt)
715   int ksoc;
716   struct packet *pkt;
717 {   char *packet = pkt->data;
718     unsigned char version, auth_msg_type;
719
720     version = *packet++;
721     if (version != KRB_PROT_VERSION) {
722         err_packet (ksoc, pkt, KERB_ERR_PKT_VER, "packet version number unknown");
723         return;
724     }
725     auth_msg_type = *packet++;
726     pkt->byteOrder = auth_msg_type & 1;
727     pkt->rest = packet;
728     switch (auth_msg_type & ~1) {
729       case AUTH_MSG_KDC_REQUEST:
730         process_udp_auth (ksoc, pkt);
731         break;
732       case AUTH_MSG_APPL_REQUEST:
733         process_udp_appl (ksoc, pkt);
734         break;
735       default:
736         printf ("unknown msg type 0x%x\n", auth_msg_type);
737         err_packet (ksoc, pkt, KERB_ERR_BAD_MSG_TYPE, "message type not supported");
738         return;
739     }
740     return;
741 }
742
743 static SocketListener ()
744 {   fd_set rfds;
745     struct timeval tv;
746     struct packet packet;
747     int fromLen;
748     afs_int32 code;
749
750     printf ("Starting to listen for UDP packets\n");
751     while (1) {
752         FD_ZERO(&rfds);
753         if (sock_kerb  >= 0) FD_SET(sock_kerb, &rfds);
754         if (sock_kerb5 >= 0) FD_SET(sock_kerb5, &rfds);
755
756         tv.tv_sec = 100;
757         tv.tv_usec = 0;
758         /* write and exception fd_set's are null */
759         code = IOMGR_Select(32, &rfds, NULL, NULL, &tv);
760         if (code == 0) { /* timeout */
761             /* printf ("Timeout\n"); */
762             continue;
763         }
764         else if (code < 0) {
765             perror ("calling IOMGR_Select");
766             break;
767         }
768     
769         fromLen = sizeof(packet.from);
770         if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) {
771             code = recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0,
772                             (struct sockaddr *) &packet.from, &fromLen);
773             if (code < 0) {
774                 perror ("calling recvfrom");
775                 break;
776             }
777             packet.len = code;
778             if (krb_udp_debug) {
779                 printf ("Kerb:udp: Got %d bytes from addr %s which are '",
780                         code, afs_inet_ntoa(packet.from.sin_addr.s_addr));
781                 ka_PrintBytes (packet.data, packet.len);
782                 printf ("'\n");
783             }
784             packet.name = packet.inst = packet.realm = "";
785             packet.time = 0;
786             process_udp_request (sock_kerb, &packet);
787         } 
788         if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) {
789             code = recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0,
790                             (struct sockaddr *) &packet.from, &fromLen);
791             if (code < 0) {
792                 perror ("calling recvfrom");
793                 break;
794             }
795             packet.len = code;
796             if (krb_udp_debug) {
797                 printf ("Kerb5:udp: Got %d bytes from addr %s which are '",
798                         code, afs_inet_ntoa(packet.from.sin_addr.s_addr));
799                 ka_PrintBytes (packet.data, packet.len);
800                 printf ("'\n");
801             }
802             packet.name = packet.inst = packet.realm = "";
803             packet.time = 0;
804             process_udp_request (sock_kerb5, &packet);
805         } 
806     }
807 }
808
809 #if MAIN
810
811 #include "AFS_component_version_number.c"
812
813 main ()
814 #else
815 afs_int32 init_krb_udp ()
816 #endif
817 {   struct sockaddr_in taddr;
818     static PROCESS slPid;               /* socket listener pid */
819     static PROCESS checkPid;            /* fiveminute check */
820     afs_int32  code;
821     char*  krb4name;                    /* kerberos version4 service */
822
823 #if MAIN
824     PROCESS junk;
825 #endif
826     struct servent *sp;
827     static int inited = 0;
828     afs_int32 kerb_port;
829
830     if (inited) return -1;
831     inited = 1;
832
833     memset(&taddr, 0, sizeof(taddr));
834     krb4name = "kerberos4";
835     sp = getservbyname(krb4name, "udp");
836     taddr.sin_family = AF_INET;  /* added for NCR port */
837     if ( !sp )  
838     {
839         /* if kerberos-4 is not available, try "kerberos-iv" */
840         krb4name = "kerberos-iv";
841         sp = getservbyname(krb4name, "udp");
842     }
843     if ( !sp )  
844     {
845         /* if kerberos-iv is not available, try "kerberos" */
846         krb4name = "kerberos";
847         sp = getservbyname(krb4name, "udp");
848     }
849     if (!sp) {
850         fprintf (stderr, 
851           "kerberos/udp is unknown; check /etc/services.  Using port=%d as default\n",
852           KRB_PORT);
853         taddr.sin_port = htons(KRB_PORT);
854     } else {
855         /* copy the port number */
856         fprintf (stderr, "%s/udp port=%hu\n", krb4name, (unsigned short)sp->s_port);
857         taddr.sin_port = sp->s_port;
858     }
859     kerb_port = taddr.sin_port;
860     sock_kerb = socket(AF_INET, SOCK_DGRAM, 0);
861     code = bind(sock_kerb, (struct sockaddr *) &taddr, sizeof(taddr));
862     if (code < 0) {
863         perror ("calling bind");
864         sock_kerb = -1;
865     }
866
867     sp = getservbyname("kerberos5", "udp");
868     if (!sp) {
869         fprintf (stderr, 
870           "kerberos5/udp is unknown; check /etc/services.  Using port=%d as default\n",
871           KRB5_PORT);
872         taddr.sin_port = htons(KRB5_PORT);
873     } else {
874         /* copy the port number */
875         fprintf (stderr, "kerberos5/udp port=%hu\n", (unsigned short)sp->s_port);
876         taddr.sin_port = sp->s_port;
877     }
878     if (taddr.sin_port != kerb_port) { /* a different port */
879        sock_kerb5 = socket(AF_INET, SOCK_DGRAM, 0);
880        code = bind(sock_kerb5, (struct sockaddr *) &taddr, sizeof(taddr));
881        if (code < 0) {
882           perror ("calling bind");
883           sock_kerb5 = -1;
884        }
885     }
886
887     /* Bail out if we can't bind with any port */
888     if ((sock_kerb < 0) && (sock_kerb5 < 0))
889        return -1;
890
891 #if MAIN
892     /* this has already been done */
893     LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
894     IOMGR_Initialize();
895 #endif
896     LWP_CreateProcess(SocketListener, /*stacksize*/16000, LWP_NORMAL_PRIORITY,
897                       0, "Socket Listener", &slPid);
898
899         /* just to close the log every five minutes */
900
901         LWP_CreateProcess(FiveMinuteCheckLWP, 24*1024,
902                  LWP_MAX_PRIORITY - 2, &fiveminutes,
903                  "FiveMinuteChecks", &checkPid);
904
905 #if MAIN
906     initialize_ka_error_table();
907     initialize_rxk_error_table();
908     while (1)                           /* don't just stand there, run it */
909         IOMGR_Sleep (60);
910 #else
911     return 0;
912 #endif
913
914 }
915
916 #if MAIN
917 char *lastOperation;            /* name of last operation */
918 char *lrealm = "REALMNAME";
919 struct kadstats dynamic_statistics;
920
921 static int InitAuthServ (tt, lock, this_op)
922   struct ubik_trans **tt;
923   int                 lock;             /* read or write transaction */
924   int                *this_op;          /* op of RCP routine, for COUNT_ABO */
925 {   int   code = 0;
926
927     *tt = 0;
928     printf ("Calling InitAuthServ\n");
929     return code;
930 }
931
932 static int ubik_EndTrans (tt)
933   struct ubik_trans *tt;
934 {
935     printf ("Calling ubik_EndTrans\n");
936     return 0;
937 }
938
939 static int ubik_AbortTrans (tt)
940   struct ubik_trans *tt;
941 {
942     printf ("Calling ubik_AbortTrans\n");
943     return 0;
944 }
945
946 static int FindBlock (at, aname, ainstance, tentry)
947   struct ubik_trans *at;
948   char              *aname;
949   char              *ainstance;
950   struct kaentry    *tentry;
951 {
952     printf ("Calling FindBlock with '%s'.'%s'\n", aname, ainstance);
953     strcpy (tentry->userID.name, aname);
954     strcpy (tentry->userID.instance, ainstance);
955     tentry->key_version = htonl(17);
956     des_string_to_key ("toa", &tentry->key);
957     tentry->flags = htonl(KAFNORMAL);
958     tentry->user_expiration = htonl(NEVERDATE);
959     tentry->max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
960     return 323232;
961 }
962
963 static int ka_LookupKey (tt, name, inst, kvno, key)
964   struct ubik_trans *tt;
965   char              *name;
966   char              *inst;
967   afs_int32                 *kvno;              /* returned */
968   struct ktc_encryptionKey *key;        /* copied out */
969 {
970     printf ("Calling ka_LookupKey with '%s'.'%s'\n", name, inst);
971     *kvno = 23;
972     des_string_to_key ("applexx", key);
973 }
974
975 static afs_int32 kvno_tgs_key (authDomain, kvno, tgskey)
976   char *authDomain;
977   afs_int32  kvno;
978   struct ktc_encryptionKey *tgskey;
979 {
980     if (strcmp (authDomain, lrealm) != 0)
981         printf ("Called with wrong %s as authDomain\n", authDomain);
982     if (kvno != 23)
983         printf ("kvno_tgs_key: being called with wrong kvno: %d\n", kvno);
984     des_string_to_key ("applexx", tgskey);
985     return 0;
986 }
987
988 save_principal ()
989 {
990 }
991 name_instance_legal ()
992 {
993     return 1;
994 }
995 #endif