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