From 36e4a4c6c86a75051f0602987810c68265fb79a4 Mon Sep 17 00:00:00 2001 From: Garry Zacheiss Date: Mon, 26 Feb 2001 23:51:07 +0000 Subject: Changes from CMU: * Replace entire file, resyncing interrealm code between us and CMU. --- server/realm.c | 1983 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 1190 insertions(+), 793 deletions(-) (limited to 'server/realm.c') diff --git a/server/realm.c b/server/realm.c index a77df82..37b0df9 100644 --- a/server/realm.c +++ b/server/realm.c @@ -7,7 +7,59 @@ Realm *otherrealms; /* points to an array of the known servers */ int nrealms = 0; /* number of other realms */ -static void get_realm_addrs __P(()); +/* + * External Routines: + * + * Realm *realm_which_realm(struct sockaddr_in *who) + * figures out if this packet came from another realm's server + * + * Realm *realm_get_realm_by_pid(int pid) + * figures out which realm a child handler was for + * + * void kill_realm_pids() + * kills all ticket getting childen + * + * char *realm_expand_realm(char *realmname) + * figures out what an abbreviated realm expands to + * + * Code_t realm_send_realms() + * loops through all realms for a brain dump + * + * int realm_bound_for_realm(char *realm, char *recip) + * figures out if recip is in realm, expanding recip's realm + * + * int realm_sender_in_realm(char *realm, char *sender) + * figures out if sender is in realm + * + * Realm *realm_get_realm_by_name(char *name) + * finds a realm struct from the realm array by name, tries expansion + * + * Code_t realm_dispatch(ZNotice_t *notice, int auth, struct sockaddr_in *who, + * Server *server) + * dispatches a message from a foreign realm + * + * void realm_init() + * sets up the realm module + * + * void realm_deathgram() + * tells other realms this server is going down + * + * void realm_wakeup() + * tells other realms to resend their idea of their subs to us + * + * Code_t realm_control_dispatch(ZNotice_t *notice, int auth, + * struct sockaddr_in *who, Server *server, + * Realm *realm) + * dispatches a foreign realm control message + * + * void realm_handoff(ZNotice_t *notice, int auth, struct sockaddr_in *who, + * Realm *realm, int ack_to_sender) + * hands off a message to another realm + * + * void realm_dump_realms(File *fp) + * do a database dump of foreign realm info + * + */ static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender)); static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked)); @@ -15,175 +67,221 @@ static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who)); static void rlm_new_ticket __P(()); static void rlm_rexmit __P((void *arg)); static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm)); +static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, Realm *)); +static Code_t realm_set_server __P((struct sockaddr_in *, Realm *)); #ifdef HAVE_KRB4 static Code_t ticket_retrieve __P((Realm *realm)); +static int ticket_lookup __P((char *realm)); +static int ticket_expired __P((CREDENTIALS *cred)); #endif +static int +realm_get_idx_by_addr(realm, who) + Realm *realm; + struct sockaddr_in *who; +{ + struct sockaddr_in *addr; + int a, b; + + /* loop through the realms */ + for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++) + if (addr->sin_addr.s_addr == who->sin_addr.s_addr) + return(b); + + return 0; +} + char * realm_expand_realm(realmname) char *realmname; { - static char expand[REALM_SZ]; - static char krb_realm[REALM_SZ+1]; - char *cp1, *cp2; - int retval; - FILE *rlm_file; - char list_file[128]; - char linebuf[BUFSIZ]; - char scratch[128]; - - /* upcase what we got */ - cp2 = realmname; - cp1 = expand; - while (*cp2) { - *cp1++ = toupper(*cp2++); - } - *cp1 = '\0'; + Realm *realm; + int a; - sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE); + /* First, look for an exact match (case insensitive) */ +#ifdef HAVE_KRB4 + if (!strcasecmp(ZGetRealm(), realmname)) + return(ZGetRealm()); +#endif - if ((rlm_file = fopen(list_file, "r")) == (FILE *) 0) { - return(expand); - } + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (!strcasecmp(realm->name, realmname)) + return(realm->name); - if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) { - /* error reading */ - (void) fclose(rlm_file); - return(expand); - } + /* No exact match. See if there's a partial match */ +#ifdef HAVE_KRB4 + if (!strncasecmp(ZGetRealm(), realmname, strlen(realmname))) + return(ZGetRealm()); +#endif - while (1) { - /* run through the file, looking for admin host */ - if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) { - (void) fclose(rlm_file); - return(expand); - } + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (!strncasecmp(realm->name, realmname, strlen(realmname))) + return(realm->name); + return(realmname); +} - if (sscanf(linebuf, "%s %s", krb_realm, scratch) < 2) - continue; - if (!strncmp(krb_realm, expand, strlen(expand))) { - (void) fclose(rlm_file); - return(krb_realm); - } - } -#ifdef KERBEROS - if (!strncmp(my_realm, expand, strlen(expand))) - return(my_realm); -#endif - return(expand); +Realm * +realm_get_realm_by_pid(pid) + int pid; +{ + Realm *realm; + int a; + + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (realm->child_pid == pid) + return(realm); + + return 0; +} + +void +kill_realm_pids() +{ + Realm *realm; + int a; + + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (realm->child_pid != 0) + kill(realm->child_pid, 9); + + return; } Realmname * get_realm_lists(file) char *file; { - Realmname *rlm_list, *rlm; - int ii, nused, ntotal; - FILE *fp; - char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */ - char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1]; + Realmname *rlm_list, *rlm; + int ii, nused, ntotal; + FILE *fp; + char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */ + char realm[REALM_SZ], server[MAXHOSTNAMELEN + 1]; - nused = 0; - if (!(fp = fopen(file, "r"))) - return((Realmname *)0); + nused = 0; + if (!(fp = fopen(file, "r"))) + return((Realmname *)0); - /* start with 16, realloc if necessary */ - ntotal = 16; - rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname)); - if (!rlm_list) { - syslog(LOG_CRIT, "get_realm_lists malloc"); - abort(); - } - - while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) { - if (sscanf(buf, "%s %s", realm, server) != 2) { - syslog(LOG_CRIT, "bad format in %s", file); - abort(); - } - for (ii = 0; ii < nused; ii++) { - /* look for this realm */ - if (!strcmp(rlm_list[ii].name, realm)) - break; + /* start with 16, realloc if necessary */ + ntotal = 16; + rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists malloc"); + abort(); } - if (ii < nused) { - rlm = &rlm_list[ii]; - if (rlm->nused +1 >= rlm->nservers) { - /* make more space */ - rlm->servers = (char **)realloc((char *)rlm->servers, - (unsigned)rlm->nservers * 2 * - sizeof(char *)); - if (!rlm->servers) { - syslog(LOG_CRIT, "get_realm_lists realloc"); - abort(); - } - rlm->nservers *= 2; - } - rlm->servers[rlm->nused++] = strsave(server); - } else { - /* new realm */ - if (nused + 1 >= ntotal) { - /* make more space */ - rlm_list = (Realmname *)realloc((char *)rlm_list, - (unsigned)ntotal * 2 * - sizeof(Realmname)); - if (!rlm_list) { - syslog(LOG_CRIT, "get_realm_lists realloc"); - abort(); - } - ntotal *= 2; - } - rlm = &rlm_list[nused++]; - strcpy(rlm->name, realm); - rlm->nused = 0; - rlm->nservers = 16; - rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *)); - if (!rlm->servers) { - syslog(LOG_CRIT, "get_realm_lists malloc"); - abort(); - } - rlm->servers[rlm->nused++] = strsave(server); + + while (fgets(buf, REALM_SZ + MAXHOSTNAMELEN + 1, fp)) { + if (sscanf(buf, "%s %s", realm, server) != 2) { + syslog(LOG_CRIT, "bad format in %s", file); + abort(); + } + for (ii = 0; ii < nused; ii++) { + /* look for this realm */ + if (!strcmp(rlm_list[ii].name, realm)) + break; + } + if (ii < nused) { + rlm = &rlm_list[ii]; + if (rlm->nused +1 >= rlm->nservers) { + /* make more space */ + rlm->servers = (char **)realloc((char *)rlm->servers, + (unsigned)rlm->nservers * 2 * + sizeof(char *)); + if (!rlm->servers) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } + rlm->nservers *= 2; + } + rlm->servers[rlm->nused++] = strsave(server); + } else { + /* new realm */ + if (nused + 1 >= ntotal) { + /* make more space */ + rlm_list = (Realmname *)realloc((char *)rlm_list, + (unsigned)ntotal * 2 * + sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } + ntotal *= 2; + } + rlm = &rlm_list[nused++]; + strcpy(rlm->name, realm); + rlm->nused = 0; + rlm->nservers = 16; + rlm->servers = (char **)malloc(rlm->nservers * sizeof(char *)); + if (!rlm->servers) { + syslog(LOG_CRIT, "get_realm_lists malloc"); + abort(); + } + rlm->servers[rlm->nused++] = strsave(server); + } } - } - if (nused + 1 >= ntotal) { - rlm_list = (Realmname *)realloc((char *)rlm_list, - (unsigned)(ntotal + 1) * - sizeof(Realmname)); - if (!rlm_list) { - syslog(LOG_CRIT, "get_realm_lists realloc"); - abort(); + if (nused + 1 >= ntotal) { + rlm_list = (Realmname *)realloc((char *)rlm_list, + (unsigned)(ntotal + 1) * + sizeof(Realmname)); + if (!rlm_list) { + syslog(LOG_CRIT, "get_realm_lists realloc"); + abort(); + } } - } - *rlm_list[nused].name = '\0'; + *rlm_list[nused].name = '\0'; - return(rlm_list); + return(rlm_list); } Code_t realm_send_realms() { - int cnt, retval; - for (cnt = 0; cnt < nrealms; cnt++) { - if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE) - return(retval); - } - return ZERR_NONE; + int cnt, retval; + for (cnt = 0; cnt < nrealms; cnt++) { + if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE) + return(retval); + } } int -bound_for_local_realm(notice) - ZNotice_t *notice; +realm_bound_for_realm(realm, recip) + char *realm; + char *recip; { - char *realm; - - realm = strchr(notice->z_recipient, '@'); - - if (!realm || !strcmp(realm_expand_realm(realm + 1), ZGetRealm())) - return 1; + char *rlm = NULL; + int remote = strcmp(ZGetRealm(), realm); + + if (recip) + rlm = strchr(recip, '@'); + + if (!rlm && !remote) + return 1; - return 0; + if (rlm && strcmp(realm_expand_realm(rlm + 1), realm) == 0) + return 1; + + return 0; } int +realm_sender_in_realm(realm, sender) + char *realm; + char *sender; +{ + char *rlm = NULL; + int remote = strcmp(ZGetRealm(), realm); + + if (sender) + rlm = strchr(sender, '@'); + + if (!rlm && !remote) + return 1; + + if (rlm && strcmp((rlm + 1), realm) == 0) + return 1; + + return 0; +} + sender_in_realm(notice) ZNotice_t *notice; { @@ -201,32 +299,41 @@ Realm * realm_which_realm(who) struct sockaddr_in *who; { - Realm *realm; - struct sockaddr_in *addr; - int a, b; - - /* loop through the realms */ - for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) - /* loop through the addresses for the realm */ - for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++) - if (addr->sin_addr.s_addr == who->sin_addr.s_addr) - return(realm); + Realm *realm; + struct sockaddr_in *addr; + int a, b; + + if (who->sin_port != srv_addr.sin_port) + return 0; + + /* loop through the realms */ + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + /* loop through the addresses for the realm */ + for (addr = realm->addrs, b = 0; b < realm->count; b++, addr++) + if (addr->sin_addr.s_addr == who->sin_addr.s_addr) + return(realm); - return 0; + return 0; } Realm * realm_get_realm_by_name(name) -char *name; + char *name; { - int a; - Realm *realm; + int a; + Realm *realm; - for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) - if (!strcmp(realm->name, name)) - return(realm); + /* First, look for an exact match (case insensitive) */ + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (!strcasecmp(realm->name, name)) + return(realm); - return 0; + /* Failing that, look for an inexact match */ + for (realm = otherrealms, a = 0; a < nrealms; a++, realm++) + if (!strncasecmp(realm->name, name, strlen(name))) + return(realm); + + return 0; } static void @@ -234,43 +341,44 @@ rlm_nack_cancel(notice, who) register ZNotice_t *notice; struct sockaddr_in *who; { - register Realm *which = realm_which_realm(who); - register Unacked *nacked, *next; - ZNotice_t acknotice; - ZPacket_t retval; + register Realm *which = realm_which_realm(who); + register Unacked *nacked, *next; + ZPacket_t retval; -#if 0 +#if 1 zdbug((LOG_DEBUG, "rlm_nack_cancel: %s:%08X,%08X", inet_ntoa(notice->z_uid.zuid_addr), notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); #endif - if (!which) { - syslog(LOG_ERR, "non-realm ack?"); - return; - } + if (!which) { + syslog(LOG_ERR, "non-realm ack?"); + return; + } - for (nacked = rlm_nacklist; nacked; nacked = nacked->next) { - if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) { - if (ZCompareUID(&nacked->uid, ¬ice->z_uid)) { - timer_reset(nacked->timer); + for (nacked = rlm_nacklist; nacked; nacked = nacked->next) { + if (&otherrealms[nacked->dest.rlm.rlm_idx] == which) { + /* First, note the realm appears to be up */ + which->state = REALM_UP; + if (ZCompareUID(&nacked->uid, ¬ice->z_uid)) { + timer_reset(nacked->timer); - if (nacked->ack_addr.sin_addr.s_addr) - rlm_ack(notice, nacked); + if (nacked->ack_addr.sin_addr.s_addr) + rlm_ack(notice, nacked); - /* free the data */ - free(nacked->packet); - LIST_DELETE(nacked); - free(nacked); - return; - } + /* free the data */ + free(nacked->packet); + LIST_DELETE(nacked); + free(nacked); + return; + } + } } - } #if 0 zdbug((LOG_DEBUG,"nack_cancel: nack not found %s:%08X,%08X", inet_ntoa (notice->z_uid.zuid_addr), notice->z_uid.tv.tv_sec, notice->z_uid.tv.tv_usec)); #endif - return; + return; } static void @@ -278,37 +386,37 @@ rlm_ack(notice, nacked) ZNotice_t *notice; Unacked *nacked; { - ZNotice_t acknotice; - ZPacket_t ackpack; - int packlen; - Code_t retval; + ZNotice_t acknotice; + ZPacket_t ackpack; + int packlen; + Code_t retval; - /* tell the original sender the result */ - acknotice = *notice; - acknotice.z_message_len = strlen(acknotice.z_message) + 1; + /* tell the original sender the result */ + acknotice = *notice; + acknotice.z_message_len = strlen(acknotice.z_message) + 1; - packlen = sizeof(ackpack); + packlen = sizeof(ackpack); - if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen)) != ZERR_NONE) { - syslog(LOG_ERR, "rlm_ack format: %s", - error_message(retval)); - return; - } - zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d", - inet_ntoa(nacked->ack_addr.sin_addr), - ntohs(nacked->ack_addr.sin_port))); - if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_ack set addr: %s", - error_message(retval)); - return; - } - if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval)); - return; - } + if ((retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen)) + != ZERR_NONE) { + syslog(LOG_ERR, "rlm_ack format: %s", + error_message(retval)); + return; + } + zdbug((LOG_DEBUG, "rlm_ack sending to %s/%d", + inet_ntoa(nacked->ack_addr.sin_addr), + ntohs(nacked->ack_addr.sin_port))); + if ((retval = ZSetDestAddr(&nacked->ack_addr)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_ack set addr: %s", + error_message(retval)); + return; + } + if ((retval = ZSendPacket(ackpack, packlen, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_ack xmit: %s", error_message(retval)); + return; + } } - Code_t realm_dispatch(notice, auth, who, server) ZNotice_t *notice; @@ -316,164 +424,291 @@ realm_dispatch(notice, auth, who, server) struct sockaddr_in *who; Server *server; { - Realm *realm; - struct sockaddr_in newwho; - Code_t status = ZERR_NONE; - char rlm_recipient[REALM_SZ + 1]; - int external = 0; - String *notice_class; - - if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) { - rlm_nack_cancel(notice, who); - return(ZERR_NONE); - } - /* set up a who for the real origin */ - memset((caddr_t) &newwho, 0, sizeof(newwho)); - newwho.sin_family = AF_INET; - newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; - newwho.sin_port = hm_port; - - /* check if it's a control message */ - realm = realm_which_realm(who); - - notice_class = make_string(notice->z_class,1); - - if (class_is_admin(notice_class)) { - syslog(LOG_WARNING, "%s sending admin opcode %s", - realm->name, notice->z_opcode); - } else if (class_is_hm(notice_class)) { - syslog(LOG_WARNING, "%s sending hm opcode %s", - realm->name, notice->z_opcode); - } else if (class_is_control(notice_class)) { - status = realm_control_dispatch(notice, auth, who, - server, realm); - } else if (class_is_ulogin(notice_class)) { - /* don't need to forward this */ - if (server == me_server) { + Realm *realm; + struct sockaddr_in newwho; + Code_t status = ZERR_NONE; + char rlm_recipient[REALM_SZ + 1]; + int external = 0; + String *notice_class; + + if (notice->z_kind == SERVACK || notice->z_kind == SERVNAK) { + rlm_nack_cancel(notice, who); + return(ZERR_NONE); + } + /* set up a who for the real origin */ + memset((caddr_t) &newwho, 0, sizeof(newwho)); + newwho.sin_family = AF_INET; + newwho.sin_addr.s_addr = notice->z_sender_addr.s_addr; + newwho.sin_port = hm_port; + + /* check if it's a control message */ + realm = realm_which_realm(who); + + notice_class = make_string(notice->z_class,1); + + if (class_is_admin(notice_class)) { + syslog(LOG_WARNING, "%s sending admin opcode %s", + realm->name, notice->z_opcode); + } else if (class_is_hm(notice_class)) { + syslog(LOG_WARNING, "%s sending hm opcode %s", + realm->name, notice->z_opcode); + } else if (class_is_control(notice_class)) { + status = realm_control_dispatch(notice, auth, who, + server, realm); + } else if (class_is_ulogin(notice_class)) { + /* don't need to forward this */ + if (server == me_server) { sprintf(rlm_recipient, "@%s", realm->name); notice->z_recipient = rlm_recipient; sendit(notice, 1, who, 0); - } - } else if (class_is_ulocate(notice_class)) { - status = realm_ulocate_dispatch(notice, auth, who, server, realm); - } else { - /* redo the recipient */ - if (*notice->z_recipient == '\0') { - sprintf(rlm_recipient, "@%s", realm->name); - notice->z_recipient = rlm_recipient; - /* only send to our realm */ - external = 0; - } else if (bound_for_local_realm(notice) && *notice->z_recipient - == '@') - { - /* we're responsible for getting this message out */ - external = 1; - notice->z_recipient = ""; - } + } + } else if (class_is_ulocate(notice_class)) { + status = realm_ulocate_dispatch(notice, auth, who, server, realm); + } else { + /* redo the recipient */ + if (*notice->z_recipient == '\0') { + sprintf(rlm_recipient, "@%s", realm->name); + notice->z_recipient = rlm_recipient; + external = 0; + } else if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient) + && *notice->z_recipient == '@') + { + /* we're responsible for getting this message out */ + external = 1; + notice->z_recipient = ""; + } - /* otherwise, send to local subscribers */ - sendit(notice, auth, who, external); - } + /* otherwise, send to local subscribers */ + sendit(notice, auth, who, external); + } - return(status); + return(status); } void realm_init() { - Client *client; - Realmname *rlmnames; - Realm *rlm; - int ii, jj, found; - struct in_addr *addresses; - struct hostent *hp; - char list_file[128]; - char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3]; - - sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE); - rlmnames = get_realm_lists(list_file); - if (!rlmnames) { - zdbug((LOG_DEBUG, "No other realms")); - nrealms = 0; - return; - } - - for (nrealms = 0; *rlmnames[nrealms].name; nrealms++); - - otherrealms = (Realm *)malloc(nrealms * sizeof(Realm)); - if (!otherrealms) { - syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); - abort(); - } - - for (ii = 0; ii < nrealms; ii++) { - rlm = &otherrealms[ii]; - strcpy(rlm->name, rlmnames[ii].name); - - addresses = (struct in_addr *)malloc(rlmnames[ii].nused * sizeof(struct in_addr)); - if (!addresses) { - syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); - abort(); + Client *client; + Realmname *rlmnames; + Realm *rlm; + int ii, jj, found; + struct in_addr *addresses; + struct hostent *hp; + char list_file[128]; + char rlmprinc[ANAME_SZ+INST_SZ+REALM_SZ+3]; + + sprintf(list_file, "%s/zephyr/%s", SYSCONFDIR, REALM_LIST_FILE); + rlmnames = get_realm_lists(list_file); + if (!rlmnames) { + zdbug((LOG_DEBUG, "No other realms")); + nrealms = 0; + return; } - /* convert names to addresses */ - found = 0; - for (jj = 0; jj < rlmnames[ii].nused; jj++) { - hp = gethostbyname(rlmnames[ii].servers[jj]); - if (hp) { - memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr, sizeof(struct in_addr)); - found++; - } else - syslog(LOG_WARNING, "hostname failed, %s", rlmnames[ii].servers[jj]); - /* free the hostname */ - free(rlmnames[ii].servers[jj]); + + for (nrealms = 0; *rlmnames[nrealms].name; nrealms++); + + otherrealms = (Realm *)malloc(nrealms * sizeof(Realm)); + if (!otherrealms) { + syslog(LOG_CRIT, "malloc failed in realm_init"); + abort(); } - /* If we found no servers, die here so we don't divide by zero later */ - if (found != 0) - rlm->count = found; - else { - syslog(LOG_CRIT, "Found no servers for realm %s", rlm->name); - abort(); + + for (ii = 0; ii < nrealms; ii++) { + rlm = &otherrealms[ii]; + strcpy(rlm->name, rlmnames[ii].name); + + addresses = (struct in_addr *)malloc(rlmnames[ii].nused * + sizeof(struct in_addr)); + if (!addresses) { + syslog(LOG_CRIT, "malloc failed in realm_init"); + abort(); + } + /* convert names to addresses */ + found = 0; + for (jj = 0; jj < rlmnames[ii].nused; jj++) { + hp = gethostbyname(rlmnames[ii].servers[jj]); + if (hp) { + memmove((caddr_t) &addresses[found], (caddr_t)hp->h_addr, + sizeof(struct in_addr)); + found++; + } else + syslog(LOG_WARNING, "hostname failed, %s", + rlmnames[ii].servers[jj]); + /* free the hostname */ + free(rlmnames[ii].servers[jj]); + } + rlm->count = found; + rlm->addrs = (struct sockaddr_in *)malloc(found * + sizeof (struct sockaddr_in)); + if (!rlm->addrs) { + syslog(LOG_CRIT, "malloc failed in realm_init"); + abort(); + } + for (jj = 0; jj < rlm->count; jj++) { + rlm->addrs[jj].sin_family = AF_INET; + /* use the server port */ + rlm->addrs[jj].sin_port = srv_addr.sin_port; + rlm->addrs[jj].sin_addr = addresses[jj]; + } + client = (Client *) malloc(sizeof(Client)); + if (!client) { + syslog(LOG_CRIT, "malloc failed in realm_init"); + abort(); + } + memset(&client->addr, 0, sizeof(struct sockaddr_in)); +#ifdef HAVE_KRB4 + memset(&client->session_key, 0, sizeof(client->session_key)); +#endif + sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, + rlm->name); + client->principal = make_string(rlmprinc, 0); + client->last_send = 0; + client->last_ack = NOW; + client->subs = NULL; + client->realm = rlm; + client->addr.sin_family = 0; + client->addr.sin_port = 0; + client->addr.sin_addr.s_addr = 0; + + rlm->client = client; + rlm->idx = (rlm->count) ? random() % rlm->count : 0; + rlm->subs = NULL; + rlm->remsubs = NULL; + rlm->child_pid = 0; + /* Assume the best */ + rlm->state = REALM_TARDY; + rlm->have_tkt = 1; + free(rlmnames[ii].servers); + free(addresses); } + free(rlmnames); +} - rlm->addrs = (struct sockaddr_in *)malloc(found * sizeof (struct sockaddr_in)); - if (!rlm->addrs) { - syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); - abort(); +void +realm_deathgram(server) + Server *server; +{ + Realm *realm; + char rlm_recipient[REALM_SZ + 1]; + int jj = 0; + + /* Get it out once, and assume foreign servers will share */ + for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) { + ZNotice_t snotice; + char *pack; + char rlm_recipient[REALM_SZ + 1]; + int packlen, retval; + + memset (&snotice, 0, sizeof (snotice)); + + snotice.z_kind = ACKED; + snotice.z_port = srv_addr.sin_port; + snotice.z_class = ZEPHYR_CTL_CLASS; + snotice.z_class_inst = ZEPHYR_CTL_REALM; + snotice.z_opcode = SERVER_SHUTDOWN; + snotice.z_sender = myname; /* my host name */ + sprintf(rlm_recipient, "@%s", realm->name); + snotice.z_recipient = rlm_recipient; + snotice.z_default_format = ""; + snotice.z_num_other_fields = 0; + snotice.z_default_format = ""; + snotice.z_message = (server) ? server->addr_str : NULL; + snotice.z_message_len = (server) ? strlen(server->addr_str) + 1 : 0; + + zdbug((LOG_DEBUG, "rlm_deathgram: suggesting %s to %s", + (server) ? server->addr_str : "nothing", realm->name)); + + if (!ticket_lookup(realm->name)) + if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_deathgram failed: %s", + error_message(retval)); + return; + } + + if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) + != ZERR_NONE) + { + syslog(LOG_WARNING, "rlm_deathgram format: %s", + error_message(retval)); + return; + } + if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_deathgram parse: %s", + error_message(retval)); + free(pack); + return; + } + + realm_handoff(&snotice, 1, NULL, realm, 0); + free(pack); } - for (jj = 0; jj < rlm->count; jj++) { - rlm->addrs[jj].sin_family = AF_INET; - /* use the server port */ - rlm->addrs[jj].sin_port = srv_addr.sin_port; - rlm->addrs[jj].sin_addr = addresses[jj]; +} + +void +realm_wakeup() +{ + int jj, found = 0; + Realm *realm; + char rlm_recipient[REALM_SZ + 1]; + + for (jj = 1; jj < nservers; jj++) { /* skip limbo server */ + if (jj != me_server_idx && otherservers[jj].state == SERV_UP) + found++; } - client = (Client *) malloc(sizeof(Client)); - if (!client) { - syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); - abort(); + + if (nservers < 2 || !found) { + /* if we're the only server up, send a REALM_BOOT to one of their + servers here */ + for (realm = otherrealms, jj = 0; jj < nrealms; jj++, realm++) { + ZNotice_t snotice; + char *pack; + char rlm_recipient[REALM_SZ + 1]; + int packlen, retval; + + memset (&snotice, 0, sizeof (snotice)); + + snotice.z_opcode = REALM_BOOT; + snotice.z_port = srv_addr.sin_port; + snotice.z_class_inst = ZEPHYR_CTL_REALM; + snotice.z_class = ZEPHYR_CTL_CLASS; + snotice.z_recipient = ""; + snotice.z_kind = ACKED; + snotice.z_num_other_fields = 0; + snotice.z_default_format = ""; + snotice.z_sender = myname; /* my host name */ + sprintf(rlm_recipient, "@%s", realm->name); + snotice.z_recipient = rlm_recipient; + snotice.z_default_format = ""; + snotice.z_message = NULL; + snotice.z_message_len = 0; + + if (!ticket_lookup(realm->name)) + if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_wakeup failed: %s", + error_message(retval)); + continue; + } + + if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) + != ZERR_NONE) + { + syslog(LOG_WARNING, "rlm_wakeup format: %s", + error_message(retval)); + return; + } + if ((retval = ZParseNotice(pack, packlen, &snotice)) + != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_wakeup parse: %s", + error_message(retval)); + free(pack); + return; + } + + realm_handoff(&snotice, 1, NULL, realm, 0); + free(pack); + } } - memset(&client->addr, 0, sizeof(struct sockaddr_in)); -#ifdef HAVE_KRB4 - memset(&client->session_key, 0, sizeof(client->session_key)); -#endif - sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, rlm->name); - client->principal = make_string(rlmprinc, 0); - client->last_send = 0; - client->last_ack = NOW; - client->subs = NULL; - client->realm = rlm; - client->addr.sin_family = 0; - client->addr.sin_port = 0; - client->addr.sin_addr.s_addr = 0; - - rlm->client = client; - rlm->idx = random() % rlm->count; - rlm->subs = NULL; - rlm->tkt_try = 0; - free(rlmnames[ii].servers); - free(addresses); - } - free(rlmnames); } static Code_t @@ -484,29 +719,35 @@ realm_ulocate_dispatch(notice, auth, who, server, realm) Server *server; Realm *realm; { - register char *opcode = notice->z_opcode; - Code_t status; + register char *opcode = notice->z_opcode; + Code_t status; - if (!auth) { - syslog(LOG_WARNING, "unauth locate msg from %s", - inet_ntoa(who->sin_addr)); - clt_ack(notice, who, AUTH_FAILED); + if (!auth) { + syslog(LOG_WARNING, "unauth locate msg from %s (%s/%s/%s)", + inet_ntoa(who->sin_addr), + notice->z_class, notice->z_class_inst, + notice->z_opcode); /* XXX */ +#if 0 + syslog(LOG_WARNING, "unauth locate msg from %s", + inet_ntoa(who->sin_addr)); +#endif + clt_ack(notice, who, AUTH_FAILED); + return(ZERR_NONE); + } + + if (!strcmp(opcode, REALM_REQ_LOCATE)) { + ack(notice, who); + ulogin_realm_locate(notice, who, realm); + } else if (!strcmp(opcode, REALM_ANS_LOCATE)) { + ack(notice, who); + ulogin_relay_locate(notice, who); + } else { + syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s", + realm->name, opcode); + nack(notice, who); + } + return(ZERR_NONE); - } - - if (!strcmp(opcode, REALM_REQ_LOCATE)) { - ack(notice, who); - ulogin_realm_locate(notice, who, realm); - } else if (!strcmp(opcode, REALM_ANS_LOCATE)) { - ack(notice, who); - ulogin_relay_locate(notice, who); - } else { - syslog(LOG_WARNING, "%s unknown/illegal loc opcode %s", - realm->name, opcode); - nack(notice, who); - } - - return(ZERR_NONE); } @@ -518,48 +759,130 @@ realm_control_dispatch(notice, auth, who, server, realm) Server *server; Realm *realm; { - register char *opcode = notice->z_opcode; - Code_t status; - - if (!auth) { - syslog(LOG_WARNING, "unauth ctl msg from %s", - inet_ntoa(who->sin_addr)); - if (server == me_server) - clt_ack(notice, who, AUTH_FAILED); - return(ZERR_NONE); - } + register char *opcode = notice->z_opcode; + Code_t status; + + if (!auth) { + syslog(LOG_WARNING, "unauth ctl msg from %s (%s/%s/%s)", + inet_ntoa(who->sin_addr), + notice->z_class, notice->z_class_inst, + notice->z_opcode); /* XXX */ +#if 0 + syslog(LOG_WARNING, "unauth ctl msg from %s", + inet_ntoa(who->sin_addr)); +#endif + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return(ZERR_NONE); + } - if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) { - syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s", - notice->z_class_inst); - return(ZERR_NONE); - } - - if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) { - /* try to add subscriptions */ - /* attempts to get defaults are ignored */ - if ((status = subscr_foreign_user(notice, who, realm)) != ZERR_NONE) { - clt_ack(notice, who, AUTH_FAILED); - } else if (server == me_server) { - server_forward(notice, auth, who); - ack(notice, who); + if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM)) { + syslog(LOG_WARNING, "Invalid rlm_dispatch instance %s", + notice->z_class_inst); + return(ZERR_NONE); } - } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) { - /* try to remove subscriptions */ - if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) { - clt_ack(notice, who, NOT_FOUND); - } else if (server == me_server) { - server_forward(notice, auth, who); - ack(notice, who); + + if (!strcmp(opcode, REALM_REQ_SUBSCRIBE) || !strcmp(opcode, REALM_ADD_SUBSCRIBE)) { + /* try to add subscriptions */ + /* attempts to get defaults are ignored */ + if ((status = subscr_foreign_user(notice, who, server, realm)) != ZERR_NONE) { + clt_ack(notice, who, AUTH_FAILED); + } else if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + } else if (!strcmp(opcode, REALM_UNSUBSCRIBE)) { + /* try to remove subscriptions */ + if ((status = subscr_realm_cancel(who, notice, realm)) != ZERR_NONE) { + clt_ack(notice, who, NOT_FOUND); + } else if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + } else if (!strcmp(opcode, REALM_BOOT)) { + zdbug((LOG_DEBUG, "got a REALM_BOOT from %d (me %d)", server, me_server)); + realm->state = REALM_STARTING; + realm_set_server(who, realm); +#ifdef REALM_MGMT + /* resend subscriptions but only if this was to us */ + if (server == me_server) { + if ((status = subscr_realm_subs(realm)) != ZERR_NONE) { + clt_ack(notice, who, NOT_FOUND); + } else { + /* do forward the hint in case it ever matters */ + server_forward(notice, auth, who); + ack(notice, who); + } + } +#endif + } else if (!strcmp(opcode, SERVER_SHUTDOWN)) { + /* try to remove subscriptions */ + if ((status = realm_new_server(who, notice, realm)) != ZERR_NONE) { + clt_ack(notice, who, NOT_FOUND); + } else if (server == me_server) { + server_forward(notice, auth, who); + ack(notice, who); + } + } else { + syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s", + realm->name, opcode); + if (server == me_server) + nack(notice, who); + return(ZERR_NONE); } - } else { - syslog(LOG_WARNING, "%s unknown/illegal ctl opcode %s", - realm->name, opcode); - if (server == me_server) - nack(notice, who); return(ZERR_NONE); - } - return(ZERR_NONE); +} + +static Code_t +realm_new_server(sin, notice, realm) + struct sockaddr_in *sin; + ZNotice_t *notice; + Realm *realm; +{ + struct hostent *hp; + char suggested_server[MAXHOSTNAMELEN]; + unsigned long addr; + Realm *rlm; + struct sockaddr_in sinaddr; + int srvidx; + + if (!realm) + return ZSRV_NORLM; + + srvidx = realm_get_idx_by_addr(realm, sin); + zdbug((LOG_DEBUG, "rlm_new_srv: message from %d in %s (%s)", + srvidx, realm->name, inet_ntoa(sin->sin_addr))); + if (realm->idx == srvidx) { + if (notice->z_message_len) { + addr = inet_addr(notice->z_message); + sinaddr.sin_addr.s_addr = addr; + rlm = realm_which_realm(&sinaddr); + /* Not exactly */ + if (!rlm || (rlm != realm)) + return ZSRV_NORLM; + realm->idx = realm_get_idx_by_addr(realm, &sinaddr); + } else { + realm->idx = (realm->idx + 1) % realm->count; + } + zdbug((LOG_DEBUG, "rlm_new_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + } else { + zdbug((LOG_DEBUG, "rlm_new_srv: not switching servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + } +} + +static Code_t +realm_set_server(sin, realm) + struct sockaddr_in *sin; + Realm *realm; +{ + Realm *rlm; + + rlm = realm_which_realm(sin); + /* Not exactly */ + if (!rlm || (rlm != realm)) + return ZSRV_NORLM; + realm->idx = realm_get_idx_by_addr(realm, sin); + zdbug((LOG_DEBUG, "rlm_pick_srv: switched servers (%s)", inet_ntoa((realm->addrs[realm->idx]).sin_addr))); } void @@ -571,24 +894,28 @@ realm_handoff(notice, auth, who, realm, ack_to_sender) int ack_to_sender; { #ifdef HAVE_KRB4 - Code_t retval; + Code_t retval; - if (!auth) { - zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s", realm->name)) - realm_sendit(notice, who, auth, realm, ack_to_sender); - } - - if (!ticket_lookup(realm->name)) - if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_handoff failed: %s", error_message(retval)); - return; + if (!auth) { + zdbug((LOG_DEBUG, "realm_sendit unauthentic to realm %s", + realm->name)); + realm_sendit(notice, who, auth, realm, ack_to_sender); + return; } - zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); - /* valid ticket available now, send the message */ - realm_sendit_auth(notice, who, auth, realm, ack_to_sender); + if (!ticket_lookup(realm->name)) + if ((retval = ticket_retrieve(realm)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_handoff failed: %s", + error_message(retval)); + realm_sendit(notice, who, auth, realm, ack_to_sender); + return; + } + + zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); + /* valid ticket available now, send the message */ + realm_sendit_auth(notice, who, auth, realm, ack_to_sender); #else /* HAVE_KRB4 */ - realm_sendit(notice, who, auth, realm, ack_to_sender); + realm_sendit(notice, who, auth, realm, ack_to_sender); #endif /* HAVE_KRB4 */ } @@ -600,142 +927,174 @@ realm_sendit(notice, who, auth, realm, ack_to_sender) Realm *realm; int ack_to_sender; { - caddr_t pack; - int packlen; - Code_t retval; - Unacked *nacked; + caddr_t pack; + int packlen; + Code_t retval; + Unacked *nacked; - notice->z_auth = auth; + notice->z_auth = auth; - /* format the notice */ - if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit format: %s", - error_message(retval)); - return; - } + /* format the notice */ + if ((retval = ZFormatRawNotice(notice, &pack, &packlen)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit format: %s", + error_message(retval)); + return; + } - /* now send */ - if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit set addr: %s", - error_message(retval)); - free(pack); - return; - } - if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval)); - free(pack); - return; - } - - /* now we've sent it, mark it as not ack'ed */ + /* now send */ + if ((retval = ZSetDestAddr(&realm->addrs[realm->idx])) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit set addr: %s", + error_message(retval)); + free(pack); + return; + } + if ((retval = ZSendPacket(pack, packlen, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit xmit: %s", error_message(retval)); + free(pack); + return; + } + + /* now we've sent it, mark it as not ack'ed */ - if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { - /* no space: just punt */ - syslog(LOG_ERR, "rlm_sendit nack malloc"); - free(pack); + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit nack malloc"); + free(pack); + return; + } + + nacked->client = NULL; + nacked->rexmits = 0; + nacked->packet = pack; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = packlen; + nacked->uid = notice->z_uid; + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; + + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); return; - } - - nacked->client = NULL; - nacked->rexmits = 0; - nacked->packet = pack; - nacked->dest.rlm.rlm_idx = realm - otherrealms; - nacked->dest.rlm.rlm_srv_idx = realm->idx; - nacked->packsz = packlen; - nacked->uid = notice->z_uid; - if (ack_to_sender) - nacked->ack_addr = *who; - else - nacked->ack_addr.sin_addr.s_addr = 0; - - /* set a timer to retransmit */ - nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); - /* chain in */ - LIST_INSERT(&rlm_nacklist, nacked); - return; } static void packet_ctl_nack(nackpacket) Unacked *nackpacket; { - ZNotice_t notice; + ZNotice_t notice; - /* extract the notice */ - ZParseNotice(nackpacket->packet, nackpacket->packsz, ¬ice); - nack(¬ice, &nackpacket->ack_addr); + /* extract the notice */ + ZParseNotice(nackpacket->packet, nackpacket->packsz, ¬ice); + if (nackpacket->ack_addr.sin_addr.s_addr != 0) + nack(¬ice, &nackpacket->ack_addr); +#if 1 + else + syslog(LOG_WARNING, "would have acked nobody (%s/%s/%s)", + notice.z_class, notice.z_class_inst, notice.z_opcode); /* XXX */ +#endif } static void rlm_rexmit(arg) void *arg; { - Unacked *nackpacket = (Unacked *) arg; - Code_t retval; - register Realm *realm; - int new_srv_idx; + Unacked *nackpacket = (Unacked *) arg; + Code_t retval; + register Realm *realm; + int new_srv_idx; - zdbug((LOG_DEBUG,"rlm_rexmit")); + zdbug((LOG_DEBUG,"rlm_rexmit")); - realm = &otherrealms[nackpacket->dest.rlm.rlm_idx]; + realm = &otherrealms[nackpacket->dest.rlm.rlm_idx]; - zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s", realm->name)); + zdbug((LOG_DEBUG, "rlm_rexmit: sending to %s:%d (%d)", + realm->name, realm->idx, nackpacket->rexmits)); - if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] == -1) { - /* give a server ack that the packet is lost/realm dead */ - packet_ctl_nack(nackpacket); - LIST_DELETE(nackpacket); - free(nackpacket->packet); - free(nackpacket); + if (realm->count == 0) + return; - zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name)); - return; - } + /* Check to see if we've retransmitted as many times as we can */ + if (nackpacket->rexmits >= (NUM_REXMIT_TIMES * realm->count)) { + /* give a server ack that the packet is lost/realm dead */ + packet_ctl_nack(nackpacket); + LIST_DELETE(nackpacket); + + zdbug((LOG_DEBUG, "rlm_rexmit: %s appears dead", realm->name)); + realm->state = REALM_DEAD; - /* retransmit the packet, trying each server in the realm multiple times */ -#if 0 - new_srv_idx = ((nackpacket->rexmits / NUM_REXMIT_TIMES) - + nackpacket->rlm.rlm_srv_idx) % realm->count; -#else - new_srv_idx = nackpacket->rexmits % realm->count; -#endif - if (new_srv_idx != realm->idx) - realm->idx = new_srv_idx; - - retval = ZSetDestAddr(&realm->addrs[realm->idx]); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_rexmit set addr: %s", error_message(retval)); - } else { - retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0); - if (retval != ZERR_NONE) - syslog(LOG_WARNING, "rlm_rexmit xmit: %s", error_message(retval)); - } - /* reset the timer */ - if (rexmit_times[(nackpacket->rexmits + 1)/(realm->count)] != -1) + free(nackpacket->packet); + free(nackpacket); + return; + } + + /* if we've reached our limit, move on to the next server */ + if ((realm->state == REALM_TARDY) || + (nackpacket->rexmits && + !((nackpacket->rexmits+1) % (NUM_REXMIT_TIMES/3)))) + { + realm->idx = (realm->idx + 1) % realm->count; + zdbug((LOG_DEBUG, "rlm_rexmit: %s switching servers:%d (%s)", + realm->name, realm->idx, + inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + } + + /* throttle back if it looks like the realm is down */ + if ((realm->state != REALM_DEAD) || + ((nackpacket->rexmits % (realm->count+1)) == 1)) { + /* do the retransmit */ + retval = ZSetDestAddr(&realm->addrs[realm->idx]); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_rexmit set addr: %s", + error_message(retval)); + } else { + retval = ZSendPacket(nackpacket->packet, nackpacket->packsz, 0); + if (retval != ZERR_NONE) + syslog(LOG_WARNING, "rlm_rexmit xmit: %s", + error_message(retval)); + } + /* no per-server nack queues for foreign realms yet, doesn't matter */ + nackpacket->dest.rlm.rlm_srv_idx = realm->idx; + zdbug((LOG_DEBUG, "rlm_rexmit(%s): send to %s", realm->name, + inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + } else { + zdbug((LOG_DEBUG, "rlm_rexmit(%s): not sending to %s", realm->name, + inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + } + + /* reset the timer */ nackpacket->rexmits++; - - nackpacket->timer = timer_set_rel(rexmit_times[(nackpacket->rexmits)/(realm->count)], rlm_rexmit, nackpacket); - return; + nackpacket->timer = + timer_set_rel(rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES], + rlm_rexmit, nackpacket); + if (rexmit_times[nackpacket->rexmits%NUM_REXMIT_TIMES] == -1) + zdbug((LOG_DEBUG, "rlm_rexmit(%s): would send at -1 to %s", + realm->name, inet_ntoa((realm->addrs[realm->idx]).sin_addr))); + + return; } void realm_dump_realms(fp) FILE *fp; { - register int ii, jj; + register int ii, jj; - for (ii = 0; ii < nrealms; ii++) { - (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name); - for (jj = 0; jj < otherrealms[ii].count; jj++) { - (void) fprintf(fp, "\t%s\n", - inet_ntoa(otherrealms[ii].addrs[jj].sin_addr)); + for (ii = 0; ii < nrealms; ii++) { + (void) fprintf(fp, "%d:%s\n", ii, otherrealms[ii].name); + for (jj = 0; jj < otherrealms[ii].count; jj++) { + (void) fprintf(fp, "\t%s\n", + inet_ntoa(otherrealms[ii].addrs[jj].sin_addr)); + } + /* dump the subs */ + subscr_dump_subs(fp, otherrealms[ii].subs); } - /* dump the subs */ - subscr_dump_subs(fp, otherrealms[ii].subs); - } } - #ifdef HAVE_KRB4 static void realm_sendit_auth(notice, who, auth, realm, ack_to_sender) @@ -745,344 +1104,382 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender) Realm *realm; int ack_to_sender; { - char *buffer, *ptr; - caddr_t pack; - int buffer_len, hdrlen, offset, fragsize, ret_len, message_len; - int origoffset, origlen; - Code_t retval; - Unacked *nacked; - char buf[1024], multi[64]; - CREDENTIALS cred; - KTEXT_ST authent; - ZNotice_t partnotice, newnotice; - - offset = 0; - - /* first, build an authent */ - retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred); - if (retval != GC_OK) { - syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s", - error_message(retval+krb_err_base)); - return; - } + char *buffer, *ptr; + caddr_t pack; + int buffer_len, hdrlen, offset, fragsize, ret_len, message_len; + int origoffset, origlen; + Code_t retval; + Unacked *nacked; + char buf[1024], multi[64]; + CREDENTIALS cred; + KTEXT_ST authent; + ZNotice_t partnotice, newnotice; + + offset = 0; + + /* build an authent. first, make sure we have the ticket available */ + retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred); + if (retval != GC_OK) { + syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s", + error_message(retval+krb_err_base)); + return; + } - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm->name, 1); - if (retval != MK_AP_OK) { - syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s", - error_message(retval+krb_err_base)); - return; - } + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + realm->name, 1); + if (retval != MK_AP_OK) { + syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s", + error_message(retval+krb_err_base)); + return; + } - retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s", - error_message(retval)); - return; - } + retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s", + error_message(retval)); + return; + } - /* set the dest addr */ - retval = ZSetDestAddr(&realm->addrs[realm->idx]); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", error_message(retval)); - return; - } - - /* now format the notice, refragmenting if needed */ - newnotice = *notice; - newnotice.z_auth = 1; - newnotice.z_ascii_authent = buf; - newnotice.z_authent_len = authent.length; - - buffer = (char *) malloc(sizeof(ZPacket_t)); - if (!buffer) { - syslog(LOG_ERR, "realm_sendit_auth malloc"); - return; /* DON'T put on nack list */ - } - - buffer_len = sizeof(ZPacket_t); - - retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, - NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; - } + /* set the dest addr */ + retval = ZSetDestAddr(&realm->addrs[realm->idx]); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", + error_message(retval)); + return; + } + + /* now format the notice, refragmenting if needed */ + newnotice = *notice; + newnotice.z_auth = 1; + newnotice.z_ascii_authent = buf; + newnotice.z_authent_len = authent.length; + + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "realm_sendit_auth malloc"); + return; /* DON'T put on nack list */ + } + + buffer_len = sizeof(ZPacket_t); + + retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, + NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } #ifdef NOENCRYPTION - newnotice.z_checksum = 0; + newnotice.z_checksum = 0; #else - newnotice.z_checksum = - (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, cred.session); + newnotice.z_checksum = + (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, + cred.session); #endif - retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, - NULL, NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; - } + retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, + NULL, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); + free(buffer); + return; + } - /* This is not terribly pretty, but it does do its job. - * If a packet we get that needs to get sent off to another realm is - * too big after we slap on our authent, we refragment it further, - * a la Z_SendFragmentedNotice. This obliviates the need for what - * used to be done in ZFormatAuthenticRealmNotice, as we do it here. - * At some point it should be pulled back out into its own function, - * but only the server uses it. - */ - - if ((newnotice.z_message_len+hdrlen > buffer_len) || - (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)){ - /* Deallocate buffer, use a local one */ - free(buffer); + /* This is not terribly pretty, but it does do its job. + * If a packet we get that needs to get sent off to another realm is + * too big after we slap on our authent, we refragment it further, + * a la Z_SendFragmentedNotice. This obviates the need for what + * used to be done in ZFormatAuthenticRealmNotice, as we do it here. + * At some point it should be pulled back out into its own function, + * but only the server uses it. + */ + + if ((newnotice.z_message_len+hdrlen > buffer_len) || + (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) { + /* Deallocate buffer, use a local one */ + free(buffer); - partnotice = *notice; + partnotice = *notice; - partnotice.z_auth = 1; - partnotice.z_ascii_authent = buf; - partnotice.z_authent_len = authent.length; + partnotice.z_auth = 1; + partnotice.z_ascii_authent = buf; + partnotice.z_authent_len = authent.length; - origoffset = 0; - origlen = notice->z_message_len; + origoffset = 0; + origlen = notice->z_message_len; - if (notice->z_multinotice && strcmp(notice->z_multinotice, "")) - if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen) != 2) { - syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed"); - return; - } + if (notice->z_multinotice && strcmp(notice->z_multinotice, "")) + if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, + &origlen) != 2) { + syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed"); + return; + } #if 0 - zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset, notice->z_message_len, origlen)); + zdbug((LOG_DEBUG,"rlm_send_auth: orig: %d-%d/%d", origoffset, + notice->z_message_len, origlen)); #endif - fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE; - - while (offset < notice->z_message_len || !notice->z_message_len) { - (void) sprintf(multi, "%d/%d", offset+origoffset, origlen); - partnotice.z_multinotice = multi; - if (offset > 0) { - (void) gettimeofday(&partnotice.z_uid.tv, (struct timezone *)0); - partnotice.z_uid.tv.tv_sec = htonl((u_long) - partnotice.z_uid.tv.tv_sec); - partnotice.z_uid.tv.tv_usec = htonl((u_long) - partnotice.z_uid.tv.tv_usec); - (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr, - sizeof(__My_addr)); - } - message_len = min(notice->z_message_len-offset, fragsize); - partnotice.z_message = notice->z_message+offset; - partnotice.z_message_len = message_len; + fragsize = Z_MAXPKTLEN-hdrlen-Z_FRAGFUDGE; + + while (offset < notice->z_message_len || !notice->z_message_len) { + (void) sprintf(multi, "%d/%d", offset+origoffset, origlen); + partnotice.z_multinotice = multi; + if (offset > 0) { + (void) gettimeofday(&partnotice.z_uid.tv, + (struct timezone *)0); + partnotice.z_uid.tv.tv_sec = htonl((u_long) + partnotice.z_uid.tv.tv_sec); + partnotice.z_uid.tv.tv_usec = + htonl((u_long) partnotice.z_uid.tv.tv_usec); + (void) memcpy((char *)&partnotice.z_uid.zuid_addr, &__My_addr, + sizeof(__My_addr)); + } + message_len = min(notice->z_message_len-offset, fragsize); + partnotice.z_message = notice->z_message+offset; + partnotice.z_message_len = message_len; #if 0 - zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d", origoffset+offset, message_len, origlen)); + zdbug((LOG_DEBUG,"rlm_send_auth: new: %d-%d/%d", + origoffset+offset, message_len, origlen)); #endif - buffer = (char *) malloc(sizeof(ZPacket_t)); - if (!buffer) { - syslog(LOG_ERR, "realm_sendit_auth malloc"); - return; /* DON'T put on nack list */ - } - - retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, - &ptr, NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; - } + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "realm_sendit_auth malloc"); + return; /* DON'T put on nack list */ + } + + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, + &hdrlen, &ptr, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", + error_message(retval)); + free(buffer); + return; + } #ifdef NOENCRYPTION - partnotice.z_checksum = 0; + partnotice.z_checksum = 0; #else - partnotice.z_checksum = - (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, - cred.session); + partnotice.z_checksum = + (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, + cred.session); #endif - retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, &hdrlen, - NULL, NULL); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval)); - free(buffer); - return; - } - - ptr = buffer+hdrlen; - - (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len); - - buffer_len = hdrlen+partnotice.z_message_len; - - /* now send */ - if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); - free(buffer); - return; - } - - offset += fragsize; - - if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { - /* no space: just punt */ - syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); - free(buffer); - return; - } - - nacked->rexmits = 0; - nacked->packet = buffer; - nacked->dest.rlm.rlm_idx = realm - otherrealms; - nacked->dest.rlm.rlm_srv_idx = realm->idx; - nacked->packsz = buffer_len; - nacked->uid = partnotice.z_uid; - - /* Do the ack for the last frag, below */ - if (ack_to_sender) - nacked->ack_addr = *who; - else - nacked->ack_addr.sin_addr.s_addr = 0; - - /* set a timer to retransmit */ - nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); - - /* chain in */ - LIST_INSERT(&rlm_nacklist, nacked); - - if (!notice->z_message_len) - break; - } + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, + &hdrlen, NULL, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", + error_message(retval)); + free(buffer); + return; + } + + ptr = buffer+hdrlen; + + (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len); + + buffer_len = hdrlen+partnotice.z_message_len; + + /* now send */ + if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", + error_message(retval)); + free(buffer); + return; + } + + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); + free(buffer); + return; + } + + nacked->rexmits = 0; + nacked->packet = buffer; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = buffer_len; + nacked->uid = partnotice.z_uid; + + /* Do the ack for the last frag, below */ + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; + + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); + + offset += fragsize; + + if (!notice->z_message_len) + break; + } #if 0 - zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent")); + zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent")); #endif - } else { - /* This is easy, no further fragmentation needed */ - ptr = buffer+hdrlen; + } else { + /* This is easy, no further fragmentation needed */ + ptr = buffer+hdrlen; - (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len); + (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len); - buffer_len = hdrlen+newnotice.z_message_len; + buffer_len = hdrlen+newnotice.z_message_len; - /* now send */ - if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { - syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", error_message(retval)); - free(buffer); - return; - } + /* now send */ + if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) { + syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", + error_message(retval)); + free(buffer); + return; + } #if 0 - zdbug((LOG_DEBUG, "rlm_sendit_auth message sent")); + zdbug((LOG_DEBUG, "rlm_sendit_auth message sent")); #endif - /* now we've sent it, mark it as not ack'ed */ + /* now we've sent it, mark it as not ack'ed */ - if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { - /* no space: just punt */ - syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); - free(buffer); - return; - } - - nacked->rexmits = 0; - nacked->packet = buffer; - nacked->dest.rlm.rlm_idx = realm - otherrealms; - nacked->dest.rlm.rlm_srv_idx = realm->idx; - nacked->packsz = buffer_len; - nacked->uid = notice->z_uid; + if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) { + /* no space: just punt */ + syslog(LOG_ERR, "rlm_sendit_auth nack malloc"); + free(buffer); + return; + } - /* Do the ack for the last frag, below */ - if (ack_to_sender) - nacked->ack_addr = *who; - else - nacked->ack_addr.sin_addr.s_addr = 0; + nacked->rexmits = 0; + nacked->packet = buffer; + nacked->dest.rlm.rlm_idx = realm - otherrealms; + nacked->dest.rlm.rlm_srv_idx = realm->idx; + nacked->packsz = buffer_len; + nacked->uid = notice->z_uid; + + /* Do the ack for the last frag, below */ + if (ack_to_sender) + nacked->ack_addr = *who; + else + nacked->ack_addr.sin_addr.s_addr = 0; - /* set a timer to retransmit */ - nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); - /* chain in */ - LIST_INSERT(&rlm_nacklist, nacked); - } -#if 0 - if (ack_to_sender) - nacked->ack_addr = *who; -#endif - return; + /* set a timer to retransmit */ + nacked->timer = timer_set_rel(rexmit_times[0], rlm_rexmit, nacked); + /* chain in */ + LIST_INSERT(&rlm_nacklist, nacked); + } + return; } -int +static int ticket_expired(cred) CREDENTIALS *cred; { - /* extra 15 minutes for safety margin */ -#ifdef AFS_LIFETIMES - return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW + 15*60); -#else /* AFS_LIFETIMES */ - return (cred->issue_date + cred->lifetime*5*60 < NOW + 15*60); -#endif /* AFS_LIFETIMES */ +#ifdef HAVE_KRB_LIFE_TO_TIME + return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW); +#else /* HAVE_KRB_LIFE_TO_TIME */ + return (cred->issue_date + cred->lifetime*5*60 < NOW); +#endif /* HAVE_KRB_LIFE_TO_TIME */ } -int +static int ticket_lookup(realm) char *realm; { - CREDENTIALS cred; - KTEXT_ST authent; - int retval; + CREDENTIALS cred; + KTEXT_ST authent; + int retval; - retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred); - if (retval == GC_OK && !ticket_expired(&cred)) - /* good ticket */ - return(1); + retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred); + if (retval == GC_OK && !ticket_expired(&cred)) + /* good ticket */ + return(1); - if (!strcmp(realm, ZGetRealm())) { - get_tgt(); + return (0); +} + +static Code_t +ticket_retrieve(realm) + Realm *realm; +{ + int pid, retval = 0; + KTEXT_ST authent; + get_tgt(); + + if (realm->child_pid) + /* Right idea. Basically, we haven't gotten it yet */ + return KRBET_KDC_AUTH_EXP; + /* For Putrify */ memset(&authent.dat,0,MAX_KTXT_LEN); authent.mbz=0; - /* this is local, so try to contact the Kerberos server */ - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm, 0); - if (retval != KSUCCESS) { - syslog(LOG_ERR, "tkt_lookup: local: %s", - krb_err_txt[retval]); - return(0); + if (realm->have_tkt) { + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + realm->name, 0); + if (retval == KSUCCESS) { + return retval; + } } else { - return(1); + syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child"); } - } - - return (0); -} + + pid = fork(); + if (pid < 0) { + syslog(LOG_ERR, "tkt_rtrv: can't fork"); + return KRBET_KDC_AUTH_EXP; + } + else if (pid == 0) { +#ifdef _POSIX_VERSION + struct sigaction action; + + action.sa_flags = 0; + sigemptyset(&action.sa_mask); + action.sa_handler = 0; + sigaction(SIGCHLD, &action, NULL); + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); + sigaction(SIGFPE, &action, NULL); + sigaction(SIGHUP, &action, NULL); +#ifdef SIGEMT + sigaction(SIGEMT, &action, NULL); +#endif +#else + signal(SIGCHLD, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGUSR1, SIG_DFL); + signal(SIGUSR2, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGHUP, SIG_DFL); +#ifdef SIGEMT + signal(SIGEMT, SIG_DFL); +#endif +#endif -static Code_t -ticket_retrieve(realm) - Realm *realm; -{ - int pid, retval; - KTEXT_ST authent; - - get_tgt(); - - /* For Putrify */ - memset(&authent.dat,0,MAX_KTXT_LEN); - authent.mbz=0; - - /* Don't lose by trying too often. */ - if (NOW - realm->tkt_try > 5 * 60) { - retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, - realm->name, 0); - realm->tkt_try = NOW; - if (retval != KSUCCESS) { - syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm, - krb_err_txt[retval]); - return (retval+krb_err_base); + while (1) { + retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, + realm->name, 0); + if (retval == KSUCCESS) + exit(0); + + /* Sleep a little while before retrying */ + sleep(30); + } + } else { + realm->child_pid = pid; + realm->have_tkt = 0; + + syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name, + krb_err_txt[retval]); + return (retval+krb_err_base); } - return (0); - } else { - return (1); - } } #endif /* HAVE_KRB4 */ -- cgit v1.2.3