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