*
* Created by: John T. Kohl
*
- * $Id: subscr.c,v 1.56 1999/01/22 23:19:48 ghudson Exp $
+ * $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/subscr.c,v $
+ * $Author$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
#ifndef lint
#ifndef SABER
-static const char rcsid_subscr_c[] = "$Id: subscr.c,v 1.56 1999/01/22 23:19:48 ghudson Exp $";
+static const char rcsid_subscr_c[] = "$Id$";
#endif
#endif
#ifdef OLD_COMPAT
#define OLD_ZEPHYR_VERSION "ZEPH0.0"
#define OLD_CLIENT_INCOMPSUBS "INCOMP"
-static void old_compat_subscr_sendlist __P((ZNotice_t *notice, int auth,
- struct sockaddr_in *who));
+static void old_compat_subscr_sendlist(ZNotice_t *notice, int auth,
+ struct sockaddr_in *who);
extern int old_compat_count_subscr; /* counter of old use */
#endif /* OLD_COMPAT */
#ifdef NEW_COMPAT
#define NEW_OLD_ZEPHYR_VERSION "ZEPH0.1"
-static void new_old_compat_subscr_sendlist __P((ZNotice_t *notice, int auth,
- struct sockaddr_in *who));
+static void new_old_compat_subscr_sendlist(ZNotice_t *notice, int auth,
+ struct sockaddr_in *who);
extern int new_compat_count_subscr; /* counter of old use */
#endif /* NEW_COMPAT */
-extern char *re_comp(), *re_conv();
-static Code_t add_subscriptions __P((Client *who, Destlist *subs_queue,
- ZNotice_t *notice));
-static Destlist *extract_subscriptions __P((ZNotice_t *notice));
-static void free_subscriptions __P((Destlist *subs));
-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 int cl_match __P((Destlist*, Client *));
+static Code_t add_subscriptions(Client *who, Destlist *subs_queue,
+ ZNotice_t *notice, Server *server);
+static Destlist *extract_subscriptions(ZNotice_t *notice);
+static void free_subscriptions(Destlist *subs);
+static void free_subscription(Destlist *sub);
+static char **subscr_marshal_subs(ZNotice_t *notice, int auth,
+ struct sockaddr_in *who,
+ int *found);
+static Destlist *subscr_copy_def_subs(char *person);
+static Code_t subscr_realm_sendit(Client *who, Destlist *subs,
+ ZNotice_t *notice, ZRealm *realm);
+static void subscr_unsub_realms(Destlist *newsubs);
+static void subscr_unsub_sendit(Client *who, Destlist *subs,
+ ZRealm *realm);
+static int cl_match (Destlist*, Client *);
static int defaults_read = 0; /* set to 1 if the default subs
are in memory */
*/
Code_t
-subscr_subscribe(who, notice)
- Client *who;
- ZNotice_t *notice;
+subscr_subscribe(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)
- Client *who;
- Destlist *subs;
- ZNotice_t *notice;
+add_subscriptions(Client *who,
+ Destlist *subs,
+ ZNotice_t *notice,
+ Server *server)
{
Destlist *next;
Code_t retval;
Acl *acl;
String *sender;
- Realm *realm = NULL;
+ ZRealm *realm = NULL;
if (!subs)
return ZERR_NONE; /* no subscr -> no error */
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) {
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) {
- retval = subscr_realm_sendit(who, subs, notice, realm);
- if (retval != ZERR_NONE) {
- free(subs);
- return(retval);
- }
- }
- retval = triplet_register(who, &subs->dest, realm);
- if (retval != ZERR_NONE) {
- free(subs);
- if (retval == ZSRV_CLASSXISTS) {
- continue;
+ if (realm && !bdumping) {
+ retval = subscr_realm_sendit(who, subs, notice, realm);
+ if (retval != ZERR_NONE) {
+ free_subscription(subs);
+ continue; /* the for loop */
} else {
- free_subscriptions(next);
- return retval;
+ /* Indicates we leaked traffic back to our realm */
+ free_subscription(subs); /* free this one, wil 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;
}
*/
Code_t
-subscr_def_subs(who)
- Client *who;
+subscr_def_subs(Client *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
-subscr_reset()
+subscr_reset(void)
{
#if 0
zdbug((LOG_DEBUG, "subscr_reset()"));
}
static Destlist *
-subscr_copy_def_subs(person)
- char *person;
+subscr_copy_def_subs(char *person)
{
int retval, fd;
struct stat statbuf;
*/
Code_t
-subscr_cancel(sin, notice)
- struct sockaddr_in *sin;
- ZNotice_t *notice;
+subscr_cancel(struct sockaddr_in *sin,
+ ZNotice_t *notice)
{
- Realm *realm;
+ ZRealm *realm;
Client *who;
Destlist *cancel_subs, *subs, *cancel_next, *client_subs, *client_next;
Code_t retval;
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;
}
}
Code_t
-subscr_realm_cancel(sin, notice, realm)
- struct sockaddr_in *sin;
- ZNotice_t *notice;
- Realm *realm;
+subscr_realm_cancel(struct sockaddr_in *sin,
+ ZNotice_t *notice,
+ ZRealm *realm)
{
Client *who;
Destlist *cancel_subs, *subs, *client_subs, *next, *next2;
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;
}
*/
void
-subscr_cancel_client(client)
- Client *client;
+subscr_cancel_client(Client *client)
{
Destlist *subs, *next;
Code_t retval;
- Realm *realm;
+ ZRealm *realm;
#if 0
zdbug((LOG_DEBUG,"subscr_cancel_client %s",
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;
*/
void
-subscr_sendlist(notice, auth, who)
- ZNotice_t *notice;
- int auth;
- struct sockaddr_in *who;
+subscr_sendlist(ZNotice_t *notice,
+ int auth,
+ struct sockaddr_in *who)
{
char **answer;
int found;
}
static char **
-subscr_marshal_subs(notice, auth, who, found)
- ZNotice_t *notice;
- int auth;
- struct sockaddr_in *who;
- int *found;
+subscr_marshal_subs(ZNotice_t *notice,
+ int auth,
+ struct sockaddr_in *who,
+ int *found)
{
char **answer = NULL;
unsigned short temp;
zdbug((LOG_DEBUG, "subscr_marshal"));
#endif
*found = 0;
-
+
/* Note that the following code is an incredible crock! */
/* We cannot send multiple packets as acknowledgements to the client,
/*ARGSUSED*/
Code_t
-subscr_send_subs(client)
- Client *client;
+subscr_send_subs(Client *client)
{
int i = 0;
Destlist *subs;
+#ifdef HAVE_KRB5
+ char buf[512];
+ char *bufp;
+#else
#ifdef HAVE_KRB4
char buf[512];
C_Block cblock;
#endif /* HAVE_KRB4 */
+#endif
char buf2[512];
char *list[7 * NUM_FIELDS];
int num = 0;
list[num++] = buf2;
+#ifdef HAVE_KRB5
+#ifdef HAVE_KRB4 /* XXX make this optional for server transition time */
+ if (Z_enctype(client->session_keyblock) == ENCTYPE_DES_CBC_CRC) {
+ bufp = malloc(Z_keylen(client->session_keyblock));
+ if (bufp == NULL) {
+ syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for DES keyblock: %m");
+ return errno;
+ }
+ des_ecb_encrypt(Z_keydata(client->session_keyblock), bufp, serv_ksched.s, DES_ENCRYPT);
+ retval = ZMakeAscii(buf, sizeof(buf), bufp, Z_keylen(client->session_keyblock));
+ } else {
+#endif
+ bufp = malloc(Z_keylen(client->session_keyblock) + 8); /* + enctype
+ + length */
+ if (bufp == NULL) {
+ syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for keyblock: %m");
+ return errno;
+ }
+ *(krb5_enctype *)&bufp[0] = htonl(Z_enctype(client->session_keyblock));
+ *(u_int32_t *)&bufp[4] = htonl(Z_keylen(client->session_keyblock));
+ memcpy(&bufp[8], Z_keydata(client->session_keyblock), Z_keylen(client->session_keyblock));
+
+ retval = ZMakeZcode(buf, sizeof(buf), bufp, Z_keylen(client->session_keyblock) + 8);
+#ifdef HAVE_KRB4
+ }
+#endif /* HAVE_KRB4 */
+#else /* HAVE_KRB5 */
#ifdef HAVE_KRB4
#ifdef NOENCRYPTION
memcpy(cblock, client->session_key, sizeof(C_Block));
-#else
+#else /* NOENCRYPTION */
des_ecb_encrypt(client->session_key, cblock, serv_ksched.s, DES_ENCRYPT);
-#endif
+#endif /* NOENCRYPTION */
retval = ZMakeAscii(buf, sizeof(buf), cblock, sizeof(C_Block));
+#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
+
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
if (retval != ZERR_NONE) {
#if 0
zdbug((LOG_DEBUG,"zmakeascii failed: %s", error_message(retval)));
zdbug((LOG_DEBUG, "cblock %s", buf));
#endif
}
-#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB4 || HAVE_KRB5*/
retval = bdump_send_list_tcp(SERVACK, &client->addr, ZEPHYR_ADMIN_CLASS,
num > 1 ? "CBLOCK" : "", ADMIN_NEWCLT,
client->principal->string, "", list, num);
* free the memory allocated for the list of subscriptions.
*/
+/*
+ * free the memory allocated for one subscription.
+ */
+
static void
-free_subscriptions(subs)
- Destlist *subs;
+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(Destlist *subs)
{
Destlist *next;
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);
}
}
*/
static Destlist *
-extract_subscriptions(notice)
- ZNotice_t *notice;
+extract_subscriptions(ZNotice_t *notice)
{
Destlist *subs = NULL, *sub;
char *recip, *class_name, *classinst;
*/
void
-subscr_dump_subs(fp, subs)
- FILE *fp;
- Destlist *subs;
+subscr_dump_subs(FILE *fp,
+ Destlist *subs)
{
char *p;
/* As it exists, this function expects to take only the first sub from the
* Destlist. At some point, it and the calling code should be replaced */
static Code_t
-subscr_realm_sendit(who, subs, notice, realm)
- Client *who;
- Destlist *subs;
- ZNotice_t *notice;
- Realm *realm;
+subscr_realm_sendit(Client *who,
+ Destlist *subs,
+ ZNotice_t *notice,
+ ZRealm *realm)
{
-#if 0
- Destlist *subs2;
-#endif
ZNotice_t snotice;
char *pack;
int packlen;
#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));
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;
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));
return(ZERR_NONE);
}
+/* Called from subscr_realm and subscr_foreign_user */
static Code_t
-subscr_add_raw(client, realm, newsubs)
- Client *client;
- Realm *realm;
- Destlist *newsubs;
+subscr_add_raw(Client *client,
+ ZRealm *realm,
+ Destlist *newsubs)
{
Destlist *subs, *subs2, *subs3, **head;
Code_t retval;
#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) {
+ ZRealm *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);
return ZERR_NONE;
}
+/* Called from bdump_recv_loop to decapsulate realm subs */
Code_t
-subscr_realm(realm, notice)
- Realm *realm;
- ZNotice_t *notice;
+subscr_realm(ZRealm *realm,
+ ZNotice_t *notice)
{
Destlist *newsubs;
/* Like realm_sendit, this only takes one item from subs */
static void
-subscr_unsub_sendit(subs, realm)
- Destlist *subs;
- Realm *realm;
+subscr_unsub_sendit(Client *who,
+ Destlist *subs,
+ ZRealm *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;
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",
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;
+subscr_send_realm_subs(ZRealm *realm)
{
int i = 0;
Destlist *subs, *next;
return ZERR_NONE;
}
-static Code_t
-subscr_check_foreign_subs(notice, who, realm, newsubs)
- ZNotice_t *notice;
- struct sockaddr_in *who;
- Realm *realm;
- Destlist *newsubs;
+Code_t
+subscr_realm_subs(ZRealm *realm)
{
- 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)
- ZNotice_t *notice;
- struct sockaddr_in *who;
- Realm *realm;
+/* Called from subscr_foreign_user for REALM_REQ_SUBSCRIBE */
+static Code_t
+subscr_check_foreign_subs(ZNotice_t *notice,
+ struct sockaddr_in *who,
+ Server *server,
+ ZRealm *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) {
+ ZRealm *rlm;
+ next=subs->next;
+ if (subs->dest.recip->string[0] != '\0') {
+ rlm = realm_which_realm(who);
+ syslog(LOG_WARNING, "subscr bad recip %s by %s (%s)",
+ subs->dest.recip->string,
+ sender->string, rlm->name);
+ continue;
+ }
+ acl = class_get_acl(subs->dest.classname);
+ if (acl) {
+ 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);
+ free_subscriptions(newsubs);
+ free_string(sender);
+ free(text);
+ return ZSRV_CLASSRESTRICTED;
+ }
+ }
+ 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(ZNotice_t *notice,
+ struct sockaddr_in *who,
+ Server *server,
+ ZRealm *realm)
{
Destlist *newsubs, *temp;
Acl *acl;
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) {
}
I_ADVANCE(0);
+ tp1 = cp;
snotice = *notice;
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",
temp->dest.recip = make_string(rlm_recipient, 0);
}
- status = subscr_add_raw(client, (Realm *)0, newsubs);
+ status = subscr_add_raw(client, (ZRealm *)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);