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