2 #include <sys/socket.h>
4 Unacked *rlm_nacklist = NULL; /* not acked list for realm-realm
6 Realm *otherrealms; /* points to an array of the known
8 int nrealms = 0; /* number of other realms */
13 * Realm *realm_which_realm(struct sockaddr_in *who)
14 * figures out if this packet came from another realm's server
16 * Realm *realm_get_realm_by_pid(int pid)
17 * figures out which realm a child handler was for
19 * void kill_realm_pids()
20 * kills all ticket getting childen
22 * char *realm_expand_realm(char *realmname)
23 * figures out what an abbreviated realm expands to
25 * Code_t realm_send_realms()
26 * loops through all realms for a brain dump
28 * int realm_bound_for_realm(char *realm, char *recip)
29 * figures out if recip is in realm, expanding recip's realm
31 * int realm_sender_in_realm(char *realm, char *sender)
32 * figures out if sender is in realm
34 * Realm *realm_get_realm_by_name(char *name)
35 * finds a realm struct from the realm array by name, tries expansion
37 * Code_t realm_dispatch(ZNotice_t *notice, int auth, struct sockaddr_in *who,
39 * dispatches a message from a foreign realm
42 * sets up the realm module
44 * void realm_deathgram()
45 * tells other realms this server is going down
48 * tells other realms to resend their idea of their subs to us
50 * Code_t realm_control_dispatch(ZNotice_t *notice, int auth,
51 * struct sockaddr_in *who, Server *server,
53 * dispatches a foreign realm control message
55 * void realm_handoff(ZNotice_t *notice, int auth, struct sockaddr_in *who,
56 * Realm *realm, int ack_to_sender)
57 * hands off a message to another realm
59 * void realm_dump_realms(File *fp)
60 * do a database dump of foreign realm info
63 static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
64 static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
65 static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked));
66 static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who));
67 static void rlm_new_ticket __P(());
68 static void rlm_rexmit __P((void *arg));
69 static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm));
70 static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, Realm *));
71 static Code_t realm_set_server __P((struct sockaddr_in *, Realm *));
73 static Code_t ticket_retrieve __P((Realm *realm));
74 static int ticket_lookup __P((char *realm));
75 static int ticket_expired __P((CREDENTIALS *cred));
79 realm_get_idx_by_addr(realm, who)
81 struct sockaddr_in *who;
83 struct sockaddr_in *addr;
86 /* loop through the realms */
87 for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++)
88 if (addr->sin_addr.s_addr == who->sin_addr.s_addr)
95 realm_expand_realm(realmname)
101 /* First, look for an exact match (case insensitive) */
103 if (!strcasecmp(ZGetRealm(), realmname))
107 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
108 if (!strcasecmp(realm->name, realmname))
111 /* No exact match. See if there's a partial match */
113 if (!strncasecmp(ZGetRealm(), realmname, strlen(realmname)))
117 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
118 if (!strncasecmp(realm->name, realmname, strlen(realmname)))
124 realm_get_realm_by_pid(pid)
130 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
131 if (realm->child_pid == pid)
143 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
144 if (realm->child_pid != 0)
145 kill(realm->child_pid, 9);
151 get_realm_lists(file)
154 Realmname *rlm_list, *rlm;
155 int ii, nused, ntotal;
157 char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */
158 char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1];
161 if (!(fp = fopen(file, "r")))
162 return((Realmname *)0);
164 /* start with 16, realloc if necessary */
166 rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname));
168 syslog(LOG_CRIT, "get_realm_lists malloc");
172 while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) {
173 if (sscanf(buf, "%s %s", realm, server) != 2) {
174 syslog(LOG_CRIT, "bad format in %s", file);
177 for (ii = 0; ii < nused; ii++) {
178 /* look for this realm */
179 if (!strcmp(rlm_list[ii].name, realm))
184 if (rlm->nused +1 >= rlm->nservers) {
185 /* make more space */
186 rlm->servers = (char **)realloc((char *)rlm->servers,
187 (unsigned)rlm->nservers * 2 *
190 syslog(LOG_CRIT, "get_realm_lists realloc");
195 rlm->servers[rlm->nused++] = strsave(server);
198 if (nused + 1 >= ntotal) {
199 /* make more space */
200 rlm_list = (Realmname *)realloc((char *)rlm_list,
201 (unsigned)ntotal * 2 *
204 syslog(LOG_CRIT, "get_realm_lists realloc");
209 rlm = &rlm_list[nused++];
210 strcpy(rlm->name, realm);
213 rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *));
215 syslog(LOG_CRIT, "get_realm_lists malloc");
218 rlm->servers[rlm->nused++] = strsave(server);
221 if (nused + 1 >= ntotal) {
222 rlm_list = (Realmname *)realloc((char *)rlm_list,
223 (unsigned)(ntotal + 1) *
226 syslog(LOG_CRIT, "get_realm_lists realloc");
230 *rlm_list[nused].name = '\0';
239 for (cnt = 0; cnt < nrealms; cnt++) {
240 if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE)
246 realm_bound_for_realm(realm, recip)
251 int remote = strcmp(ZGetRealm(), realm);
254 rlm = strchr(recip, '@');
259 if (rlm && strcmp(realm_expand_realm(rlm + 1), realm) == 0)
266 realm_sender_in_realm(realm, sender)
271 int remote = strcmp(ZGetRealm(), realm);
274 rlm = strchr(sender, '@');
279 if (rlm && strcmp((rlm + 1), realm) == 0)
285 sender_in_realm(notice)
290 realm = strchr(notice->z_sender, '@');
292 if (!realm || !strcmp(realm + 1, ZGetRealm()))
299 realm_which_realm(who)
300 struct sockaddr_in *who;
303 struct sockaddr_in *addr;
306 if (who->sin_port != srv_addr.sin_port)
309 /* loop through the realms */
310 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
311 /* loop through the addresses for the realm */
312 for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++)
313 if (addr->sin_addr.s_addr == who->sin_addr.s_addr)
320 realm_get_realm_by_name(name)
326 /* First, look for an exact match (case insensitive) */
327 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
328 if (!strcasecmp(realm->name, name))
331 /* Failing that, look for an inexact match */
332 for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
333 if (!strncasecmp(realm->name, name, strlen(name)))
340 rlm_nack_cancel(notice, who)
341 register ZNotice_t *notice;
342 struct sockaddr_in *who;
344 register Realm *which = realm_which_realm(who);
345 register Unacked *nacked, *next;
349 zdbug((LOG_DEBUG, "rlm_nack_cancel: %s:%08X,%08X",
350 inet_ntoa(notice->z_uid.zuid_addr),
351 notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec));
354 syslog(LOG_ERR, "non-realm ack?");
358 for (nacked = rlm_nacklist; nacked; nacked = nacked->next) {
359 if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) {
360 /* First, note the realm appears to be up */
361 which->state = REALM_UP;
362 if (ZCompareUID(&nacked->uid, ¬ice->z_uid)) {
363 timer_reset(nacked->timer);
365 if (nacked->ack_addr.sin_addr.s_addr)
366 rlm_ack(notice, nacked);
369 free(nacked->packet);
377 zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X",
378 inet_ntoa (notice->z_uid.zuid_addr),
379 notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec));
385 rlm_ack(notice, nacked)
394 /* tell the original sender the result */
396 acknotice.z_message_len = strlen(acknotice.z_message) + 1;
398 packlen = sizeof(ackpack);
400 if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen))
402 syslog(LOG_ERR, "rlm_ack format: %s",
403 error_message(retval));
406 zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d",
407 inet_ntoa(nacked->ack_addr.sin_addr),
408 ntohs(nacked->ack_addr.sin_port)));
409 if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) {
410 syslog(LOG_WARNING, "rlm_ack set addr: %s",
411 error_message(retval));
414 if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) {
415 syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval));
421 realm_dispatch(notice, auth, who, server)
424 struct sockaddr_in *who;
428 struct sockaddr_in newwho;
429 Code_t status = ZERR_NONE;
430 char rlm_recipient[REALM_SZ + 1];
432 String *notice_class;
434 if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) {
435 rlm_nack_cancel(notice, who);
438 /* set up a who for the real origin */
439 memset((caddr_t) &newwho, 0, sizeof(newwho));
440 newwho.sin_family = AF_INET;
441 newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr;
442 newwho.sin_port = hm_port;
444 /* check if it's a control message */
445 realm = realm_which_realm(who);
447 notice_class = make_string(notice->z_class,1);
449 if (class_is_admin(notice_class)) {
450 syslog(LOG_WARNING, "%s sending admin opcode %s",
451 realm->name, notice->z_opcode);
452 } else if (class_is_hm(notice_class)) {
453 syslog(LOG_WARNING, "%s sending hm opcode %s",
454 realm->name, notice->z_opcode);
455 } else if (class_is_control(notice_class)) {
456 status = realm_control_dispatch(notice, auth, who,
458 } else if (class_is_ulogin(notice_class)) {
459 /* don't need to forward this */
460 if (server == me_server) {
461 sprintf(rlm_recipient, "@%s", realm->name);
462 notice->z_recipient = rlm_recipient;
464 sendit(notice, 1, who, 0);
466 } else if (class_is_ulocate(notice_class)) {
467 status = realm_ulocate_dispatch(notice, auth, who, server, realm);
469 /* redo the recipient */
470 if (*notice->z_recipient == '\0') {
471 sprintf(rlm_recipient, "@%s", realm->name);
472 notice->z_recipient = rlm_recipient;
474 } else if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)
475 && *notice->z_recipient == '@')
477 /* we're responsible for getting this message out */
479 notice->z_recipient = "";
482 /* otherwise, send to local subscribers */
483 sendit(notice, auth, who, external);
496 struct in_addr *addresses;
499 char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3];
501 sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE);
502 rlmnames = get_realm_lists(list_file);
504 zdbug((LOG_DEBUG, "No other realms"));
509 for (nrealms = 0; *rlmnames[nrealms].name; nrealms++);
511 otherrealms = (Realm *)malloc(nrealms * sizeof(Realm));
513 syslog(LOG_CRIT, "malloc failed in realm_init");
517 for (ii = 0; ii < nrealms; ii++) {
518 rlm = &otherrealms[ii];
519 strcpy(rlm->name, rlmnames[ii].name);
521 addresses = (struct in_addr *)malloc(rlmnames[ii].nused *
522 sizeof(struct in_addr));
524 syslog(LOG_CRIT, "malloc failed in realm_init");
527 /* convert names to addresses */
529 for (jj = 0; jj < rlmnames[ii].nused; jj++) {
530 hp = gethostbyname(rlmnames[ii].servers[jj]);
532 memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr,
533 sizeof(struct in_addr));
536 syslog(LOG_WARNING, "hostname failed, %s",
537 rlmnames[ii].servers[jj]);
538 /* free the hostname */
539 free(rlmnames[ii].servers[jj]);
542 rlm->addrs = (struct sockaddr_in *)malloc(found *
543 sizeof (struct sockaddr_in));
545 syslog(LOG_CRIT, "malloc failed in realm_init");
548 for (jj = 0; jj < rlm->count; jj++) {
549 rlm->addrs[jj].sin_family = AF_INET;
550 /* use the server port */
551 rlm->addrs[jj].sin_port = srv_addr.sin_port;
552 rlm->addrs[jj].sin_addr = addresses[jj];
554 client = (Client *) malloc(sizeof(Client));
556 syslog(LOG_CRIT, "malloc failed in realm_init");
559 memset(&client->addr, 0, sizeof(struct sockaddr_in));
561 memset(&client->session_key, 0, sizeof(client->session_key));
563 sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE,
565 client->principal = make_string(rlmprinc, 0);
566 client->last_send = 0;
567 client->last_ack = NOW;
570 client->addr.sin_family = 0;
571 client->addr.sin_port = 0;
572 client->addr.sin_addr.s_addr = 0;
574 rlm->client = client;
575 rlm->idx = (rlm->count) ? random() % rlm->count : 0;
579 /* Assume the best */
580 rlm->state = REALM_TARDY;
582 free(rlmnames[ii].servers);
589 realm_deathgram(server)
593 char rlm_recipient[REALM_SZ + 1];
596 /* Get it out once, and assume foreign servers will share */
597 for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) {
600 char rlm_recipient[REALM_SZ + 1];
603 memset (&snotice, 0, sizeof (snotice));
605 snotice.z_kind = ACKED;
606 snotice.z_port = srv_addr.sin_port;
607 snotice.z_class = ZEPHYR_CTL_CLASS;
608 snotice.z_class_inst = ZEPHYR_CTL_REALM;
609 snotice.z_opcode = SERVER_SHUTDOWN;
610 snotice.z_sender = myname; /* my host name */
611 sprintf(rlm_recipient, "@%s", realm->name);
612 snotice.z_recipient = rlm_recipient;
613 snotice.z_default_format = "";
614 snotice.z_num_other_fields = 0;
615 snotice.z_default_format = "";
616 snotice.z_message = (server) ? server->addr_str : NULL;
617 snotice.z_message_len = (server) ? strlen(server->addr_str) + 1 : 0;
619 zdbug((LOG_DEBUG, "rlm_deathgram: suggesting %s to %s",
620 (server) ? server->addr_str : "nothing", realm->name));
623 if (!ticket_lookup(realm->name))
624 if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
625 syslog(LOG_WARNING, "rlm_deathgram failed: %s",
626 error_message(retval));
631 if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH))
634 syslog(LOG_WARNING, "rlm_deathgram format: %s",
635 error_message(retval));
638 if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) {
639 syslog(LOG_WARNING, "rlm_deathgram parse: %s",
640 error_message(retval));
645 realm_handoff(&snotice, 1, NULL, realm, 0);
655 char rlm_recipient[REALM_SZ + 1];
657 for (jj = 1; jj < nservers; jj++) { /* skip limbo server */
658 if (jj != me_server_idx && otherservers[jj].state == SERV_UP)
662 if (nservers < 2 || !found) {
663 /* if we're the only server up, send a REALM_BOOT to one of their
665 for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) {
668 char rlm_recipient[REALM_SZ + 1];
671 memset (&snotice, 0, sizeof (snotice));
673 snotice.z_opcode = REALM_BOOT;
674 snotice.z_port = srv_addr.sin_port;
675 snotice.z_class_inst = ZEPHYR_CTL_REALM;
676 snotice.z_class = ZEPHYR_CTL_CLASS;
677 snotice.z_recipient = "";
678 snotice.z_kind = ACKED;
679 snotice.z_num_other_fields = 0;
680 snotice.z_default_format = "";
681 snotice.z_sender = myname; /* my host name */
682 sprintf(rlm_recipient, "@%s", realm->name);
683 snotice.z_recipient = rlm_recipient;
684 snotice.z_default_format = "";
685 snotice.z_message = NULL;
686 snotice.z_message_len = 0;
689 if (!ticket_lookup(realm->name))
690 if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
691 syslog(LOG_WARNING, "rlm_wakeup failed: %s",
692 error_message(retval));
697 if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH))
700 syslog(LOG_WARNING, "rlm_wakeup format: %s",
701 error_message(retval));
704 if ((retval = ZParseNotice(pack, packlen, &snotice))
706 syslog(LOG_WARNING, "rlm_wakeup parse: %s",
707 error_message(retval));
712 realm_handoff(&snotice, 1, NULL, realm, 0);
719 realm_ulocate_dispatch(notice, auth, who, server, realm)
722 struct sockaddr_in *who;
726 register char *opcode = notice->z_opcode;
730 syslog(LOG_WARNING, "unauth locate msg from %s (%s/%s/%s)",
731 inet_ntoa(who->sin_addr),
732 notice->z_class, notice->z_class_inst,
733 notice->z_opcode); /* XXX */
735 syslog(LOG_WARNING, "unauth locate msg from %s",
736 inet_ntoa(who->sin_addr));
738 clt_ack(notice, who, AUTH_FAILED);
742 if (!strcmp(opcode, REALM_REQ_LOCATE)) {
744 ulogin_realm_locate(notice, who, realm);
745 } else if (!strcmp(opcode, REALM_ANS_LOCATE)) {
747 ulogin_relay_locate(notice, who);
749 syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s",
750 realm->name, opcode);
759 realm_control_dispatch(notice, auth, who, server, realm)
762 struct sockaddr_in *who;
766 register char *opcode = notice->z_opcode;
770 syslog(LOG_WARNING, "unauth ctl msg from %s (%s/%s/%s)",
771 inet_ntoa(who->sin_addr),
772 notice->z_class, notice->z_class_inst,
773 notice->z_opcode); /* XXX */
775 syslog(LOG_WARNING, "unauth ctl msg from %s",
776 inet_ntoa(who->sin_addr));
778 if (server == me_server)
779 clt_ack(notice, who, AUTH_FAILED);
783 if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) {
784 syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s",
785 notice->z_class_inst);
789 if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) {
790 /* try to add subscriptions */
791 /* attempts to get defaults are ignored */
792 if ((status = subscr_foreign_user(notice, who, server, realm)) != ZERR_NONE) {
793 clt_ack(notice, who, AUTH_FAILED);
794 } else if (server == me_server) {
795 server_forward(notice, auth, who);
798 } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) {
799 /* try to remove subscriptions */
800 if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) {
801 clt_ack(notice, who, NOT_FOUND);
802 } else if (server == me_server) {
803 server_forward(notice, auth, who);
806 } else if (!strcmp(opcode, REALM_BOOT)) {
807 zdbug((LOG_DEBUG, "got a REALM_BOOT from %d (me %d)", server, me_server));
808 realm->state = REALM_STARTING;
809 realm_set_server(who, realm);
811 /* resend subscriptions but only if this was to us */
812 if (server == me_server) {
813 if ((status = subscr_realm_subs(realm)) != ZERR_NONE) {
814 clt_ack(notice, who, NOT_FOUND);
816 /* do forward the hint in case it ever matters */
817 server_forward(notice, auth, who);
822 } else if (!strcmp(opcode, SERVER_SHUTDOWN)) {
823 /* try to remove subscriptions */
824 if ((status = realm_new_server(who, notice, realm)) != ZERR_NONE) {
825 clt_ack(notice, who, NOT_FOUND);
826 } else if (server == me_server) {
827 server_forward(notice, auth, who);
831 syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s",
832 realm->name, opcode);
833 if (server == me_server)
841 realm_new_server(sin, notice, realm)
842 struct sockaddr_in *sin;
847 char suggested_server[MAXHOSTNAMELEN];
850 struct sockaddr_in sinaddr;
856 srvidx = realm_get_idx_by_addr(realm, sin);
857 zdbug((LOG_DEBUG, "rlm_new_srv: message from %d in %s (%s)",
858 srvidx, realm->name, inet_ntoa(sin->sin_addr)));
859 if (realm->idx == srvidx) {
860 if (notice->z_message_len) {
861 addr = inet_addr(notice->z_message);
862 sinaddr.sin_addr.s_addr = addr;
863 rlm = realm_which_realm(&sinaddr);
865 if (!rlm || (rlm != realm))
867 realm->idx = realm_get_idx_by_addr(realm, &sinaddr);
869 realm->idx = (realm->idx + 1) % realm->count;
871 zdbug((LOG_DEBUG, "rlm_new_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
873 zdbug((LOG_DEBUG, "rlm_new_srv: not switching servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
878 realm_set_server(sin, realm)
879 struct sockaddr_in *sin;
884 rlm = realm_which_realm(sin);
886 if (!rlm || (rlm != realm))
888 realm->idx = realm_get_idx_by_addr(realm, sin);
889 zdbug((LOG_DEBUG, "rlm_pick_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
893 realm_handoff(notice, auth, who, realm, ack_to_sender)
896 struct sockaddr_in *who;
904 zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s",
906 realm_sendit(notice, who, auth, realm, ack_to_sender);
910 if (!ticket_lookup(realm->name))
911 if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
912 syslog(LOG_WARNING, "rlm_handoff failed: %s",
913 error_message(retval));
914 realm_sendit(notice, who, auth, realm, ack_to_sender);
918 zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth));
919 /* valid ticket available now, send the message */
920 realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
921 #else /* HAVE_KRB4 */
922 realm_sendit(notice, who, auth, realm, ack_to_sender);
923 #endif /* HAVE_KRB4 */
927 realm_sendit(notice, who, auth, realm, ack_to_sender)
929 struct sockaddr_in *who;
939 notice->z_auth = auth;
941 /* format the notice */
942 if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) {
943 syslog(LOG_WARNING, "rlm_sendit format: %s",
944 error_message(retval));
949 if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) {
950 syslog(LOG_WARNING, "rlm_sendit set addr: %s",
951 error_message(retval));
955 if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) {
956 syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval));
961 /* now we've sent it, mark it as not ack'ed */
963 if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
964 /* no space: just punt */
965 syslog(LOG_ERR, "rlm_sendit nack malloc");
970 nacked->client = NULL;
972 nacked->packet = pack;
973 nacked->dest.rlm.rlm_idx = realm - otherrealms;
974 nacked->dest.rlm.rlm_srv_idx = realm->idx;
975 nacked->packsz = packlen;
976 nacked->uid = notice->z_uid;
978 nacked->ack_addr = *who;
980 nacked->ack_addr.sin_addr.s_addr = 0;
982 /* set a timer to retransmit */
983 nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
985 LIST_INSERT(&rlm_nacklist, nacked);
990 packet_ctl_nack(nackpacket)
995 /* extract the notice */
996 ZParseNotice(nackpacket->packet, nackpacket->packsz, ¬ice);
997 if (nackpacket->ack_addr.sin_addr.s_addr != 0)
998 nack(¬ice, &nackpacket->ack_addr);
1001 syslog(LOG_WARNING, "would have acked nobody (%s/%s/%s)",
1002 notice.z_class, notice.z_class_inst, notice.z_opcode); /* XXX */
1010 Unacked *nackpacket = (Unacked *) arg;
1012 register Realm *realm;
1015 zdbug((LOG_DEBUG,"rlm_rexmit"));
1017 realm = &otherrealms[nackpacket->dest.rlm.rlm_idx];
1019 zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s:%d (%d)",
1020 realm->name, realm->idx, nackpacket->rexmits));
1022 if (realm->count == 0)
1025 /* Check to see if we've retransmitted as many times as we can */
1026 if (nackpacket->rexmits >= (NUM_REXMIT_TIMES * realm->count)) {
1027 /* give a server ack that the packet is lost/realm dead */
1028 packet_ctl_nack(nackpacket);
1029 LIST_DELETE(nackpacket);
1031 zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name));
1032 realm->state = REALM_DEAD;
1034 free(nackpacket->packet);
1039 /* if we've reached our limit, move on to the next server */
1040 if ((realm->state == REALM_TARDY) ||
1041 (nackpacket->rexmits &&
1042 !((nackpacket->rexmits+1) % (NUM_REXMIT_TIMES/3))))
1044 realm->idx = (realm->idx + 1) % realm->count;
1045 zdbug((LOG_DEBUG, "rlm_rexmit: %s switching servers:%d (%s)",
1046 realm->name, realm->idx,
1047 inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
1050 /* throttle back if it looks like the realm is down */
1051 if ((realm->state != REALM_DEAD) ||
1052 ((nackpacket->rexmits % (realm->count+1)) == 1)) {
1053 /* do the retransmit */
1054 retval = ZSetDestAddr(&realm->addrs[realm->idx]);
1055 if (retval != ZERR_NONE) {
1056 syslog(LOG_WARNING, "rlm_rexmit set addr: %s",
1057 error_message(retval));
1059 retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0);
1060 if (retval != ZERR_NONE)
1061 syslog(LOG_WARNING, "rlm_rexmit xmit: %s",
1062 error_message(retval));
1064 /* no per-server nack queues for foreign realms yet, doesn't matter */
1065 nackpacket->dest.rlm.rlm_srv_idx = realm->idx;
1066 zdbug((LOG_DEBUG, "rlm_rexmit(%s): send to %s", realm->name,
1067 inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
1069 zdbug((LOG_DEBUG, "rlm_rexmit(%s): not sending to %s", realm->name,
1070 inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
1073 /* reset the timer */
1074 nackpacket->rexmits++;
1076 timer_set_rel(rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES],
1077 rlm_rexmit, nackpacket);
1078 if (rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES] == -1)
1079 zdbug((LOG_DEBUG, "rlm_rexmit(%s): would send at -1 to %s",
1080 realm->name, inet_ntoa((realm->addrs[realm->idx]).sin_addr)));
1086 realm_dump_realms(fp)
1089 register int ii, jj;
1091 for (ii = 0; ii < nrealms; ii++) {
1092 (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name);
1093 for (jj = 0; jj < otherrealms[ii].count; jj++) {
1094 (void) fprintf(fp, "\t%s\n",
1095 inet_ntoa(otherrealms[ii].addrs[jj].sin_addr));
1098 subscr_dump_subs(fp, otherrealms[ii].subs);
1104 realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
1107 struct sockaddr_in *who;
1113 int buffer_len, hdrlen, offset, fragsize, ret_len, message_len;
1114 int origoffset, origlen;
1117 char buf[1024], multi[64];
1120 ZNotice_t partnotice, newnotice;
1124 /* build an authent. first, make sure we have the ticket available */
1125 retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred);
1126 if (retval != GC_OK) {
1127 syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s",
1128 error_message(retval+krb_err_base));
1132 retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
1134 if (retval != MK_AP_OK) {
1135 syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s",
1136 error_message(retval+krb_err_base));
1140 retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length);
1141 if (retval != ZERR_NONE) {
1142 syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s",
1143 error_message(retval));
1147 /* set the dest addr */
1148 retval = ZSetDestAddr(&realm->addrs[realm->idx]);
1149 if (retval != ZERR_NONE) {
1150 syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s",
1151 error_message(retval));
1155 /* now format the notice, refragmenting if needed */
1156 newnotice = *notice;
1157 newnotice.z_auth = 1;
1158 newnotice.z_ascii_authent = buf;
1159 newnotice.z_authent_len = authent.length;
1161 buffer = (char *) malloc(sizeof(ZPacket_t));
1163 syslog(LOG_ERR, "realm_sendit_auth malloc");
1164 return; /* DON'T put on nack list */
1167 buffer_len = sizeof(ZPacket_t);
1169 retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr,
1171 if (retval != ZERR_NONE) {
1172 syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
1178 newnotice.z_checksum = 0;
1180 newnotice.z_checksum =
1181 (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0,
1185 retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen,
1187 if (retval != ZERR_NONE) {
1188 syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
1193 /* This is not terribly pretty, but it does do its job.
1194 * If a packet we get that needs to get sent off to another realm is
1195 * too big after we slap on our authent, we refragment it further,
1196 * a la Z_SendFragmentedNotice. This obviates the need for what
1197 * used to be done in ZFormatAuthenticRealmNotice, as we do it here.
1198 * At some point it should be pulled back out into its own function,
1199 * but only the server uses it.
1202 if ((newnotice.z_message_len+hdrlen > buffer_len) ||
1203 (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) {
1204 /* Deallocate buffer, use a local one */
1207 partnotice = *notice;
1209 partnotice.z_auth = 1;
1210 partnotice.z_ascii_authent = buf;
1211 partnotice.z_authent_len = authent.length;
1214 origlen = notice->z_message_len;
1216 if (notice->z_multinotice && strcmp(notice->z_multinotice, ""))
1217 if (sscanf(notice->z_multinotice, "%d/%d", &origoffset,
1219 syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed");
1224 zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset,
1225 notice->z_message_len, origlen));
1228 fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE;
1230 while (offset < notice->z_message_len || !notice->z_message_len) {
1231 (void) sprintf(multi, "%d/%d", offset+origoffset, origlen);
1232 partnotice.z_multinotice = multi;
1234 (void) Z_gettimeofday(&partnotice.z_uid.tv,
1235 (struct timezone *)0);
1236 partnotice.z_uid.tv.tv_sec = htonl((u_long)
1237 partnotice.z_uid.tv.tv_sec);
1238 partnotice.z_uid.tv.tv_usec =
1239 htonl((u_long) partnotice.z_uid.tv.tv_usec);
1240 (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr,
1243 message_len = min(notice->z_message_len-offset, fragsize);
1244 partnotice.z_message = notice->z_message+offset;
1245 partnotice.z_message_len = message_len;
1248 zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d",
1249 origoffset+offset, message_len, origlen));
1252 buffer = (char *) malloc(sizeof(ZPacket_t));
1254 syslog(LOG_ERR, "realm_sendit_auth malloc");
1255 return; /* DON'T put on nack list */
1258 retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len,
1259 &hdrlen, &ptr, NULL);
1260 if (retval != ZERR_NONE) {
1261 syslog(LOG_WARNING, "rlm_sendit_auth raw: %s",
1262 error_message(retval));
1268 partnotice.z_checksum = 0;
1270 partnotice.z_checksum =
1271 (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0,
1275 retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len,
1276 &hdrlen, NULL, NULL);
1277 if (retval != ZERR_NONE) {
1278 syslog(LOG_WARNING, "rlm_sendit_auth raw: %s",
1279 error_message(retval));
1284 ptr = buffer+hdrlen;
1286 (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len);
1288 buffer_len = hdrlen+partnotice.z_message_len;
1291 if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
1292 syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s",
1293 error_message(retval));
1298 if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
1299 /* no space: just punt */
1300 syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
1305 nacked->rexmits = 0;
1306 nacked->packet = buffer;
1307 nacked->dest.rlm.rlm_idx = realm - otherrealms;
1308 nacked->dest.rlm.rlm_srv_idx = realm->idx;
1309 nacked->packsz = buffer_len;
1310 nacked->uid = partnotice.z_uid;
1312 /* Do the ack for the last frag, below */
1314 nacked->ack_addr = *who;
1316 nacked->ack_addr.sin_addr.s_addr = 0;
1318 /* set a timer to retransmit */
1319 nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
1322 LIST_INSERT(&rlm_nacklist, nacked);
1326 if (!notice->z_message_len)
1330 zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent"));
1333 /* This is easy, no further fragmentation needed */
1334 ptr = buffer+hdrlen;
1336 (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
1338 buffer_len = hdrlen+newnotice.z_message_len;
1341 if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
1342 syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s",
1343 error_message(retval));
1349 zdbug((LOG_DEBUG, "rlm_sendit_auth message sent"));
1351 /* now we've sent it, mark it as not ack'ed */
1353 if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
1354 /* no space: just punt */
1355 syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
1360 nacked->rexmits = 0;
1361 nacked->packet = buffer;
1362 nacked->dest.rlm.rlm_idx = realm - otherrealms;
1363 nacked->dest.rlm.rlm_srv_idx = realm->idx;
1364 nacked->packsz = buffer_len;
1365 nacked->uid = notice->z_uid;
1367 /* Do the ack for the last frag, below */
1369 nacked->ack_addr = *who;
1371 nacked->ack_addr.sin_addr.s_addr = 0;
1373 /* set a timer to retransmit */
1374 nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked);
1376 LIST_INSERT(&rlm_nacklist, nacked);
1382 ticket_expired(cred)
1385 #ifdef HAVE_KRB_LIFE_TO_TIME
1386 return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW);
1387 #else /* HAVE_KRB_LIFE_TO_TIME */
1388 return (cred->issue_date + cred->lifetime*5*60 < NOW);
1389 #endif /* HAVE_KRB_LIFE_TO_TIME */
1393 ticket_lookup(realm)
1400 retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred);
1401 if (retval == GC_OK && !ticket_expired(&cred))
1409 ticket_retrieve(realm)
1412 int pid, retval = 0;
1417 if (realm->child_pid)
1418 /* Right idea. Basically, we haven't gotten it yet */
1419 return KRBET_KDC_AUTH_EXP;
1422 memset(&authent.dat,0,MAX_KTXT_LEN);
1425 if (realm->have_tkt) {
1426 retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
1428 if (retval == KSUCCESS) {
1432 syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child");
1437 syslog(LOG_ERR, "tkt_rtrv: can't fork");
1438 return KRBET_KDC_AUTH_EXP;
1440 else if (pid == 0) {
1441 #ifdef _POSIX_VERSION
1442 struct sigaction action;
1444 action.sa_flags = 0;
1445 sigemptyset(&action.sa_mask);
1446 action.sa_handler = 0;
1447 sigaction(SIGCHLD, &action, NULL);
1448 sigaction(SIGINT, &action, NULL);
1449 sigaction(SIGTERM, &action, NULL);
1450 sigaction(SIGUSR1, &action, NULL);
1451 sigaction(SIGUSR2, &action, NULL);
1452 sigaction(SIGFPE, &action, NULL);
1453 sigaction(SIGHUP, &action, NULL);
1455 sigaction(SIGEMT, &action, NULL);
1458 signal(SIGCHLD, SIG_DFL);
1459 signal(SIGINT, SIG_DFL);
1460 signal(SIGTERM, SIG_DFL);
1461 signal(SIGUSR1, SIG_DFL);
1462 signal(SIGUSR2, SIG_DFL);
1463 signal(SIGFPE, SIG_DFL);
1464 signal(SIGHUP, SIG_DFL);
1466 signal(SIGEMT, SIG_DFL);
1471 retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
1473 if (retval == KSUCCESS)
1476 /* Sleep a little while before retrying */
1480 realm->child_pid = pid;
1481 realm->have_tkt = 0;
1483 syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name,
1484 krb_err_txt[retval]);
1485 return (retval+krb_err_base);
1488 #endif /* HAVE_KRB4 */