189e31360471c34e576a987258f16895be00f694
[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(AFSDIR_SERVER_KALOG_FILEPATH);        /* 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         save_principal(udpAuthPrincipal, name, inst, 0);
278
279         tgt = ((strcmp(sname, KA_TGS_NAME) == 0)
280                && (strcmp(sinst, lrealm) == 0));
281         if ((ntohl(tentry.user_expiration) < now)
282             || (tgt && (ntohl(tentry.flags) & KAFNOTGS))) {
283             code = KERB_ERR_NAME_EXP;   /* KABADUSER */
284             goto abort;
285         }
286         code = FindBlock(tt, KA_TGS_NAME, lrealm, &sto, &sentry);
287         if (code)
288             goto abort;
289         if (sto == 0) {
290             code = KANOENT;
291             goto abort;
292         }
293         if ((ntohl(sentry.user_expiration) < now)) {
294             code = KERB_ERR_NAME_EXP;   /* XXX Could use another error code XXX */
295             goto abort;
296         }
297         if (startTime - now > KTC_TIME_UNCERTAINTY) {
298             code = KERB_ERR_SERVICE_EXP;        /* was KABADREQUEST */
299             goto abort;
300         }
301
302         if (tentry.misc_auth_bytes) {
303             unsigned char misc_auth_bytes[4];
304             afs_uint32 temp;    /* unsigned for safety */
305             afs_uint32 pwexpires;
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
322         /* make the ticket */
323         code = DES_new_random_key(ktc_to_cblock(&sessionKey));
324         if (code) {
325             code = KERB_ERR_NULL_KEY;   /* was KANOKEYS */
326             goto abort;
327         }
328         endTime =
329             umin(endTime, startTime + ntohl(tentry.max_ticket_lifetime));
330         if ((code = ka_LookupKey(tt, sname, sinst, &tgskvno, &tgskey))
331             || (code =
332                 tkt_MakeTicket(ticket, &ticketLen, &tgskey, name, inst,
333                                lrealm, startTime, endTime, &sessionKey,
334                                htonl(client->sin_addr.s_addr), sname, sinst)))
335             goto abort;
336
337         cipherLen = sizeof(cipher);
338         code =
339             create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst,
340                           startTime, endTime, tgskvno, ticket, ticketLen,
341                           &tentry.key);
342         if (code)
343             goto abort;
344     } else {                    /* no such user */
345         cipherLen = 0;
346         tentry.key_version = 0;
347     }
348     code = ubik_EndTrans(tt);
349     if (code)
350         goto fail;
351
352     code =
353         create_reply(&ans, name, inst, startTime, endTime,
354                      ntohl(tentry.key_version), cipher, cipherLen);
355     if (code)
356         goto fail;
357
358     if (krb_udp_debug) {
359         printf("Sending %d bytes ending in: ", ans.len);
360         ka_PrintBytes(ans.data + ans.len - 8, 8);
361         printf("\n");
362     }
363
364     code =
365         sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)client,
366                sizeof(*client));
367     if (code != ans.len) {
368         perror("calling sendto");
369         code = -1;
370         goto fail;
371     }
372     KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr,
373           LOG_AUTHENTICATE);
374
375     if (cipherLen != 0) {
376         KALOG(name, inst, sname, sinst, NULL, client->sin_addr.s_addr,
377               LOG_TGTREQUEST);
378     }
379     osi_audit(UDPAuthenticateEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_END);
380     return 0;
381
382   abort:
383     COUNT_ABO;
384     ubik_AbortTrans(tt);
385
386   fail:
387     osi_audit(UDPAuthenticateEvent, code, AUD_STR, name, AUD_STR, inst,
388               AUD_END);
389     return code;
390 }
391
392 afs_int32
393 UDP_GetTicket(int ksoc, struct packet *pkt, afs_int32 kvno,
394               char *authDomain, char *ticket, int ticketLen, char *auth,
395               int authLen)
396 {
397     afs_int32 code;
398     struct ktc_encryptionKey tgskey;
399     char name[MAXKTCNAMELEN];
400     char inst[MAXKTCNAMELEN];
401     char cell[MAXKTCREALMLEN];
402     struct ktc_encryptionKey authSessionKey;
403     afs_int32 host;
404     Date start;
405     Date authEnd;
406     Date now = time(0);
407     int celllen;
408     int import;
409
410     char *packet;
411     int slen;
412     int byteOrder = pkt->byteOrder;
413     char sname[MAXKTCNAMELEN];
414     char sinst[MAXKTCNAMELEN];
415     afs_int32 time_ws;
416     unsigned char life;
417
418     struct ubik_trans *tt;
419     afs_int32 to;
420     struct kaentry caller;
421     struct kaentry server;
422     Date reqEnd;
423     struct ktc_encryptionKey sessionKey;
424     int newTicketLen;
425     char newTicket[MAXKTCTICKETLEN];
426
427     char cipher[2 * MAXKTCTICKETLEN];   /* put encrypted part of answer here */
428     int cipherLen;
429     struct packet ans;
430
431     COUNT_REQ(UGetTicket);
432
433     if ((code = InitAuthServ(&tt, LOCKREAD, this_op)))
434         goto fail;
435     code =
436         ka_LookupKvno(tt, KA_TGS_NAME,
437                       ((strlen(authDomain) > 0) ? authDomain : lrealm), kvno,
438                       &tgskey);
439     if (code)
440         goto abort;
441
442     code =
443         tkt_DecodeTicket(ticket, ticketLen, &tgskey, name, inst, cell,
444                          &authSessionKey, &host, &start, &authEnd);
445     pkt->name = name;
446     pkt->inst = inst;
447     pkt->realm = cell;
448     if (code) {
449         code = KERB_ERR_AUTH_EXP;       /* was KANOAUTH */
450         goto abort;
451     }
452     save_principal(udptgsPrincipal, name, inst, cell);
453     code = tkt_CheckTimes(start, authEnd, now);
454     if (code <= 0) {
455         if (code == -1) {
456             code = KERB_ERR_SERVICE_EXP;        /* was RXKADEXPIRED */
457             goto abort;
458         }
459         code = KERB_ERR_AUTH_EXP;       /* was KANOAUTH */
460         goto abort;
461     }
462     celllen = strlen(cell);
463     import = 0;
464     if ((strlen(authDomain) > 0) && (strcmp(authDomain, lrealm) != 0))
465         import = 1;
466     if (import && (celllen == 0)) {
467         code = KERB_ERR_PKT_VER;        /* was KABADTICKET */
468         goto abort;
469     }
470     if (celllen == 0) {
471         strncpy(cell, lrealm, MAXKTCREALMLEN - 1);
472         cell[MAXKTCREALMLEN - 1] = 0;
473     };
474
475     if (!krb4_cross && strcmp(lrealm, cell) != 0) {
476         code = KERB_ERR_PRINCIPAL_UNKNOWN;
477         goto abort;
478     }
479
480     if (krb_udp_debug) {
481         printf("UGetTicket: got ticket from '%s'.'%s'@'%s'\n", name, inst,
482                cell);
483     }
484
485     code = check_auth(pkt, auth, authLen, &authSessionKey, name, inst, cell);
486     if (code)
487         goto abort;
488
489     /* authenticator and all is OK so read actual request */
490     packet = pkt->rest;
491     getint(time_ws);
492     life = *(unsigned char *)packet++;
493     getstr(sname);
494     getstr(sinst);
495     start = now;
496     reqEnd = life_to_time(start, life);
497     if (krb_udp_debug) {
498         printf("UGetTicket: request for server '%s'.'%s'\n", sname, sinst);
499     }
500     save_principal(udptgsServerPrincipal, sname, sinst, 0);
501
502     if (import) {
503         strcpy(caller.userID.name, name);
504         strcpy(caller.userID.instance, inst);
505         caller.max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
506     } else {
507         code = FindBlock(tt, name, inst, &to, &caller);
508         if (code)
509             goto abort;
510         if (to == 0) {
511             ka_PrintUserID("GetTicket: User ", name, inst, " unknown.\n");
512             code = KERB_ERR_PRINCIPAL_UNKNOWN;  /* KANOENT */
513             goto abort;
514         }
515         if (ntohl(caller.flags) & KAFNOTGS) {
516             code = KERB_ERR_AUTH_EXP;   /* was KABADUSER */
517             goto abort;
518         }
519     }
520
521     code = FindBlock(tt, sname, sinst, &to, &server);   /* get server's entry */
522     if (code)
523         goto abort;
524     if (to == 0) {              /* entry not found */
525         ka_PrintUserID("GetTicket: Server ", sname, sinst, " unknown.\n");
526         code = KERB_ERR_PRINCIPAL_UNKNOWN;      /* KANOENT */
527         goto abort;
528     }
529     code = ubik_EndTrans(tt);
530     if (code)
531         goto fail;
532
533     if (ntohl(server.flags) & KAFNOSEAL)
534         return KABADSERVER;
535
536     code = DES_new_random_key(ktc_to_cblock(&sessionKey));
537     if (code) {
538         code = KERB_ERR_NULL_KEY;       /* was KANOKEYS */
539         goto fail;
540     }
541
542     reqEnd =
543         umin(umin(reqEnd, authEnd),
544              umin(start + ntohl(caller.max_ticket_lifetime),
545                   start + ntohl(server.max_ticket_lifetime)));
546
547     code =
548         tkt_MakeTicket(newTicket, &newTicketLen, &server.key,
549                        caller.userID.name, caller.userID.instance, cell,
550                        start, reqEnd, &sessionKey,
551                        htonl(pkt->from.sin_addr.s_addr), server.userID.name,
552                        server.userID.instance);
553     if (code)
554         goto fail;
555
556     cipherLen = sizeof(cipher);
557     code =
558         create_cipher(cipher, &cipherLen, &sessionKey, sname, sinst, start,
559                       reqEnd, ntohl(server.key_version), newTicket,
560                       newTicketLen, &authSessionKey);
561     if (code)
562         goto fail;
563
564     code =
565         create_reply(&ans, name, inst, start, reqEnd, 0, cipher, cipherLen);
566     if (code)
567         goto fail;
568
569     code =
570         sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from,
571                sizeof(pkt->from));
572     if (code != ans.len) {
573         perror("calling sendto");
574         code = -1;
575         goto fail;
576     }
577
578     if (cipherLen != 0) {
579         KALOG(name, inst, sname, sinst, NULL, host, LOG_GETTICKET);
580     }
581     osi_audit(UDPGetTicketEvent, 0, AUD_STR, name, AUD_STR, inst, AUD_STR,
582               cell, AUD_STR, sname, AUD_STR, sinst, AUD_END);
583     return 0;
584
585   abort:
586     ubik_AbortTrans(tt);
587   fail:
588     osi_audit(UDPGetTicketEvent, code, AUD_STR, name, AUD_STR, inst, AUD_STR,
589               NULL, AUD_STR, NULL, AUD_STR, NULL, AUD_END);
590     return code;
591 }
592
593 static int
594 err_packet(int ksoc, struct packet *pkt, afs_int32 code, char *reason)
595 {
596     struct packet ans;
597     char *answer = ans.data;
598     int slen;
599     char buf[256];
600
601     if (reason == 0)
602         reason = "";
603     snprintf(buf, 255, "code = %d: %s", code, reason);
604
605     if (krb_udp_debug) {
606         printf("Sending error packet to '%s'.'%s'@'%s' containing %s\n",
607                pkt->name, pkt->inst, pkt->realm, buf);
608     }
609
610     ans.len =
611         2 + strlen(pkt->name) + strlen(pkt->inst) + strlen(pkt->realm) +
612         3 /* nulls */  + (2 * sizeof(afs_int32)) + strlen(buf) + 1;
613     if (ans.len > sizeof(ans.data)) {
614         printf("Answer packet too long\n");
615         return -1;
616     }
617
618     *answer++ = (unsigned char)KRB_PROT_VERSION;
619     *answer++ = (unsigned char)AUTH_MSG_ERR_REPLY;
620     /* always send claiming network byte order */
621     putstr(pkt->name);
622     putstr(pkt->inst);
623     putstr(pkt->realm);
624     putint(pkt->time);
625     if ((code < 0) || (code > KERB_ERR_MAXIMUM)) {
626         /* It could be because of kauth errors so we should return something instead of success!! */
627         code = KDC_GEN_ERR;
628     }
629     putint(code);
630     putstr(buf);
631
632     code =
633         sendto(ksoc, ans.data, ans.len, 0, (struct sockaddr *)&pkt->from,
634                sizeof(pkt->from));
635     if (code != ans.len) {
636         if (code >= 0)
637             printf
638                 ("call to sendto returned %d, sending error packet %d bytes long\n",
639                  code, ans.len);
640         else
641             perror("err_packet: sendto");
642     }
643     return 0;
644 }
645
646 int
647 process_udp_auth(int ksoc, struct packet *pkt)
648 {
649     char *packet = pkt->rest;
650     char name[MAXKTCNAMELEN];
651     char inst[MAXKTCNAMELEN];
652     char realm[MAXKTCREALMLEN];
653     char sname[MAXKTCNAMELEN];
654     char sinst[MAXKTCNAMELEN];
655     int slen;
656     Date now = time(0);
657     Date startTime, endTime;
658     unsigned char lifetime;
659     afs_int32 code;
660
661     pkt->name = packet;
662     getstr(name);
663     pkt->inst = packet;
664     getstr(inst);
665     pkt->realm = packet;
666     getstr(realm);
667     if (krb_udp_debug) {
668         printf("Processing KDC Request from '%s'.'%s'@'%s'\n", name, inst,
669                realm);
670     }
671
672     if ((strlen(realm) > 0) && (strcmp(realm, lrealm) != 0)) {
673         err_packet(ksoc, pkt, KERB_ERR_NONNULL_REALM,
674                    "null realm name not allowed");
675         return -1;
676     }
677     memcpy(&startTime, packet, sizeof(startTime));
678     packet += sizeof(startTime);
679     startTime = ktohl(pkt->byteOrder, startTime);
680     pkt->time = startTime;
681     lifetime = *packet++;
682     endTime = life_to_time(startTime, lifetime);
683     code = tkt_CheckTimes(startTime, endTime, now);
684     if (code < 0) {
685         err_packet(ksoc, pkt, KERB_ERR_BAD_LIFETIME,
686                    "requested ticket lifetime invalid");
687         return -1;
688     }
689     getstr(sname);
690     getstr(sinst);
691     if ((packet - pkt->data) != pkt->len) {
692         err_packet(ksoc, pkt, KERB_ERR_PKT_LENGTH,
693                    "packet length inconsistent");
694         return -1;
695     }
696     pkt->rest = packet;
697     code =
698         UDP_Authenticate(ksoc, &pkt->from, name, inst, startTime, endTime,
699                          sname, sinst);
700     if (code) {
701         if (code == KANOENT) {
702             code = KERB_ERR_PRINCIPAL_UNKNOWN;
703             err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
704         } else if (code == KAPWEXPIRED) {
705             code = KERB_ERR_NAME_EXP;
706             err_packet(ksoc, pkt, code, "password has expired");
707         } else
708             err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
709     }
710     return 0;
711 }
712
713 int
714 process_udp_appl(int ksoc, struct packet *pkt)
715 {
716     char *packet = pkt->rest;
717     afs_int32 kvno;
718     char realm[MAXKTCREALMLEN];
719     char ticket[MAXKTCTICKETLEN];
720     char auth[3 * MAXKTCNAMELEN + 4 + 5];
721     int slen;
722     int ticketLen, authLen;
723     afs_int32 code;
724
725     if (krb_udp_debug) {
726         printf("Processing APPL Request\n");
727     }
728     kvno = *packet++;
729     getstr(realm);
730     ticketLen = *(unsigned char *)packet++;
731     authLen = *(unsigned char *)packet++;
732     if (ticketLen > sizeof(ticket)) {
733         err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "ticket too long");
734         return -1;
735     }
736     memcpy(ticket, packet, ticketLen);
737     packet += ticketLen;
738     if (authLen > sizeof(auth)) {
739         err_packet(ksoc, pkt, KERB_ERR_TEXT_LENGTH, "authenticator too long");
740         return -1;
741     }
742     memcpy(auth, packet, authLen);
743     pkt->rest = packet + authLen;
744     code =
745         UDP_GetTicket(ksoc, pkt, kvno, realm, ticket, ticketLen, auth,
746                       authLen);
747     if (code) {
748         if (code == KANOENT)
749             code = KERB_ERR_PRINCIPAL_UNKNOWN;
750         err_packet(ksoc, pkt, code, (char *)afs_error_message(code));
751         return -1;
752     }
753     return 0;
754 }
755
756 void
757 process_udp_request(int ksoc, struct packet *pkt)
758 {
759     char *packet = pkt->data;
760     unsigned char version, auth_msg_type;
761
762     version = *packet++;
763     if (version != KRB_PROT_VERSION) {
764         err_packet(ksoc, pkt, KERB_ERR_PKT_VER,
765                    "packet version number unknown");
766         return;
767     }
768     auth_msg_type = *packet++;
769     pkt->byteOrder = auth_msg_type & 1;
770     pkt->rest = packet;
771     switch (auth_msg_type & ~1) {
772     case AUTH_MSG_KDC_REQUEST:
773         process_udp_auth(ksoc, pkt);
774         break;
775     case AUTH_MSG_APPL_REQUEST:
776         process_udp_appl(ksoc, pkt);
777         break;
778     default:
779         printf("unknown msg type 0x%x\n", auth_msg_type);
780         err_packet(ksoc, pkt, KERB_ERR_BAD_MSG_TYPE,
781                    "message type not supported");
782         return;
783     }
784     return;
785 }
786
787 static void *
788 SocketListener(void *unused)
789 {
790     fd_set rfds;
791     struct timeval tv;
792     struct packet packet;
793     socklen_t fromLen;
794     afs_int32 code;
795     char hoststr[16];
796
797     printf("Starting to listen for UDP packets\n");
798     while (1) {
799         FD_ZERO(&rfds);
800         if (sock_kerb >= 0)
801             FD_SET(sock_kerb, &rfds);
802         if (sock_kerb5 >= 0)
803             FD_SET(sock_kerb5, &rfds);
804
805         tv.tv_sec = 100;
806         tv.tv_usec = 0;
807         /* write and exception fd_set's are null */
808         code = IOMGR_Select(32, &rfds, NULL, NULL, &tv);
809         if (code == 0) {        /* timeout */
810             /* printf ("Timeout\n"); */
811             continue;
812         } else if (code < 0) {
813             perror("calling IOMGR_Select");
814             break;
815         }
816
817         fromLen = sizeof(packet.from);
818         if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) {
819             code =
820                 recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0,
821                          (struct sockaddr *)&packet.from, &fromLen);
822             if (code < 0) {
823                 if (errno == EAGAIN || errno == ECONNREFUSED)
824                     goto try_kerb5;
825                 perror("calling recvfrom");
826                 break;
827             }
828             packet.len = code;
829             if (krb_udp_debug) {
830                 printf("Kerb:udp: Got %d bytes from addr %s which are '",
831                        code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
832                 ka_PrintBytes(packet.data, packet.len);
833                 printf("'\n");
834             }
835             packet.name = packet.inst = packet.realm = "";
836             packet.time = 0;
837             process_udp_request(sock_kerb, &packet);
838         }
839       try_kerb5:
840         if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) {
841             code =
842                 recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0,
843                          (struct sockaddr *)&packet.from, &fromLen);
844             if (code < 0) {
845                 if (errno == EAGAIN || errno == ECONNREFUSED)
846                     continue;
847                 perror("calling recvfrom");
848                 break;
849             }
850             packet.len = code;
851             if (krb_udp_debug) {
852                 printf("Kerb5:udp: Got %d bytes from addr %s which are '",
853                        code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr));
854                 ka_PrintBytes(packet.data, packet.len);
855                 printf("'\n");
856             }
857             packet.name = packet.inst = packet.realm = "";
858             packet.time = 0;
859             process_udp_request(sock_kerb5, &packet);
860         }
861     }
862     if (sock_kerb >= 0) {
863         closesocket(sock_kerb);
864         sock_kerb = -1;
865     }
866     if (sock_kerb5 >= 0) {
867         closesocket(sock_kerb5);
868         sock_kerb5 = -1;
869     }
870     printf("UDP SocketListener exiting due to error\n");
871
872     return NULL;
873 }
874
875 #if MAIN
876
877 #include "AFS_component_version_number.c"
878
879 int
880 main(int, char **)
881 #else
882 afs_int32
883 init_krb_udp(void)
884 #endif
885 {
886     struct sockaddr_in taddr;
887     static PROCESS slPid;       /* socket listener pid */
888     static PROCESS checkPid;    /* fiveminute check */
889     afs_int32 code;
890     char *krb4name;             /* kerberos version4 service */
891
892 #if MAIN
893     PROCESS junk;
894 #endif
895     struct servent *sp;
896     static int inited = 0;
897     afs_int32 kerb_port;
898
899     if (inited)
900         return -1;
901     inited = 1;
902
903     memset(&taddr, 0, sizeof(taddr));
904     krb4name = "kerberos4";
905     sp = getservbyname(krb4name, "udp");
906     taddr.sin_family = AF_INET; /* added for NCR port */
907 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
908     taddr.sin_len = sizeof(struct sockaddr_in);
909 #endif
910     if (!sp) {
911         /* if kerberos-4 is not available, try "kerberos-iv" */
912         krb4name = "kerberos-iv";
913         sp = getservbyname(krb4name, "udp");
914     }
915     if (!sp) {
916         /* if kerberos-iv is not available, try "kerberos" */
917         krb4name = "kerberos";
918         sp = getservbyname(krb4name, "udp");
919     }
920     if (!sp) {
921         fprintf(stderr,
922                 "kerberos/udp is unknown; check /etc/services.  Using port=%d as default\n",
923                 KRB_PORT);
924         taddr.sin_port = htons(KRB_PORT);
925     } else {
926         /* copy the port number */
927         fprintf(stderr, "%s/udp port=%hu\n", krb4name,
928                 (unsigned short)sp->s_port);
929         taddr.sin_port = sp->s_port;
930     }
931     kerb_port = taddr.sin_port;
932     sock_kerb = socket(AF_INET, SOCK_DGRAM, 0);
933     code = bind(sock_kerb, (struct sockaddr *)&taddr, sizeof(taddr));
934     if (code < 0) {
935         perror("calling bind");
936         sock_kerb = -1;
937     }
938
939     sp = getservbyname("kerberos5", "udp");
940     if (!sp) {
941         fprintf(stderr,
942                 "kerberos5/udp is unknown; check /etc/services.  Using port=%d as default\n",
943                 KRB5_PORT);
944         taddr.sin_port = htons(KRB5_PORT);
945     } else {
946         /* copy the port number */
947         fprintf(stderr, "kerberos5/udp port=%hu\n",
948                 (unsigned short)sp->s_port);
949         taddr.sin_port = sp->s_port;
950     }
951     if (taddr.sin_port != kerb_port) {  /* a different port */
952         sock_kerb5 = socket(AF_INET, SOCK_DGRAM, 0);
953         code = bind(sock_kerb5, (struct sockaddr *)&taddr, sizeof(taddr));
954         if (code < 0) {
955             perror("calling bind");
956             sock_kerb5 = -1;
957         }
958     }
959
960     /* Bail out if we can't bind with any port */
961     if ((sock_kerb < 0) && (sock_kerb5 < 0))
962         return -1;
963
964 #if MAIN
965     /* this has already been done */
966     LWP_InitializeProcessSupport(LWP_NORMAL_PRIORITY, &junk);
967     IOMGR_Initialize();
968 #endif
969     LWP_CreateProcess(SocketListener, /*stacksize */ 16000,
970                       LWP_NORMAL_PRIORITY, (void *)0, "Socket Listener",
971                       &slPid);
972
973     /* just to close the log every five minutes */
974
975     LWP_CreateProcess(FiveMinuteCheckLWP, 24 * 1024, LWP_MAX_PRIORITY - 2,
976                       (void *)&fiveminutes, "FiveMinuteChecks", &checkPid);
977
978 #if MAIN
979     initialize_ka_error_table();
980     initialize_rxk_error_table();
981     while (1)                   /* don't just stand there, run it */
982         IOMGR_Sleep(60);
983 #else
984     return 0;
985 #endif
986
987 }
988
989 #if MAIN
990 char *lastOperation;            /* name of last operation */
991 char *lrealm = "REALMNAME";
992 struct kadstats dynamic_statistics;
993
994 static int
995 InitAuthServ(tt, lock, this_op)
996      struct ubik_trans **tt;
997      int lock;                  /* read or write transaction */
998      int *this_op;              /* op of RCP routine, for COUNT_ABO */
999 {
1000     int code = 0;
1001
1002     *tt = 0;
1003     printf("Calling InitAuthServ\n");
1004     return code;
1005 }
1006
1007 static int
1008 ubik_EndTrans(tt)
1009      struct ubik_trans *tt;
1010 {
1011     printf("Calling ubik_EndTrans\n");
1012     return 0;
1013 }
1014
1015 static int
1016 ubik_AbortTrans(tt)
1017      struct ubik_trans *tt;
1018 {
1019     printf("Calling ubik_AbortTrans\n");
1020     return 0;
1021 }
1022
1023 static int
1024 FindBlock(at, aname, ainstance, tentry)
1025      struct ubik_trans *at;
1026      char *aname;
1027      char *ainstance;
1028      struct kaentry *tentry;
1029 {
1030     printf("Calling FindBlock with '%s'.'%s'\n", aname, ainstance);
1031     strcpy(tentry->userID.name, aname);
1032     strcpy(tentry->userID.instance, ainstance);
1033     tentry->key_version = htonl(17);
1034     DES_string_to_key("toa", &tentry->key);
1035     tentry->flags = htonl(KAFNORMAL);
1036     tentry->user_expiration = htonl(NEVERDATE);
1037     tentry->max_ticket_lifetime = htonl(MAXKTCTICKETLIFETIME);
1038     return 323232;
1039 }
1040
1041 static int
1042 ka_LookupKey(tt, name, inst, kvno, key)
1043      struct ubik_trans *tt;
1044      char *name;
1045      char *inst;
1046      afs_int32 *kvno;           /* returned */
1047      struct ktc_encryptionKey *key;     /* copied out */
1048 {
1049     printf("Calling ka_LookupKey with '%s'.'%s'\n", name, inst);
1050     *kvno = 23;
1051     DES_string_to_key("applexx", key);
1052 }
1053
1054 static afs_int32
1055 kvno_tgs_key(authDomain, kvno, tgskey)
1056      char *authDomain;
1057      afs_int32 kvno;
1058      struct ktc_encryptionKey *tgskey;
1059 {
1060     if (strcmp(authDomain, lrealm) != 0)
1061         printf("Called with wrong %s as authDomain\n", authDomain);
1062     if (kvno != 23)
1063         printf("kvno_tgs_key: being called with wrong kvno: %d\n", kvno);
1064     DES_string_to_key("applexx", tgskey);
1065     return 0;
1066 }
1067
1068 save_principal()
1069 {
1070 }
1071
1072 name_instance_legal()
1073 {
1074     return 1;
1075 }
1076 #endif