From 5c7254c327f37f65b5835017e8d3a83cfee3817d Mon Sep 17 00:00:00 2001 From: Karl Ramm Date: Wed, 20 Jun 2001 06:48:38 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r81, which included commits to RCS files with non-trunk default branches. --- clients/zaway/zaway.1 | 10 +- clients/zaway/zaway.c | 5 +- clients/zctl/zctl.1 | 13 + clients/znol/znol.c | 5 +- server/bdump.c | 57 +- server/class.c | 4 +- server/dispatch.c | 248 ++++++- server/kstuff.c | 29 +- server/main.c | 47 +- server/realm.c | 1980 +++++++++++++++++++++++++++++-------------------- server/server.c | 30 +- server/subscr.c | 560 ++++++++------ server/uloc.c | 2 +- server/zserver.h | 33 +- zhm/zhm.h | 1 - zhm/zhm_server.c | 17 +- zwgc/zephyr.c | 6 +- zwgc/zwgc.1 | 8 +- zwgc/zwgc.desc | 168 ++--- 19 files changed, 2007 insertions(+), 1216 deletions(-) diff --git a/clients/zaway/zaway.1 b/clients/zaway/zaway.1 index 0f46f96..85d0bce 100644 --- a/clients/zaway/zaway.1 +++ b/clients/zaway/zaway.1 @@ -77,11 +77,11 @@ not able to receive your message. .in -5 .sp If a user name does not match any of those listed in the file, and no -"*" or "%" field is specified, no return message is sent. -All messages are preceded by the line "Automated reply:". -To avoid loops, messages are not sent in response to messages beginning -with "Automated reply:" or sent by the same Kerberos principal as the -user running +"*" or "%" field is specified, no return message is sent. All +messages are preceded by a signature "Automated reply:". To avoid +loops, messages are not sent in response to messages beginning with an +"Automated reply:" signature or sent by the same Kerberos principal as +the user running .I zaway. .SH SAMPLE FILE diff --git a/clients/zaway/zaway.c b/clients/zaway/zaway.c index 8186f61..332598f 100644 --- a/clients/zaway/zaway.c +++ b/clients/zaway/zaway.c @@ -113,7 +113,7 @@ int main(argc,argv) } fp = fopen(awayfile,"r"); - if (!fp && argc > 1) { + if (!fp && argc > optind) { fprintf(stderr,"File %s not found!\n",awayfile); exit(1); } @@ -136,7 +136,8 @@ int main(argc,argv) for (;;) { if ((retval = ZReceiveNotice(¬ice, (struct sockaddr_in *)0)) != ZERR_NONE) { - com_err(argv[0],retval,"while receiving notice"); + if (retval != ETIMEDOUT) + com_err(argv[0],retval,"while receiving notice"); continue; } diff --git a/clients/zctl/zctl.1 b/clients/zctl/zctl.1 index 0817363..73d4fd5 100644 --- a/clients/zctl/zctl.1 +++ b/clients/zctl/zctl.1 @@ -125,6 +125,19 @@ performs the equivalent of a .B wg_startup command. .br +The variable \fBresolved_addresses\fR determines whether zwgc will, +for an IP address indicating the origin of a message, attempt to look +up the hostname corresponding to that IP address. The value none +indicates that hostnames will never be found, and that the zwgc +fromhost variable will thus always contain an IP address (in +dotted-decimal form). The value all indicates that there will always +be an attempt to look up a hostname. Note that in this case, if you +have any subscriptions with recipient ``\fI*\fR'', these subscriptions +may be revealed to other Zephyr users who operate their own DNS name +servers. Any other value is interpreted as a regular expression; +hostname lookup attempts will occur only if the IP address matches +this regular expression. +.br Any variable settings you make will be stored in \fI$HOME/.zephyr.vars\fR .TP .B show \fIvar\fR [ \fIvar\fR \ ... ] diff --git a/clients/znol/znol.c b/clients/znol/znol.c index 804f63f..53fd47c 100644 --- a/clients/znol/znol.c +++ b/clients/znol/znol.c @@ -194,7 +194,8 @@ main(argc,argv) if (ind == SUBSATONCE) { if (!justlist) if ((retval = (onoff==ON)? - ZSubscribeTo(subs,ind,(u_short)wgport): + ZSubscribeToSansDefaults(subs,ind, + (u_short)wgport): ZUnsubscribeTo(subs,ind,(u_short)wgport)) != ZERR_NONE) { com_err(argv[0],retval,(onoff==ON)? @@ -210,7 +211,7 @@ main(argc,argv) if (ind && !justlist) if ((retval = (onoff==ON)? - ZSubscribeTo(subs,ind,(u_short)wgport): + ZSubscribeToSansDefaults(subs,ind,(u_short)wgport): ZUnsubscribeTo(subs,ind,(u_short)wgport)) != ZERR_NONE) { com_err(argv[0],retval,(onoff==ON)? diff --git a/server/bdump.c b/server/bdump.c index 2de58e4..80f7e72 100644 --- a/server/bdump.c +++ b/server/bdump.c @@ -3,7 +3,9 @@ * * Created by: John T. Kohl * + * $Source$ * $Id$ + * $Author$ * * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -66,7 +68,6 @@ static void cleanup __P((Server *server)); #ifdef HAVE_KRB4 static long ticket_time; -static char my_realm[REALM_SZ]; #define TKTLIFETIME 120 #define tkt_lifetime(val) ((long) val * 5L * 60L) @@ -474,10 +475,10 @@ bdump_get_v12 (notice, auth, who, server) cleanup(server); return; } - /* my_realm is filled in inside get_tgt() */ + if (strcmp(kdata.pname, SERVER_SERVICE) || strcmp(kdata.pinst, SERVER_INSTANCE) || - strcmp(kdata.prealm, my_realm)) { + strcmp(kdata.prealm, ZGetRealm())) { syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s", kdata.pname, kdata.pinst,kdata.prealm); cleanup(server); @@ -582,6 +583,8 @@ bdump_send_list_tcp(kind, addr, class_name, inst, opcode, sender, recip, lyst, Code_t retval; u_short length; + memset (¬ice, 0, sizeof(notice)); + retval = ZMakeAscii(addrbuf, sizeof(addrbuf), (unsigned char *) &addr->sin_addr, sizeof(struct in_addr)); @@ -692,16 +695,8 @@ get_tgt() Sched *s; #endif - if (!*my_realm) { - retval = krb_get_lrealm(my_realm, 1); - if (retval != KSUCCESS) { - syslog(LOG_ERR,"krb_get_lrealm: %s", krb_get_err_text(retval)); - *my_realm = '\0'; - return(1); - } - } /* have they expired ? */ - if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + 15L) { + if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + (15L * 60L)) { /* +15 for leeway */ #if 0 zdbug((LOG_DEBUG,"get new tickets: %d %d %d", ticket_time, NOW, @@ -816,13 +811,10 @@ bdump_recv_loop(server) } #if defined (DEBUG) if (zdebug) { - char buf[4096]; - - sprintf(buf, "bdump:%s '%s' '%s' '%s' '%s' '%s'", + syslog(LOG_DEBUG, "bdump:%s '%s' '%s' '%s' '%s' '%s'", ZNoticeKinds[(int) notice.z_kind], notice.z_class, notice.z_class_inst, notice.z_opcode, notice.z_sender, notice.z_recipient); - syslog(LOG_DEBUG, buf); } #endif /* DEBUG */ if (notice.z_num_other_fields >= 1) { @@ -847,8 +839,10 @@ bdump_recv_loop(server) } else if (strcmp(notice.z_opcode, ADMIN_NEWREALM) == 0) { /* get a realm from the message */ realm = realm_get_realm_by_name(notice.z_message); - if (!realm) - return(ZERR_NONE); + if (!realm) { + syslog(LOG_ERR, "brl newrlm failed: no realm %s", + notice.z_message); + } } else if (strcmp(notice.z_class, LOGIN_CLASS) == 0) { /* 1 = tell it we are authentic */ retval = ulogin_dispatch(¬ice, 1, &who, server); @@ -890,7 +884,7 @@ bdump_recv_loop(server) syslog(LOG_ERR, "brl no client"); return ZSRV_NOCLT; } - retval = subscr_subscribe(client, ¬ice); + retval = subscr_subscribe(client, ¬ice, server); if (retval != ZERR_NONE) { syslog(LOG_WARNING, "brl subscr failed: %s", error_message(retval)); @@ -898,16 +892,17 @@ bdump_recv_loop(server) } } else if (strcmp(notice.z_opcode, REALM_SUBSCRIBE) == 0) { /* add a subscription for a realm */ - if (!realm) { - syslog(LOG_ERR, "brl no realm"); - return(ZSRV_NORLM); - } - retval = subscr_realm(realm, ¬ice); - if (retval != ZERR_NONE) { - syslog(LOG_WARNING, "brl subscr failed: %s", - error_message(retval)); - return retval; - } + if (realm) { + retval = subscr_realm(realm, ¬ice); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "brl subscr failed: %s", + error_message(retval)); + return retval; + } + } /* else + /* Other side tried to send us subs for a realm we didn't + know about, and so we drop them silently */ + } else { syslog(LOG_ERR, "brl bad opcode %s",notice.z_opcode); return ZSRV_UNKNOWNOPCODE; @@ -974,6 +969,8 @@ send_list(kind, port, class_name, inst, opcode, sender, recip, lyst, num) int packlen; Code_t retval; + memset (¬ice, 0, sizeof(notice)); + notice.z_kind = kind; notice.z_port = port; notice.z_class = class_name; @@ -1014,6 +1011,8 @@ send_normal_tcp(kind, port, class_name, inst, opcode, sender, recip, Code_t retval; u_short length; + memset (¬ice, 0, sizeof(notice)); + notice.z_kind = kind; notice.z_port = port; notice.z_class = class_name; diff --git a/server/class.c b/server/class.c index 63a4a2f..6ccacae 100644 --- a/server/class.c +++ b/server/class.c @@ -3,7 +3,8 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ * * Copyright (c) 1987 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -158,6 +159,7 @@ triplet_deregister(client, dest, realm) if (*triplet->clients == NULL && !triplet->acl) { LIST_DELETE(triplet); free_triplet(triplet); + return ZSRV_EMPTYCLASS; } return ZERR_NONE; } diff --git a/server/dispatch.c b/server/dispatch.c index 12f9c04..493fcd4 100644 --- a/server/dispatch.c +++ b/server/dispatch.c @@ -3,7 +3,8 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ * * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -51,10 +52,11 @@ ZCONST char *ZNoticeKinds[9] = {"UNSAFE", "UNACKED", "ACKED", "HMACK", * void nack_release(client) * Client *client; * - * void sendit(notice, auth, who) + * void sendit(notice, auth, who, external) * ZNotice_t *notice; * int auth; * struct sockaddr_in *who; + * int external; * * void xmit(notice, dest, auth, client) * ZNotice_t *notice; @@ -190,21 +192,33 @@ handle_packet() input_sin.sin_addr.s_addr = new_notice.z_sender_addr.s_addr; input_sin.sin_port = new_notice.z_port; input_sin.sin_family = AF_INET; - realm = realm_which_realm(&input_sin); - if (realm) { - authentic = ZCheckRealmAuthentication(&new_notice, &input_sin, - realm->name); - } else { + /* Should check to see if packet is from another realm's server, + or a client */ + /* Clients don't check auth of acks, nor do we make it so they + can in general, so this is safe. */ + if (new_notice.z_kind == SERVACK || new_notice.z_kind == SERVNAK) { + authentic = ZAUTH_YES; + } else { + if (realm = realm_which_realm(&input_sin)) { + authentic = ZCheckRealmAuthentication(&new_notice, + &input_sin, + realm->name); + } else authentic = ZCheckAuthentication(&new_notice, &input_sin); } from_server = 1; } else { from_server = 0; - realm = realm_which_realm(&whoisit); - if (realm) { - authentic = ZCheckRealmAuthentication(&new_notice, &whoisit, - realm->name); - } else { + /* Clients don't check auth of acks, nor do we make it so they + can in general, so this is safe. */ + if (new_notice.z_kind == SERVACK || new_notice.z_kind == SERVNAK) { + authentic = ZAUTH_YES; + } else { + if (realm = realm_which_realm(&whoisit)) { + authentic = ZCheckRealmAuthentication(&new_notice, + &whoisit, + realm->name); + } else authentic = ZCheckAuthentication(&new_notice, &whoisit); } } @@ -253,13 +267,12 @@ dispatch(notice, auth, who, from_server) } #if 0 if (zdebug) { - sprintf(dbg_buf, + syslog(LOG_DEBUG, "disp:%s '%s' '%s' '%s' notice to '%s' from '%s' %s/%d/%d", ZNoticeKinds[(int) notice->z_kind], notice->z_class, notice->z_class_inst, notice->z_opcode, notice->z_recipient, notice->z_sender, inet_ntoa(who->sin_addr), ntohs(who->sin_port), ntohs(notice->z_port)); - syslog(LOG_DEBUG, "%s", dbg_buf); } #endif @@ -298,12 +311,13 @@ dispatch(notice, auth, who, from_server) admin_notices.val++; status = server_adispatch(notice, authflag, who, me_server); } else { - if (!bound_for_local_realm(notice)) { + if (!realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) { cp = strchr(notice->z_recipient, '@'); if (!cp || - !(realm = realm_get_realm_by_name(realm_expand_realm(cp + 1)))) + !(realm = realm_get_realm_by_name(cp + 1))) { + /* Foreign user, local realm */ sendit(notice, authflag, who, 0); - else + } else realm_handoff(notice, authflag, who, realm, 1); } else { if (notice->z_recipient[0] == '@') @@ -338,15 +352,29 @@ sendit(notice, auth, who, external) String *class; class = make_string(notice->z_class, 1); - acl = class_get_acl(class); - if (acl != NULL) { + if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) { + Realm *rlm; + + acl = class_get_acl(class); + if (acl != NULL) { /* if controlled and not auth, fail */ - if (!auth) { - syslog(LOG_WARNING, "sendit unauthentic %s from %s", - notice->z_class, notice->z_sender); + if (!auth) { + syslog(LOG_WARNING, "sendit unauthentic %s from %s", + notice->z_class, notice->z_sender); + clt_ack(notice, who, AUTH_FAILED); + free_string(class); + return; + } + /* if from foreign realm server, disallow if not realm of sender */ + rlm = realm_which_realm(who); + if (rlm) { + if (!realm_sender_in_realm(rlm->name, notice->z_sender)) { + syslog(LOG_WARNING, "sendit auth not verifiable %s (%s) from %s", + notice->z_class, rlm->name, notice->z_sender); clt_ack(notice, who, AUTH_FAILED); free_string(class); return; + } } /* if not auth to transmit, fail */ if (!access_check(notice->z_sender, acl, TRANSMIT)) { @@ -365,6 +393,7 @@ sendit(notice, auth, who, external) free_string(class); return; } + } } if (!realm_which_realm(who)) { if (memcmp(¬ice->z_sender_addr.s_addr, &who->sin_addr.s_addr, @@ -406,15 +435,17 @@ sendit(notice, auth, who, external) /* Send to clients subscribed to the triplet itself. */ dest.classname = class; dest.inst = make_string(notice->z_class_inst, 1); - if (bound_for_local_realm(notice) && *notice->z_recipient == '@') { - dest.recip = make_string("", 0); - } else { - strncpy(recipbuf, notice->z_recipient, sizeof(recipbuf)); - recipp = strrchr(recipbuf, '@'); - if (recipp) - sprintf(recipp + 1, "%s", realm_expand_realm(recipp + 1)); - dest.recip = make_string(recipbuf, 0); + if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient) && + *notice->z_recipient == '@') + dest.recip = make_string("", 0); + else { + strncpy(recipbuf, notice->z_recipient, sizeof(recipbuf)); + recipp = strrchr(recipbuf, '@'); + if (recipp) + sprintf(recipp + 1, "%s", realm_expand_realm(recipp + 1)); + dest.recip = make_string(recipbuf, 0); } + if (send_to_dest(notice, auth, &dest, send_counter, external)) any = 1; @@ -458,12 +489,16 @@ send_to_dest(notice, auth, dest, send_counter, external) if ((*clientp)->last_send == send_counter) continue; (*clientp)->last_send = send_counter; - if ((*clientp)->realm && external) + if ((*clientp)->realm) { + if (external) { realm_handoff(notice, auth, &clientp[0]->addr, clientp[0]->realm, 1); - else + any = 1; + } + } else { xmit(notice, &((*clientp)->addr), auth, *clientp); - any = 1; + any = 1; + } } return any; @@ -606,6 +641,104 @@ xmit(notice, dest, auth, client) notice->z_authent_len = 0; notice->z_ascii_authent = (char *)""; retval = ZFormatSmallRawNotice(notice, noticepack, &packlen); + /* This code is needed because a Zephyr can "grow" when a remote + * realm name is inserted into the Zephyr before being resent out + * locally. It essentially matches the code in realm.c to do the + * same thing with authentic Zephyrs. + */ + if (retval == ZERR_PKTLEN) { + ZNotice_t partnotice, newnotice; + char multi[64]; + char *buffer, *ptr; + int buffer_len, hdrlen, offset, fragsize, ret_len, message_len; + int origoffset, origlen; + + free(noticepack); + + retval = ZSetDestAddr(dest); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "xmit set addr: %s", error_message(retval)); + return; + } + + partnotice = *notice; + + partnotice.z_auth = 0; + partnotice.z_authent_len = 0; + partnotice.z_ascii_authent = (char *)""; + + origoffset = offset = fragsize = 0; + origlen = notice->z_message_len; + + buffer = (char *) malloc(sizeof(ZPacket_t)); + if (!buffer) { + syslog(LOG_ERR, "xmit unauth refrag malloc"); + return; /* DON'T put on nack list */ + } + buffer_len = sizeof(ZPacket_t); + + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, + &hdrlen, NULL, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_ERR, "xmit unauth refrag fmt: failed"); + free(buffer); + return; + } + + if (notice->z_multinotice && strcmp(notice->z_multinotice, "")) + if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, &origlen) + != 2) + { + syslog(LOG_WARNING, "xmit unauth refrag: parse failed"); + free(buffer); + return; + } + + 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)); + } + partnotice.z_message = notice->z_message+offset; + message_len = min(notice->z_message_len-offset, fragsize); + partnotice.z_message_len = message_len; + + retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, + &hdrlen, &ptr, NULL); + if (retval != ZERR_NONE) { + syslog(LOG_WARNING, "xmit unauth refrag 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; + + xmit_frag(&partnotice, buffer, buffer_len, 0); + + offset += fragsize; + + if (!notice->z_message_len) + break; + } + free(buffer); + return; + } + /* End of refrag code */ + if (retval != ZERR_NONE) { syslog(LOG_ERR, "xmit format: %s", error_message(retval)); free(noticepack); @@ -786,6 +919,18 @@ clt_ack(notice, who, sent) packlen = sizeof(ackpack); retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen); + + if (retval == ZERR_HEADERLEN) { + /* Since an ack header can be larger than a message header... (crock) */ + acknotice.z_opcode = ""; + acknotice.z_class = ""; + acknotice.z_class_inst = ""; + acknotice.z_opcode = ""; + acknotice.z_default_format = ""; + + retval = ZFormatSmallRawNotice(&acknotice, ackpack, &packlen); + } + if (retval != ZERR_NONE) { syslog(LOG_ERR, "clt_ack format: %s", error_message(retval)); return; @@ -1022,7 +1167,7 @@ control_dispatch(notice, auth, who, server) /* in case it's changed */ memcpy(client->session_key, ZGetSession(), sizeof(C_Block)); #endif - retval = subscr_subscribe(client, notice); + retval = subscr_subscribe(client, notice, server); if (retval != ZERR_NONE) { syslog(LOG_WARNING, "subscr failed: %s", error_message(retval)); if (server == me_server) @@ -1080,9 +1225,11 @@ control_dispatch(notice, auth, who, server) #endif client_deregister(client, 0); } else { - syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); - if (server == me_server) - nack(notice, who); + syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); + if (server == me_server) { + if (strcmp(notice->z_class_inst, ZEPHYR_CTL_REALM) != 0) + nack(notice, who); + } return ZERR_NONE; } @@ -1120,6 +1267,31 @@ hostm_shutdown() } } +void +realm_shutdown() +{ + int i, s, newserver; + struct sockaddr_in sin; + + for (i = 0; i < nservers; i++) { + if (i != me_server_idx && otherservers[i].state == SERV_UP) + break; + } + zdbug((LOG_DEBUG, "rlm_shutdown")); + + newserver = (i < nservers); + if (newserver) { + while (1) { + s = (random() % (nservers - 1)) + 1; + if (otherservers[s].state == SERV_UP) + break; + } + realm_deathgram(&otherservers[s]); + } else { + realm_deathgram(NULL); + } +} + static void hostm_deathgram(sin, server) struct sockaddr_in *sin; @@ -1130,6 +1302,8 @@ hostm_deathgram(sin, server) ZNotice_t shutnotice; char *shutpack; + memset (&shutnotice, 0, sizeof(shutnotice)); + shutnotice.z_kind = HMCTL; shutnotice.z_port = sin->sin_port; /* we are sending it */ shutnotice.z_class = HM_CTL_CLASS; diff --git a/server/kstuff.c b/server/kstuff.c index 04396fa..ca9f055 100644 --- a/server/kstuff.c +++ b/server/kstuff.c @@ -8,7 +8,8 @@ * "mit-copyright.h". */ /* - * $Id$ + * $Source$ + * $Header$ */ #include "zserver.h" @@ -121,7 +122,6 @@ SendKerberosData(fd, ticket, service, host) { int rem; char p[32]; - char krb_realm[REALM_SZ]; int written; int size_to_write; @@ -190,8 +190,18 @@ ZCheckRealmAuthentication(notice, from, realm) checksum = compute_rlm_checksum(notice, session_key); /* If checksum matches, packet is authentic. If not, we might - * have an outdated session key, so keep going the slow way. - */ + * have an outdated session key, so keep going the slow way. + */ + if (checksum == notice->z_checksum) { + (void) memcpy((char *)__Zephyr_session, (char *)session_key, + sizeof(C_Block)); /* For control_dispatch() */ + return ZAUTH_YES; + } + + /* Try again. This way we can switch to the same checksums + * that the rest of Zephyr uses at a future date, but for now + * we need to be compatible */ + checksum = compute_checksum(notice, session_key); if (checksum == notice->z_checksum) { memcpy(__Zephyr_session, session_key, sizeof(C_Block)); return ZAUTH_YES; @@ -212,12 +222,17 @@ ZCheckRealmAuthentication(notice, from, realm) /* Check the cryptographic checksum. */ #ifdef NOENCRYPTION - our_checksum = 0; + checksum = 0; #else checksum = compute_rlm_checksum(notice, dat.session); #endif - if (checksum != notice->z_checksum) + if (checksum != notice->z_checksum) { +#ifndef NOENCRYPTION + checksum = compute_checksum(notice, dat.session); + if (checksum != notice->z_checksum) +#endif return ZAUTH_FAILED; + } /* Record the session key, expiry time, and source principal in the * hash table, so we can do a fast check next time. */ @@ -296,7 +311,7 @@ ZCheckAuthentication(notice, from) /* Check the cryptographic checksum. */ #ifdef NOENCRYPTION - our_checksum = 0; + checksum = 0; #else checksum = compute_checksum(notice, dat.session); #endif diff --git a/server/main.c b/server/main.c index bd3e138..37b8efb 100644 --- a/server/main.c +++ b/server/main.c @@ -3,7 +3,8 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ * * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -300,6 +301,7 @@ main(argc, argv) timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL); #endif + realm_wakeup(); #ifdef DEBUG_MALLOC malloc_inuse(&m_size); #endif @@ -380,9 +382,14 @@ initialize() krb_set_tkt_string(tkt_file); #endif realm_init(); - + ZSetServerState(1); ZInitialize(); /* set up the library */ +#ifdef HAVE_KRB4 + /* Override what Zinitialize set for ZGetRealm() */ + if (*my_realm) + strcpy(__Zephyr_realm, my_realm); +#endif init_zsrv_err_tbl(); /* set up err table */ ZSetFD(srv_socket); /* set up the socket as the input fildes */ @@ -502,7 +509,11 @@ bye(sig) int sig; { server_shutdown(); /* tell other servers */ +#ifdef REALM_MGMT + realm_shutdown(); /* tell other realms */ +#endif hostm_shutdown(); /* tell our hosts */ + kill_realm_pids(); #ifdef HAVE_KRB4 dest_tkt(); #endif @@ -624,17 +635,43 @@ static RETSIGTYPE reap(sig) int sig; { + int pid, i = 0; int oerrno = errno; - + Realm *rlm; #ifdef _POSIX_VERSION int waitb; - while (waitpid(-1, &waitb, WNOHANG) == 0) ; #else union wait waitb; - while (wait3 (&waitb, WNOHANG, (struct rusage*) 0) == 0) ; +#endif +#if 1 + zdbug((LOG_DEBUG,"reap()")); +#endif +#ifdef _POSIX_VERSION + while ((pid = waitpid(-1, &waitb, WNOHANG)) == 0) + { i++; if (i > 10) break; } +#else + while ((pid = wait3 (&waitb, WNOHANG, (struct rusage*) 0)) == 0) + { i++; if (i > 10) break; } #endif errno = oerrno; + + if (pid) { + if (WIFSIGNALED(waitb) == 0) { + if (WIFEXITED(waitb) != 0) { + rlm = realm_get_realm_by_pid(pid); + if (rlm) { + rlm->child_pid = 0; + rlm->have_tkt = 1; + } + } + } else { + rlm = realm_get_realm_by_pid(pid); + if (rlm) { + rlm->child_pid = 0; + } + } + } } static void diff --git a/server/realm.c b/server/realm.c index 1ad55fc..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,157 +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]); - } - rlm->count = found; - rlm->addrs = (struct sockaddr_in *)malloc(found * sizeof (struct sockaddr_in)); - if (!rlm->addrs) { - syslog(LOG_CRIT, "malloc failed in get_realm_addrs"); - 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 get_realm_addrs"); - abort(); + + for (nrealms = 0; *rlmnames[nrealms].name; nrealms++); + + otherrealms = (Realm *)malloc(nrealms * sizeof(Realm)); + if (!otherrealms) { + syslog(LOG_CRIT, "malloc failed in realm_init"); + abort(); } - memset(&client->addr, 0, sizeof(struct sockaddr_in)); + + 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)); + 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; + 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); + 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); +} + +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); + } +} + +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++; + } + + 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); + } + } } static Code_t @@ -477,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); } @@ -511,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 @@ -564,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 */ } @@ -593,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) @@ -738,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 */ diff --git a/server/server.c b/server/server.c index e9c5894..377d397 100644 --- a/server/server.c +++ b/server/server.c @@ -3,7 +3,8 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ * * Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -419,6 +420,13 @@ srv_states[] = { "SERV_DEAD", "SERV_STARTING" }; +static char * +rlm_states[] = { + "REALM_UP", + "REALM_TARDY", + "REALM_DEAD", + "REALM_STARTING" +}; /* * A server timout has expired. If enough hello's have been unanswered, @@ -639,6 +647,8 @@ server_kill_clt(client) pnotice = ¬ice; + memset (¬ice, 0, sizeof(notice)); + pnotice->z_kind = ACKED; pnotice->z_port = srv_addr.sin_port; @@ -872,10 +882,9 @@ send_stats(who) char **responses; int num_resp; char *vers, *pkts, *upt; + Realm *realm; -#if defined(OLD_COMPAT) || defined(NEW_COMPAT) int extrafields = 0; -#endif /* OLD_ or NEW_COMPAT */ #define NUM_FIXED 3 /* 3 fixed fields, plus server info */ /* well, not really...but for backward compatibility, we gotta @@ -901,12 +910,9 @@ send_stats(who) if (new_compat_count_subscr) extrafields++; #endif /* NEW_COMPAT */ -#if defined(OLD_COMPAT) || defined(NEW_COMPAT) + extrafields += nrealms; responses = (char **) malloc((NUM_FIXED + nservers + extrafields) * sizeof(char *)); -#else - responses = (char **) malloc((NUM_FIXED + nservers) * sizeof(char *)); -#endif /* OLD_ or NEW_COMPAT */ responses[0] = vers; responses[1] = pkts; responses[2] = upt; @@ -944,6 +950,12 @@ send_stats(who) responses[num_resp++] = strsave(buf); } #endif /* NEW_COMPAT */ + for (realm = otherrealms, i = 0; i < nrealms ; i++, realm++) { + sprintf(buf, "%s(%s)/%s", realm->name, + inet_ntoa((realm->addrs[realm->idx]).sin_addr), + rlm_states[(int) realm->state]); + responses[num_resp++] = strsave(buf); + } send_msg_list(who, ADMIN_STATUS, responses, num_resp, 0); @@ -1251,6 +1263,8 @@ send_msg(who, opcode, auth) pnotice = ¬ice; + memset (¬ice, 0, sizeof(notice)); + pnotice->z_kind = ACKED; pnotice->z_port = srv_addr.sin_port; @@ -1307,6 +1321,8 @@ send_msg_list(who, opcode, lyst, num, auth) Code_t retval; Unacked *nacked; + memset (¬ice, 0, sizeof(notice)); + notice.z_kind = UNSAFE; notice.z_port = srv_addr.sin_port; notice.z_class = ZEPHYR_ADMIN_CLASS; diff --git a/server/subscr.c b/server/subscr.c index abf28ca..eb3ba27 100644 --- a/server/subscr.c +++ b/server/subscr.c @@ -3,7 +3,8 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ * * Copyright (c) 1987,1988 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -85,20 +86,19 @@ extern int new_compat_count_subscr; /* counter of old use */ extern char *re_comp(), *re_conv(); static Code_t add_subscriptions __P((Client *who, Destlist *subs_queue, - ZNotice_t *notice)); + ZNotice_t *notice, Server *server)); static Destlist *extract_subscriptions __P((ZNotice_t *notice)); static void free_subscriptions __P((Destlist *subs)); +static void free_subscription __P((Destlist *sub)); static char **subscr_marshal_subs __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, int *found)); static Destlist *subscr_copy_def_subs __P((char *person)); -static Code_t subscr_subscribe_realms __P((struct sockaddr_in *who, - Destlist *newsubs, - ZNotice_t *notice)); static Code_t subscr_realm_sendit __P((Client *who, Destlist *subs, ZNotice_t *notice, Realm *realm)); static void subscr_unsub_realms __P((Destlist *newsubs)); -static void subscr_unsub_sendit __P((Destlist *subs, Realm *realm)); +static void subscr_unsub_sendit __P((Client *who, Destlist *subs, + Realm *realm)); static int cl_match __P((Destlist*, Client *)); static int defaults_read = 0; /* set to 1 if the default subs @@ -118,21 +118,23 @@ String *empty; */ Code_t -subscr_subscribe(who, notice) +subscr_subscribe(who, notice, server) Client *who; ZNotice_t *notice; + Server *server; { Destlist *subs; subs = extract_subscriptions(notice); - return add_subscriptions(who, subs, notice); + return add_subscriptions(who, subs, notice, server); } static Code_t -add_subscriptions(who, subs, notice) +add_subscriptions(who, subs, notice, server) Client *who; Destlist *subs; ZNotice_t *notice; + Server *server; { Destlist *next; Code_t retval; @@ -152,18 +154,25 @@ add_subscriptions(who, subs, notice) zdbug ((LOG_DEBUG, "subscr: %s/%s/%s", subs->dest.classname->string, subs->dest.inst->string, subs->dest.recip->string)); #endif + /* check the recipient for a realm which isn't ours */ + realm = NULL; + if (subs->dest.recip->string[0] == '@' && + strcmp((subs->dest.recip->string + 1), ZGetRealm()) != 0) + realm = realm_get_realm_by_name(subs->dest.recip->string + 1); if (!bdumping) { if (subs->dest.recip != empty && subs->dest.recip != sender && subs->dest.recip->string[0] != '@') { syslog(LOG_WARNING, "subscr unauth %s recipient %s", sender->string, subs->dest.recip->string); - continue; + free_subscription(subs); /* free this one - denied */ + continue; /* the for loop */ } acl = class_get_acl(subs->dest.classname); - if (acl) { + if (acl && !realm) { if (!access_check(sender->string, acl, SUBSCRIBE)) { syslog(LOG_WARNING, "subscr unauth %s class %s", sender->string, subs->dest.classname->string); + free_subscription(subs); /* free this one - denied */ continue; /* the for loop */ } if (wildcard_instance == subs->dest.inst) { @@ -171,36 +180,39 @@ add_subscriptions(who, subs, notice) syslog(LOG_WARNING, "subscr unauth %s class %s wild inst", sender->string, subs->dest.classname->string); - continue; + free_subscription(subs); /* free this one - denied */ + continue; /* the for loop */ } } } } - /* check the recipient for a realm which isn't ours */ - realm = NULL; - if (subs->dest.recip->string[0] == '@' && - strcmp((subs->dest.recip->string + 1), ZGetRealm()) != 0) - realm = realm_get_realm_by_name(subs->dest.recip->string + 1); - if (realm) { + if (realm && !bdumping && server && server == me_server) { retval = subscr_realm_sendit(who, subs, notice, realm); if (retval != ZERR_NONE) { - free(subs); + free_subscriptions(subs); + free_string(sender); return(retval); - } - } - retval = triplet_register(who, &subs->dest, realm); - if (retval != ZERR_NONE) { - free(subs); - if (retval == ZSRV_CLASSXISTS) { - continue; } else { - free_subscriptions(next); - return retval; + free_subscription(subs); /* free this one, will get from ADD */ } + } else { + retval = triplet_register(who, &subs->dest, NULL); + if (retval != ZERR_NONE) { + if (retval == ZSRV_CLASSXISTS) { + free_subscription(subs); /* free this one */ + } else { + free_subscriptions(subs); + free_string(sender); + return retval; + } + } else { + /* If realm, let the REALM_ADD_SUBSCRIBE do insertion */ + LIST_INSERT(&who->subs, subs); + } } - LIST_INSERT(&who->subs, subs); } + free_string(sender); return ZERR_NONE; } @@ -215,7 +227,7 @@ subscr_def_subs(who) Destlist *subs; subs = subscr_copy_def_subs(who->principal->string); - return add_subscriptions(who, subs, &default_notice); + return add_subscriptions(who, subs, &default_notice, NULL); } void @@ -343,20 +355,17 @@ subscr_cancel(sin, notice) client_next = client_subs->next; if (ZDest_eq(&client_subs->dest, &subs->dest)) { LIST_DELETE(client_subs); - triplet_deregister(who, &client_subs->dest, NULL); + retval = triplet_deregister(who, &client_subs->dest, NULL); if (retval == ZSRV_EMPTYCLASS && client_subs->dest.recip->string[0] == '@') { realm = realm_get_realm_by_name(client_subs->dest.recip->string + 1); if (realm) - subscr_unsub_sendit(client_subs, realm); + subscr_unsub_sendit(who, client_subs, realm); realm = NULL; } - free_string(client_subs->dest.classname); - free_string(client_subs->dest.inst); - free_string(client_subs->dest.recip); - free(client_subs); + free_subscription(client_subs); found = 1; break; } @@ -406,10 +415,7 @@ subscr_realm_cancel(sin, notice, realm) if (ZDest_eq(&client_subs->dest, &subs->dest)) { LIST_DELETE(client_subs); retval = triplet_deregister(realm->client, &client_subs->dest, realm); - free_string(client_subs->dest.classname); - free_string(client_subs->dest.inst); - free_string(client_subs->dest.recip); - free(client_subs); + free_subscription(client_subs); found = 1; break; } @@ -460,13 +466,10 @@ subscr_cancel_client(client) subs->dest.recip->string[0] == '@') { realm = realm_get_realm_by_name(subs->dest.recip->string + 1); if (realm) - subscr_unsub_sendit(subs, realm); + subscr_unsub_sendit(client, subs, realm); realm = NULL; } - free_string(subs->dest.classname); - free_string(subs->dest.inst); - free_string(subs->dest.recip); - free(subs); + free_subscription(subs); } client->subs = NULL; @@ -918,6 +921,19 @@ subscr_send_subs(client) * free the memory allocated for the list of subscriptions. */ +/* + * free the memory allocated for one subscription. + */ + +static void +free_subscription(Destlist *sub) +{ + free_string(sub->dest.classname); + free_string(sub->dest.inst); + free_string(sub->dest.recip); + free(sub); +} + static void free_subscriptions(subs) Destlist *subs; @@ -926,10 +942,7 @@ free_subscriptions(subs) for (; subs; subs = next) { next = subs->next; - free_string(subs->dest.classname); - free_string(subs->dest.inst); - free_string(subs->dest.recip); - free(subs); + free_subscription (subs); } } @@ -1031,9 +1044,6 @@ subscr_realm_sendit(who, subs, notice, realm) ZNotice_t *notice; Realm *realm; { -#if 0 - Destlist *subs2; -#endif ZNotice_t snotice; char *pack; int packlen; @@ -1048,28 +1058,14 @@ subscr_realm_sendit(who, subs, notice, realm) #endif -#ifdef notdef - for (subs2 = subs; subs2; subs2 = subs2->next, found++); - /* found is now the number of subscriptions */ - - /* coalesce the subscription information into a list of char *'s */ - /* one extra for client information */ - if ((text = (char **) malloc((found * NUM_FIELDS + 2) - * sizeof(char *))) == (char **) 0) - { - syslog(LOG_ERR, "subscr_rlm_sendit malloc"); - return(ENOMEM); - } -#endif /* notdef */ - if ((text=(char **)malloc((NUM_FIELDS + 2)*sizeof(char *))) == (char **)0) { syslog(LOG_ERR, "subscr_rlm_sendit malloc"); return(ENOMEM); } /* convert the address to a string of the form x.x.x.x/port */ - strcpy(addr, inet_ntoa(notice->z_sender_addr)); + strcpy(addr, inet_ntoa(who->addr.sin_addr)); if ((retval = ZMakeAscii(port, sizeof(port), (unsigned char *) - ¬ice->z_port, sizeof(u_short))) != ZERR_NONE) + &who->addr.sin_port, sizeof(u_short))) != ZERR_NONE) { syslog(LOG_ERR, "subscr_rlm_sendit make ascii: %s", error_message(retval)); @@ -1078,19 +1074,15 @@ subscr_realm_sendit(who, subs, notice, realm) text[0] = addr; text[1] = port; -#ifdef notdef - for (i = 0, subs2 = subs; subs2, i < found ; i++, subs2 = subs2->next) { - text[i*NUM_FIELDS + 2] = subs2->dest.classname->string; - text[i*NUM_FIELDS + 3] = subs2->dest.inst->string; - text[i*NUM_FIELDS + 4] = subs2->dest.recip->string; - } -#endif /* notdef */ - text[2] = subs->dest.classname->string; text[3] = subs->dest.inst->string; text[4] = subs->dest.recip->string; + zdbug((LOG_DEBUG, "subscr_realm_sendit %s/%s (%s) %s,%s,%s\n", + text[0], text[1], who->principal->string, text[2], text[3], text[4])); + /* format snotice */ + memset (&snotice, 0, sizeof(snotice)); snotice.z_class_inst = ZEPHYR_CTL_REALM; snotice.z_opcode = REALM_REQ_SUBSCRIBE; snotice.z_port = srv_addr.sin_port; @@ -1101,17 +1093,12 @@ subscr_realm_sendit(who, subs, notice, realm) snotice.z_kind = ACKED; snotice.z_num_other_fields = 0; snotice.z_default_format = ""; - snotice.z_sender = notice->z_sender; + snotice.z_sender = who->principal->string; snotice.z_recipient = notice->z_recipient; snotice.z_default_format = notice->z_default_format; -#ifdef notdef - if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, - &pack, &packlen, ZNOAUTH)) != ZERR_NONE) -#else if ((retval = ZFormatNoticeList(&snotice, text, NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) -#endif { syslog(LOG_WARNING, "subscr_rlm_sendit format: %s", error_message(retval)); @@ -1136,6 +1123,7 @@ subscr_realm_sendit(who, subs, notice, realm) return(ZERR_NONE); } +/* Called from subscr_realm and subscr_foreign_user */ static Code_t subscr_add_raw(client, realm, newsubs) Client *client; @@ -1160,12 +1148,33 @@ subscr_add_raw(client, realm, newsubs) #endif retval = triplet_register(client, &subs->dest, realm); if (retval != ZERR_NONE) { - free(subs); - if (retval == ZSRV_CLASSXISTS) { - continue; - } else { - free_subscriptions(subs2); - return retval; + free_subscription(subs); + if (retval == ZSRV_CLASSXISTS) { + continue; + } else { + free_subscriptions(subs2); + return retval; + } + } else { + if (!realm) { + Realm *remrealm = + realm_get_realm_by_name(subs->dest.recip->string + 1); + if (remrealm) { + Destlist *sub = (Destlist *) malloc(sizeof(Destlist)); + if (!sub) { + syslog(LOG_WARNING, "subscr_add_raw: no mem"); + } else { + sub->dest.classname = make_string(subs->dest.classname->string, 0); + sub->dest.inst = make_string(subs->dest.inst->string, 0); + sub->dest.recip = make_string(subs->dest.recip->string, 0); +#if 1 + zdbug ((LOG_DEBUG, "subscr: add %s/%s/%s in %s", + sub->dest.classname->string, sub->dest.inst->string, + sub->dest.recip->string, remrealm->name)); +#endif + LIST_INSERT(&remrealm->remsubs, sub); + } + } } } LIST_INSERT(head, subs); @@ -1173,6 +1182,7 @@ subscr_add_raw(client, realm, newsubs) return ZERR_NONE; } +/* Called from bdump_recv_loop to decapsulate realm subs */ Code_t subscr_realm(realm, notice) Realm *realm; @@ -1192,21 +1202,41 @@ subscr_realm(realm, notice) /* Like realm_sendit, this only takes one item from subs */ static void -subscr_unsub_sendit(subs, realm) +subscr_unsub_sendit(who, subs, realm) + Client *who; Destlist *subs; Realm *realm; { ZNotice_t unotice; Code_t retval; -#ifdef notdef - char *list[7 * NUM_FIELDS]; -#else /* notdef */ - char *list[NUM_FIELDS]; -#endif /* notdef */ + char **list; char *pack; int packlen; int found = 0; - Destlist *subs2; + Destlist *subsp, *subsn; + + for (subsp = realm->remsubs; subsp; subsp = subsn) { + subsn = subsp->next; + if (ZDest_eq(&subs->dest, &subsp->dest)) { +#if 1 + zdbug ((LOG_DEBUG, "subscr: del %s/%s/%s in %s", + subsp->dest.classname->string, subsp->dest.inst->string, + subsp->dest.recip->string, realm->name)); +#endif + LIST_DELETE(subsp); + free_subscription(subsp); + break; + } + } + + if ((list=(char **)malloc((NUM_FIELDS)*sizeof(char *))) == (char **)0) { + syslog(LOG_ERR, "subscr_unsub_sendit malloc"); + return; + } + + list[0] = subs->dest.classname->string; + list[1] = subs->dest.inst->string; + list[2] = ""; unotice.z_class = ZEPHYR_CTL_CLASS; unotice.z_class_inst = ZEPHYR_CTL_REALM; @@ -1219,52 +1249,13 @@ subscr_unsub_sendit(subs, realm) unotice.z_num_other_fields = 0; unotice.z_default_format = ""; -#ifdef notdef - found = 0; - for (subs2 = subs; subs2; subs2 = subs2->next) { - list[found * NUM_FIELDS] = subs2->dest.classname->string; - list[found * NUM_FIELDS + 1] = subs2->dest.inst->string; - list[found * NUM_FIELDS + 2] = ""; - - found++; - - if (found >= 7) { - if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", - error_message(retval)); - return; - } - if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s", - error_message(retval)); - free(pack); - return; - } - free(pack); - realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0); - found = 0; - } - } - - if (found == 0) - return; - - if ((retval = ZFormatNoticeList(&unotice, list, found * NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", - error_message(retval)); - return; - } -#else /* notdef */ - list[0] = subs->dest.classname->string; - list[1] = subs->dest.inst->string; - list[2] = ""; - if ((retval = ZFormatNoticeList(&unotice, list, NUM_FIELDS, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { syslog(LOG_WARNING, "subscr_unsub_sendit format: %s", error_message(retval)); + free(list); return; } -#endif /* notdef */ + free(list); if ((retval = ZParseNotice(pack, packlen, &unotice)) != ZERR_NONE) { syslog(LOG_WARNING, "subscr_unsub_sendit parse: %s", @@ -1272,10 +1263,11 @@ subscr_unsub_sendit(subs, realm) free(pack); return; } + realm_handoff(&unotice, 1, who ? &(who->addr) : NULL, realm, 0); free(pack); - realm_handoff(&unotice, 1, (struct sockaddr_in *) 0, realm, 0); } +/* Called from bump_send_loop by way of realm_send_realms */ Code_t subscr_send_realm_subs(realm) Realm *realm; @@ -1343,117 +1335,222 @@ subscr_send_realm_subs(realm) return ZERR_NONE; } -static Code_t -subscr_check_foreign_subs(notice, who, realm, newsubs) - ZNotice_t *notice; - struct sockaddr_in *who; +Code_t +subscr_realm_subs(realm) Realm *realm; - Destlist *newsubs; { - Destlist *subs, *subs2, *next; - Acl *acl; - char **text; - int found = 0; + int i = 0; + Destlist *subs, *next; + char buf[512]; + char *text[2 + NUM_FIELDS]; + unsigned short num = 0; + Code_t retval; ZNotice_t snotice; - char *pack, *cp; + char *pack; int packlen; - Code_t retval; - String *sender; - - for (subs = newsubs; subs; subs = subs->next) - found++; - - if (found == 0) - return(ZERR_NONE); - - sender = make_string(notice->z_sender, 0); - - if ((text = (char **)malloc((found * NUM_FIELDS + 2) * sizeof(char *))) == (char **) 0) { - syslog(LOG_ERR, "subscr_ck_forn_subs no mem(text)"); - return(ENOMEM); - } - - /* grab the client information from the incoming message */ - cp = notice->z_message; - text[0] = cp; - - I_ADVANCE(2); - text[1] = cp; - - I_ADVANCE(3); + Client **clientp; + char port[16]; - found = 0; - for (subs = newsubs; subs; subs = next) { - next=subs->next; - acl = class_get_acl(subs->dest.classname); - if (acl) { - if (!access_check(sender->string, acl, SUBSCRIBE)) { - syslog(LOG_WARNING, "subscr unauth %s class %s", - sender->string, subs->dest.classname->string); - continue; /* the for loop */ - } - if (wildcard_instance == subs->dest.inst) { - if (!access_check(sender->string, acl, INSTWILD)) { - syslog(LOG_WARNING, - "subscr unauth %s class %s wild inst", - sender->string, subs->dest.classname->string); - continue; - } - } - } +#if 0 + zdbug((LOG_DEBUG, "realm_subs")); +#endif - /* okay to subscribe. save for return trip */ - text[found*NUM_FIELDS + 2] = subs->dest.classname->string; - text[found*NUM_FIELDS + 3] = subs->dest.inst->string; - text[found*NUM_FIELDS + 4] = ""; - found++; + if (!realm->remsubs) + return ZERR_NONE; - retval = triplet_register(realm->client, &subs->dest, realm); + for (subs=realm->remsubs; subs; subs = next) { + next = subs->next; #ifdef DEBUG - zdbug ((LOG_DEBUG, "ck_frn_subs: %s/%s/%s", subs->dest.classname->string, + zdbug ((LOG_DEBUG, "realm_subs: %s/%s/%s", subs->dest.classname->string, subs->dest.inst->string, subs->dest.recip->string)); #endif - if (retval != ZERR_NONE) { - if (retval == ZSRV_CLASSXISTS) { - continue; - } else { - free_subscriptions(subs->next); - free(text); - return retval; + num = 0; + if ((retval = ZMakeAscii(port, sizeof(port), (unsigned char *) + &num, sizeof(u_short))) != ZERR_NONE) + { + syslog(LOG_ERR, "subscr_rlm_sendit make ascii: %s", + error_message(retval)); + return(ZERR_NONE); } - } - LIST_INSERT(&realm->subs, subs); - } - /* don't send confirmation if we're not the initial server contacted */ - if (!(server_which_server(who) || found == 0)) { - snotice = *notice; - snotice.z_opcode = REALM_ADD_SUBSCRIBE; + + text[0] = "0.0.0.0"; + text[1] = port; + text[2] = subs->dest.classname->string; + text[3] = subs->dest.inst->string; + text[4] = subs->dest.recip->string; + + /* format snotice */ snotice.z_class_inst = ZEPHYR_CTL_REALM; - snotice.z_port = srv_addr.sin_port; - if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_ck_forn_subs format: %s", - error_message(retval)); - free(text); - return(ZERR_NONE); - } + snotice.z_opcode = REALM_REQ_SUBSCRIBE; + snotice.z_port = 0; + snotice.z_class = ZEPHYR_CTL_CLASS; + + snotice.z_recipient = ""; + snotice.z_kind = ACKED; + snotice.z_num_other_fields = 0; + snotice.z_default_format = ""; + /* Evil. In the event this is ACL'd, pick a user who is subscribed and + resubmit them as the sender. */ + clientp = triplet_lookup(&subs->dest); + if (!clientp) + snotice.z_sender = ""; + else + snotice.z_sender = (*clientp)->principal->string; + snotice.z_default_format = ""; + + if ((retval = ZFormatNoticeList(&snotice, text, NUM_FIELDS + 2, + &pack, &packlen, ZNOAUTH)) != ZERR_NONE) + { + syslog(LOG_WARNING, "subscr_rlm_subs format: %s", + error_message(retval)); + return(ZERR_NONE); + } + if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) { - syslog(LOG_WARNING, "subscr_ck_forn_subs parse: %s", - error_message(retval)); - free(text); + syslog(LOG_WARNING, "subscr_rlm_subs parse: %s", + error_message(retval)); free(pack); return(ZERR_NONE); } - realm_handoff(&snotice, 1, who, realm, 0); + realm_handoff(&snotice, 1, NULL, realm, 0); free(pack); } - free(text); + return ZERR_NONE; } -Code_t subscr_foreign_user(notice, who, realm) +/* Called from subscr_foreign_user for REALM_REQ_SUBSCRIBE */ +static Code_t +subscr_check_foreign_subs(notice, who, server, realm, newsubs) + ZNotice_t *notice; + struct sockaddr_in *who; + Server *server; + Realm *realm; + Destlist *newsubs; +{ + Destlist *subs, *subs2, *next; + Acl *acl; + char **text; + int found = 0; + ZNotice_t snotice; + char *pack, *cp; + int packlen; + Code_t retval; + String *sender; + + for (subs = newsubs; subs; subs = subs->next) + found++; + + if (found == 0) + return(ZERR_NONE); + + sender = make_string(notice->z_sender, 0); + + if ((text = (char **)malloc((found * NUM_FIELDS + 2) * sizeof(char *))) + == (char **) 0) { + syslog(LOG_ERR, "subscr_ck_forn_subs no mem(text)"); + free_string(sender); + return(ENOMEM); + } + + /* grab the client information from the incoming message */ + cp = notice->z_message; + text[0] = cp; + + I_ADVANCE(2); + text[1] = cp; + + I_ADVANCE(3); + + found = 0; + for (subs = newsubs; subs; subs = next) { + next=subs->next; + acl = class_get_acl(subs->dest.classname); + if (acl) { + Realm *rlm; + rlm = realm_which_realm(who); + if (rlm && server == me_server) { + if (!realm_sender_in_realm(rlm->name, sender->string)) { + syslog(LOG_WARNING, "subscr auth not verifiable %s (%s) class %s", + sender->string, rlm->name, + subs->dest.classname->string); + continue; + } + } + if (!access_check(sender->string, acl, SUBSCRIBE)) { + syslog(LOG_WARNING, "subscr unauth %s class %s", + sender->string, subs->dest.classname->string); + continue; /* the for loop */ + } + if (wildcard_instance == subs->dest.inst) { + if (!access_check(sender->string, acl, INSTWILD)) { + syslog(LOG_WARNING, + "subscr unauth %s class %s wild inst", + sender->string, subs->dest.classname->string); + continue; + } + } + } + + /* okay to subscribe. save for return trip */ + text[found*NUM_FIELDS + 2] = subs->dest.classname->string; + text[found*NUM_FIELDS + 3] = subs->dest.inst->string; + text[found*NUM_FIELDS + 4] = ""; + found++; + + retval = triplet_register(realm->client, &subs->dest, realm); +#ifdef DEBUG + zdbug ((LOG_DEBUG, "ck_frn_subs: %s/%s/%s", subs->dest.classname->string, + subs->dest.inst->string, subs->dest.recip->string)); +#endif + + if (retval != ZERR_NONE) { + if (retval == ZSRV_CLASSXISTS) { + continue; + } else { + free_subscriptions(newsubs); /* subs->next XXX */ + free_string(sender); + free(text); + return retval; + } + } + LIST_INSERT(&realm->subs, subs); + } + /* don't send confirmation if we're not the initial server contacted */ + if (!(server_which_server(who) || found == 0)) { + snotice = *notice; + snotice.z_opcode = REALM_ADD_SUBSCRIBE; + snotice.z_class_inst = ZEPHYR_CTL_REALM; + snotice.z_port = srv_addr.sin_port; + if ((retval = ZFormatNoticeList(&snotice, text, found * NUM_FIELDS + 2, &pack, &packlen, ZNOAUTH)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_ck_forn_subs format: %s", + error_message(retval)); + free_string(sender); + free(text); + return(ZERR_NONE); + } + if ((retval = ZParseNotice(pack, packlen, &snotice)) != ZERR_NONE) { + syslog(LOG_WARNING, "subscr_ck_forn_subs parse: %s", + error_message(retval)); + free_string(sender); + free(text); + free(pack); + return(ZERR_NONE); + } + realm_handoff(&snotice, 1, who, realm, 0); + free(pack); + } + free_string(sender); + free(text); + return ZERR_NONE; +} + +/* Called from realm_control_dispatch for REALM_REQ/ADD_SUBSCRIBE */ +Code_t subscr_foreign_user(notice, who, server, realm) ZNotice_t *notice; struct sockaddr_in *who; + Server *server; Realm *realm; { Destlist *newsubs, *temp; @@ -1462,14 +1559,14 @@ Code_t subscr_foreign_user(notice, who, realm) Client *client; ZNotice_t snotice; struct sockaddr_in newwho; - char *cp; + char *cp, *tp0, *tp1; char rlm_recipient[REALM_SZ + 1]; #if 0 zdbug((LOG_DEBUG, "subscr_foreign_user")); #endif - cp = notice->z_message; + tp0 = cp = notice->z_message; newwho.sin_addr.s_addr = inet_addr(cp); if (newwho.sin_addr.s_addr == -1) { @@ -1478,6 +1575,7 @@ Code_t subscr_foreign_user(notice, who, realm) } I_ADVANCE(0); + tp1 = cp; snotice = *notice; @@ -1503,6 +1601,13 @@ Code_t subscr_foreign_user(notice, who, realm) if (!strcmp(snotice.z_opcode, REALM_ADD_SUBSCRIBE)) { /* this was approved by the other realm, add subscriptions */ + if (!strcmp(tp0, "0.0.0.0")) { + /* skip bogus ADD reply from subscr_realm_subs */ + zdbug((LOG_DEBUG, "subscr_foreign_user ADD skipped")); + return(ZERR_NONE); + } + + zdbug((LOG_DEBUG, "subscr_foreign_user ADD %s/%s", tp0, tp1)); client = client_find(&newwho.sin_addr, snotice.z_port); if (client == (Client *)0) { syslog(LOG_WARNING, "no client at %s/%d", @@ -1522,7 +1627,8 @@ Code_t subscr_foreign_user(notice, who, realm) status = subscr_add_raw(client, (Realm *)0, newsubs); } else if (!strcmp(snotice.z_opcode, REALM_REQ_SUBSCRIBE)) { - status = subscr_check_foreign_subs(notice, who, realm, newsubs); + zdbug((LOG_DEBUG, "subscr_foreign_user REQ %s/%s", tp0, tp1)); + status = subscr_check_foreign_subs(notice, who, server, realm, newsubs); } else { syslog(LOG_ERR, "bogus opcode %s in subscr_forn_user", snotice.z_opcode); diff --git a/server/uloc.c b/server/uloc.c index 4ab909a..0d7ea8e 100644 --- a/server/uloc.c +++ b/server/uloc.c @@ -869,7 +869,7 @@ ulogin_marshal_locs(notice, found, auth) char **answer; int i = 0; String *inst; - int local = (auth && sender_in_realm(notice)); + int local = (auth && realm_sender_in_realm(ZGetRealm(), notice->z_sender)); *found = 0; /* # of matches */ diff --git a/server/zserver.h b/server/zserver.h index c0b889a..dc84cf5 100644 --- a/server/zserver.h +++ b/server/zserver.h @@ -5,7 +5,9 @@ * * Created by: John T. Kohl * - * $Id$ + * $Source$ + * $Author$ + * $Zephyr: /mit/zephyr/src/server/RCS/zserver.h,v 1.34 91/03/08 12:53:24 raeburn Exp $ * * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology. * For copying and distribution information, see the file @@ -67,6 +69,7 @@ typedef struct _Destination Destination; typedef struct _Destlist Destlist; typedef struct _Realm Realm; typedef struct _Realmname Realmname; +typedef enum _Realm_state Realm_state; typedef struct _Client Client; typedef struct _Triplet Triplet; typedef enum _Server_state Server_state; @@ -87,14 +90,24 @@ struct _Destlist { struct _Destlist *next, **prev_p; }; +enum _Realm_state { + REALM_UP, /* Realm is up */ + REALM_TARDY, /* Realm due for a hello XXX */ + REALM_DEAD, /* Realm is considered dead */ + REALM_STARTING /* Realm is between dead and up */ +}; + struct _Realm { char name[REALM_SZ]; int count; struct sockaddr_in *addrs; int idx; /* which server we are connected to */ - Destlist *subs; - Client *client; - long tkt_try; + Destlist *subs; /* what their clients sub to */ + Destlist *remsubs; /* our subs on their end */ + Client *client; + int child_pid; + int have_tkt; + Realm_state state; }; struct _Realmname { @@ -284,8 +297,9 @@ Code_t server_adispatch __P((ZNotice_t *notice, int auth, struct sockaddr_in *who, Server *server)); /* found in subscr.c */ +Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, Realm *)); Code_t subscr_cancel __P((struct sockaddr_in *sin, ZNotice_t *notice)); -Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice)); +Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice, Server *server)); Code_t subscr_send_subs __P((Client *client)); void subscr_cancel_client __P((Client *client)); void subscr_sendlist __P((ZNotice_t *notice, int auth, @@ -305,8 +319,11 @@ Code_t ulocate_dispatch __P((ZNotice_t *notice, int auth, Code_t uloc_send_locations __P((void)); /* found in realm.c */ +int realm_sender_in_realm __P((char *realm, char *sender)); +int realm_bound_for_realm __P((char *realm, char *recip)); Realm *realm_which_realm __P((struct sockaddr_in *who)); Realm *realm_get_realm_by_name __P((char *name)); +Realm *realm_get_realm_by_pid __P((int)); void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, Realm *, int); char *realm_expand_realm(char *); void realm_init __P((void)); @@ -314,6 +331,8 @@ Code_t ZCheckRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *, char *)); Code_t realm_control_dispatch __P((ZNotice_t *, int, struct sockaddr_in *, Server *, Realm *)); +void realm_shutdown __P((void)); +void realm_deathgram __P((Server *)); /* found in version.c */ char *get_version __P((void)); @@ -368,6 +387,9 @@ extern int nservers; /* number of other servers*/ extern String *empty; extern String *wildcard_instance; +extern Realm *otherrealms; +extern int nrealms; + extern struct in_addr my_addr; /* my inet address */ #define class_is_control(classname) (classname == class_control) @@ -389,6 +411,7 @@ extern struct in_addr my_addr; /* my inet address */ #define ADMIN_NEWREALM "NEXT_REALM" /* Opcode: this is a new realm */ #define REALM_REQ_LOCATE "REQ_LOCATE" /* Opcode: request a location */ #define REALM_ANS_LOCATE "ANS_LOCATE" /* Opcode: answer to location */ +#define REALM_BOOT "SENDSUBS" /* Opcode: first server in realm */ /* me_server_idx is the index into otherservers of this server descriptor. */ /* the 'limbo' server is always the first server */ diff --git a/zhm/zhm.h b/zhm/zhm.h index 733d9cc..3d6f153 100644 --- a/zhm/zhm.h +++ b/zhm/zhm.h @@ -44,7 +44,6 @@ #define ever (;;) -#define SERV_TIMEOUT 5 #define BOOTING 1 #define NOTICES 2 diff --git a/zhm/zhm_server.c b/zhm/zhm_server.c index 4630955..50fa04f 100644 --- a/zhm/zhm_server.c +++ b/zhm/zhm_server.c @@ -19,8 +19,11 @@ static char rcsid_hm_server_c[] = "$Id$"; #endif /* lint */ static void boot_timeout __P((void *)); +static int get_serv_timeout __P((void)); static Timer *boot_timer = NULL; +static int serv_rexmit_times[] = { 5, 10, 20, 40 }; +static int serv_timeouts = 0; int serv_loop = 0; extern u_short cli_port; @@ -64,7 +67,7 @@ char *op; Zperr(ret); com_err("hm", ret, "sending startup notice"); } - boot_timer = timer_set_rel(SERV_TIMEOUT, boot_timeout, NULL); + boot_timer = timer_set_rel(get_serv_timeout(), boot_timeout, NULL); } /* Argument is whether we are detaching or really going down */ @@ -182,6 +185,7 @@ ZNotice_t *notice; } else { /* This is our server, handle the notice */ booting = 0; + serv_timeouts = 0; if (boot_timer) { timer_reset(boot_timer); boot_timer = NULL; @@ -305,6 +309,17 @@ char *sugg_serv; static void boot_timeout(arg) void *arg; { + serv_timeouts++; new_server(NULL); } +static int get_serv_timeout(void) +{ + int ind, ntimeouts; + + ind = (numserv == 0) ? serv_timeouts : serv_timeouts / numserv; + ntimeouts = sizeof(serv_rexmit_times) / sizeof(*serv_rexmit_times); + if (ind >= ntimeouts) + ind = ntimeouts - 1; + return serv_rexmit_times[ind]; +} diff --git a/zwgc/zephyr.c b/zwgc/zephyr.c index c5a3855..c3276e5 100644 --- a/zwgc/zephyr.c +++ b/zwgc/zephyr.c @@ -165,7 +165,7 @@ void zephyr_init(notice_handler) exposure = EXPOSE_NONE; } } else - exposure = EXPOSE_NONE; + exposure = EXPOSE_OPSTAFF; error_code = ZSetLocation(exposure); /* <<<>>> */ if (error_code != ZERR_LOGINFAIL) TRAP( error_code, "while setting location" ); @@ -218,12 +218,12 @@ void finalize_zephyr() /* <<<>>> */ */ #ifdef DEBUG if (zwgc_debug) { - TRAP( ZCancelSubscriptions(0), "while canceling subscriptions" ); TRAP( ZUnsetLocation(), "while unsetting location" ); + TRAP( ZCancelSubscriptions(0), "while canceling subscriptions" ); } else { #endif /* DEBUG */ - (void) ZCancelSubscriptions(0); (void) ZUnsetLocation(); + (void) ZCancelSubscriptions(0); #ifdef DEBUG } #endif /* DEBUG */ diff --git a/zwgc/zwgc.1 b/zwgc/zwgc.1 index f646bec..879b240 100644 --- a/zwgc/zwgc.1 +++ b/zwgc/zwgc.1 @@ -1001,9 +1001,9 @@ Other control messages may be implemented in the future. .SH EXAMPLES For an example of a description file, see -.IR /usr/athena/lib/zephyr/zwgc.desc . +.IR /usr/athena/share/zephyr/zwgc.desc . For an example of X resources, see -.IR /usr/athena/lib/zephyr/zwgc_resources . +.IR /usr/athena/share/zephyr/zwgc_resources . .SH BUGS The X selection code can highlight the wrong portions of messages @@ -1022,10 +1022,10 @@ which case you must get new tickets and then run ``zctl load $HOME/.zwgc.desc Default location of user's description file .TQ -/usr/athena/lib/zephyr/zwgc.desc +/usr/athena/share/zephyr/zwgc.desc System-wide description file .TQ -/usr/athena/lib/zephyr/zwgc_resources +/usr/athena/share/zephyr/zwgc_resources Default X application resources. .TQ $HOME/.zephyr.vars diff --git a/zwgc/zwgc.desc b/zwgc/zwgc.desc index 71dfc1e..90a5666 100644 --- a/zwgc/zwgc.desc +++ b/zwgc/zwgc.desc @@ -41,109 +41,95 @@ if (upcase($opcode) == "PING") then exit endif # 'match "forged" to something other than "UNAUTHENTIC". case $auth match "yes" - set aval = "Authentic" + set aval = "Authentic" match "no","forged" - set aval = "@b(@large(UNAUTHENTIC))" + set aval = "@b(@large(UNAUTHENTIC))" endcase case $class match "WG_CTL_CLASS" - exit -# -# MAIL NOTIFICATION -# -# To receive mail notifications, you need to do several things: -# 1) subscribe to MAIL,POP messages. You do this by typing: -# zctl add mail pop -# to your prompt. By doing this, you will get a simple notice every -# time you are logged in and more mail arrives for you at your post office. -# -# 2) If you wish to be notified of the sender, recipient and subject of the -# new mail, remove the pound-signs from the beginning of the 10 lines below -# between 'match "MAIL"' and 'exit', inclusive, and type the command -# zctl add mail popret -# to your prompt. -# -# Note: The use of the following lines is NOT necessary to receive -# notifications of new mail. The only effect of uncommenting these -# lines is to display on your screen the sender, recipient and subject -# of the mail (In addition, uncommenting these lines will add extra load -# to the post office servers, making them run slower.). -# If you do not wish this information to be displayed where other users -# might possibly read it, or you wish to avoid loading down the post -# office servers, you need not uncomment these lines. Just follow step -# 1 above. -# -#match "MAIL" -# case $instance -# match "pop" -# exec "zmailnotify" -# exit -# endcase -# print "(Authentication: @bold("+$aval+"))\n" -# print substitute($default) -# put -# exit + exit match "message" - if (downcase($recipient) == downcase($user)) then - case $instance - match "PERSONAL" - set type = "Personal" - match "URGENT" - set type = "Urgent" - default - set type = $instance - endcase - else - set type = "Instance "+$instance - endif + if (downcase($recipient) == downcase($user)) then + case $instance + match "PERSONAL" + set type = "Personal" + match "URGENT" + set type = "Urgent" + default + set type = $instance + endcase + else + set type = "Instance "+$instance + endif - fields signature body - if ($body == "") then - set body = $signature - set signature = "" - endif - if ($signature =~ "^[Ff]rom: .*") then - set dummy = lany($signature,"From: ") - endif - if ($signature =~ "\n$") then - set dummy = rany($signature,"\n") - endif - if ($signature == "") then - set ftext = "From: @bold("+protect($sender)+")" - else - set ftext = "From: @bold(@{"+protect($signature)+"} <"+ - protect($sender)+">)" - endif + fields signature body + if ($body == "") then + set body = $signature + set signature = "" + endif + if ($signature =~ "^[Ff]rom: .*") then + set dummy = lany($signature,"From: ") + endif + if ($signature =~ "\n$") then + set dummy = rany($signature,"\n") + endif + if ($signature == "") then + set ftext = "From: @bold("+protect($sender)+")" + else + set ftext = "From: @bold(@{"+protect($signature)+"} <"+ + protect($sender)+">)" + endif - print "@center(@bold("+$aval+") "+$type+" message at "+$time+ - " on "+$date+"\n"+$ftext+" on "+$fromhost+"\nTo: "+ - $recipient+")\n\n" - print $body - put - exit + print "@center(@bold("+$aval+") "+$type+" message at "+$time+ + " on "+$date+"\n"+$ftext+" on "+$fromhost+"\nTo: "+ + $recipient+")\n\n" + print $body + put + exit match "login" - case $opcode - match "USER_LOGIN" - set log = "logged in" - match "USER_LOGOUT" - set log = "logged out" - default - set log = "unknown opcode" - endcase + case $opcode + match "USER_LOGIN" + set log = "logged in" + match "USER_LOGOUT" + set log = "logged out" + default + set log = "unknown opcode" + endcase - fields host when tty - print "@center(@bold("+$sender+") "+$log+")\n" - print "@center(on @bold("+$host+") on "+$tty+")\n" - print "@center(at "+$when+")" - put - exit + fields host when tty + print "@center(@bold("+$sender+") "+$log+")\n" + print "@center(on @bold("+$host+") on "+$tty+")\n" + print "@center(at "+$when+")" + put + exit default - print "(Authentication: @bold("+$aval+") from host: "+$fromhost+")\n" - print substitute($default) - put - exit + if (downcase($class) == "filsys" and downcase($opcode) == "shutdown") then + set format = "From $sender:\n@bold(Shutdown message from $1 at $time)\n"+ + "@center(System going down, message is:)\n\n$2\n\n@center(@bold($3))" + elseif (downcase($class) == "filsys") then + set format = "@bold(Filesystem Operation Message for $instance:)\n"+ + "From: @bold($sender) at $time $date\n$message" + elseif (downcase($class) == "mail" and downcase($instance) == "popret") then + set format = "You have new mail:\n\nFrom: $1\nTo: $2\nSubject: $3" + elseif (downcase($class) == "mail") then + set format = "From Post Office $1:\n$2" + elseif (downcase($class) == "syslog") then + set format = "From $sender:\nSyslog message from $instance, level "+ + "$opcode:\n$message" + elseif ($number_of_fields == "1") then + set format = "Class $class, Instance $instance:\nTo: @bold($recipient) "+ + "at $time $date\nFrom: @bold($sender)\n\n$message" + else + set format = "Class $class, Instance $instance:\nTo: @bold($recipient) "+ + "at $time $date\nFrom: @bold($1) <$sender>\n\n$2" + endif + + print "(Authentication: @bold("+$aval+") from host: "+$fromhost+")\n" + print substitute($format) + put + exit endcase -- cgit v1.2.3