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