adding zephyr-im master branch

This commit is contained in:
2022-07-25 09:01:27 -06:00
parent 61f5ed8f01
commit ee1236fa5c
311 changed files with 62265 additions and 0 deletions

81
lib/Makefile.in Normal file
View File

@ -0,0 +1,81 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
top_builddir=..
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
LIBS=@LIBS@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
RANLIB=@RANLIB@
DEBUG=-O
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@ ${DEBUG}
ALL_CFLAGS=${CFLAGS} -DSYSCONFDIR=\"${sysconfdir}\" -I${top_srcdir}/h \
-I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=@LIBZEPHYR_LIBS@ -lcom_err @LIBICONV@
OBJS = zephyr_err.lo ZAsyncLocate.lo ZCkAuth.lo ZCkIfNot.lo ZClosePort.lo \
ZCmpUID.lo ZCmpUIDP.lo ZFlsLocs.lo ZFlsSubs.lo ZFmtAuth.lo \
ZFmtList.lo ZFmtNotice.lo ZFmtRaw.lo ZFmtRawLst.lo ZFmtSmRLst.lo \
ZFmtSmRaw.lo ZFreeNot.lo ZGetLocs.lo ZGetSender.lo ZGetSubs.lo \
ZGetWGPort.lo ZhmStat.lo ZIfNotice.lo ZInit.lo ZLocations.lo \
ZMakeAscii.lo ZMkAuth.lo ZNewLocU.lo ZOpenPort.lo ZParseNot.lo \
ZPeekIfNot.lo ZPeekNot.lo ZPeekPkt.lo ZPending.lo ZReadAscii.lo \
ZRecvNot.lo ZRecvPkt.lo ZRetSubs.lo ZSendList.lo ZSendNot.lo \
ZSendPkt.lo ZSendRaw.lo ZSendRLst.lo ZSetDest.lo ZSetFD.lo ZSetSrv.lo \
ZSubs.lo ZVariables.lo ZWait4Not.lo Zinternal.lo ZMakeZcode.lo \
ZReadZcode.lo ZCkZAut.lo quad_cksum.lo charset.lo ZExpnRlm.lo \
ZDumpSession.lo
.SUFFIXES: .lo
all: libzephyr.la
libzephyr.la: ${OBJS}
${LIBTOOL} --mode=link ${CC} -rpath ${libdir} -version-info 4:0:0 \
${LDFLAGS} -o $@ ${OBJS} ${LIBS}
${BUILDTOP}/h/zephyr/zephyr_err.h: zephyr_err.c
zephyr_err.c: zephyr_err.et
compile_et ${srcdir}/zephyr_err.et
cp -f zephyr_err.h ${BUILDTOP}/h/zephyr
.c.lo:
${LIBTOOL} --mode=compile ${CC} -c -o $@ ${ALL_CFLAGS} $<
check:
PYTHONPATH=${top_srcdir}/python python $(srcdir)/zephyr_tests.py --builddir=$(BUILDTOP)
PYTHONPATH=${top_srcdir}/python $(srcdir)/zephyr_run_doctests --builddir=$(BUILDTOP)
install: libzephyr.la
${LIBTOOL} --mode=install ${INSTALL} -m 644 libzephyr.la \
${DESTDIR}${libdir}
${INSTALL} -m 644 ${srcdir}/zephyr.1 ${DESTDIR}${mandir}/man1
clean:
rm -f zephyr_err.c zephyr_err.h
${LIBTOOL} --mode=clean rm -f ${OBJS} libzephyr.la
${OBJS}: ${top_srcdir}/h/internal.h ${top_srcdir}/h/sysdep.h
${OBJS}: ${BUILDTOP}/h/config.h ${BUILDTOP}/h/zephyr/zephyr.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

168
lib/ZAsyncLocate.c Normal file
View File

@ -0,0 +1,168 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for asynchronous location functions.
*
* Created by: Marc Horowitz
*
* $Id$
*
* Copyright (c) 1990,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZAsyncLocate_c[] = "$Id$";
#endif
Code_t
ZRequestLocations(char *user,
register ZAsyncLocateData_t *zald,
ZNotice_Kind_t kind, /* UNSAFE, UNACKED, or ACKED */
Z_AuthProc auth)
{
int retval;
ZNotice_t notice;
if (ZGetFD() < 0)
if ((retval = ZOpenPort((u_short *)0)) != ZERR_NONE)
return (retval);
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = kind;
notice.z_port = __Zephyr_port;
notice.z_class = LOCATE_CLASS;
notice.z_class_inst = user;
notice.z_opcode = LOCATE_LOCATE;
notice.z_sender = 0;
notice.z_recipient = "";
notice.z_default_format = "";
notice.z_message_len = 0;
if ((retval = ZSendNotice(&notice, auth)) != ZERR_NONE)
return(retval);
if ((zald->user = (char *) malloc(strlen(user)+1)) == NULL) {
return(ENOMEM);
}
if ((zald->version = (char *) malloc(strlen(notice.z_version)+1)) == NULL) {
free(zald->user);
return(ENOMEM);
}
zald->uid = notice.z_multiuid;
strcpy(zald->user,user);
strcpy(zald->version,notice.z_version);
return(ZERR_NONE);
}
Code_t
ZParseLocations(register ZNotice_t *notice,
register ZAsyncLocateData_t *zald,
int *nlocs,
char **user)
{
char *ptr, *end;
int i;
ZFlushLocations(); /* This never fails (this function is part of the
library, so it is allowed to know this). */
/* non-matching protocol version numbers means the
server is probably an older version--must punt */
if (zald && strcmp(notice->z_version, zald->version))
return(ZERR_VERS);
if (notice->z_kind == SERVNAK)
return (ZERR_SERVNAK);
/* flag ACKs as special */
if (notice->z_kind == SERVACK &&
!strcmp(notice->z_opcode, LOCATE_LOCATE)) {
*nlocs = -1;
return(ZERR_NONE);
}
if (notice->z_kind != ACKED)
return (ZERR_INTERNAL);
end = notice->z_message+notice->z_message_len;
__locate_num = 0;
for (ptr=notice->z_message;ptr<end;ptr++)
if (!*ptr)
__locate_num++;
__locate_num /= 3;
if (__locate_num)
{
__locate_list = (ZLocations_t *)malloc((unsigned)__locate_num*
sizeof(ZLocations_t));
if (!__locate_list)
return (ENOMEM);
} else {
__locate_list = 0;
}
for (ptr=notice->z_message, i=0; i<__locate_num; i++) {
unsigned int len;
len = strlen (ptr) + 1;
__locate_list[i].host = (char *) malloc(len);
if (!__locate_list[i].host)
return (ENOMEM);
(void) strcpy(__locate_list[i].host, ptr);
ptr += len;
len = strlen (ptr) + 1;
__locate_list[i].time = (char *) malloc(len);
if (!__locate_list[i].time)
return (ENOMEM);
(void) strcpy(__locate_list[i].time, ptr);
ptr += len;
len = strlen (ptr) + 1;
__locate_list[i].tty = (char *) malloc(len);
if (!__locate_list[i].tty)
return (ENOMEM);
(void) strcpy(__locate_list[i].tty, ptr);
ptr += len;
}
__locate_next = 0;
*nlocs = __locate_num;
if (user) {
if (zald) {
if ((*user = (char *) malloc(strlen(zald->user)+1)) == NULL)
return(ENOMEM);
strcpy(*user,zald->user);
} else {
if ((*user = (char *) malloc(strlen(notice->z_class_inst)+1)) == NULL)
return(ENOMEM);
strcpy(*user,notice->z_class_inst);
}
}
return (ZERR_NONE);
}
int
ZCompareALDPred(ZNotice_t *notice,
void *zald)
{
return(ZCompareUID(&(notice->z_multiuid),
&(((ZAsyncLocateData_t *) zald)->uid)));
}
void
ZFreeALD(register ZAsyncLocateData_t *zald)
{
if (!zald) return;
if (zald->user) free(zald->user);
if (zald->version) free(zald->version);
(void) memset(zald, 0, sizeof(*zald));
}

67
lib/ZCkAuth.c Normal file
View File

@ -0,0 +1,67 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZCheckAuthentication function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZCheckAuthentication_c[] =
"$Id$";
#endif
#include <internal.h>
#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
#define krb5_free_data(ctx, dat) free((dat)->data)
#endif
/* Check authentication of the notice.
If it looks authentic but fails the Kerberos check, return -1.
If it looks authentic and passes the Kerberos check, return 1.
If it doesn't look authentic, return 0
When not using Kerberos, return true if the notice claims to be authentic.
Only used by clients; the server uses its own routine.
*/
Code_t
ZCheckAuthentication(ZNotice_t *notice,
struct sockaddr_in *from)
{
#if defined(HAVE_KRB4) && !defined(HAVE_KRB5)
int result;
ZChecksum_t our_checksum;
C_Block *session;
CREDENTIALS cred;
/* If the value is already known, return it. */
if (notice->z_checked_auth != ZAUTH_UNSET)
return (notice->z_checked_auth);
if (!notice->z_auth)
return (ZAUTH_NO);
if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
__Zephyr_realm, &cred)) != 0)
return (ZAUTH_NO);
session = (C_Block *)cred.session;
our_checksum = des_quad_cksum((unsigned char *)notice->z_packet,
NULL,
notice->z_default_format+
strlen(notice->z_default_format) + 1
- notice->z_packet,
0, session);
/* if mismatched checksum, then the packet was corrupted */
return ((our_checksum == notice->z_checksum) ? ZAUTH_YES : ZAUTH_FAILED);
#else
return ZCheckZcodeAuthentication(notice, from);
#endif
}

57
lib/ZCkIfNot.c Normal file
View File

@ -0,0 +1,57 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZCheckIfNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZCheckIfNotice_c[] = "$Id$";
#endif
Code_t
ZCheckIfNotice(ZNotice_t *notice,
struct sockaddr_in *from,
register int (*predicate)(ZNotice_t *, void *),
void *args)
{
ZNotice_t tmpnotice;
Code_t retval;
register char *buffer;
register struct _Z_InputQ *qptr;
if ((retval = Z_ReadEnqueue()) != ZERR_NONE)
return (retval);
qptr = Z_GetFirstComplete();
while (qptr) {
if ((retval = ZParseNotice(qptr->packet, qptr->packet_len,
&tmpnotice)) != ZERR_NONE)
return (retval);
if ((*predicate)(&tmpnotice, args)) {
if (!(buffer = (char *) malloc((unsigned) qptr->packet_len)))
return (ENOMEM);
(void) memcpy(buffer, qptr->packet, qptr->packet_len);
if (from)
*from = qptr->from;
if ((retval = ZParseNotice(buffer, qptr->packet_len,
notice)) != ZERR_NONE) {
free(buffer);
return (retval);
}
Z_RemQueue(qptr);
return (ZERR_NONE);
}
qptr = Z_GetNextComplete(qptr);
}
return (ZERR_NONOTICE);
}

232
lib/ZCkZAut.c Normal file
View File

@ -0,0 +1,232 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZCheckAuthentication function.
*
* Created by: Robert French
*
* $Source$
* $Author$
*
* Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
/* $Header$ */
#ifndef lint
static const char rcsid_ZCheckAuthentication_c[] =
"$Id$";
#endif
#include <internal.h>
#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
#define krb5_free_data(ctx, dat) free((dat)->data)
#endif
/* Check authentication of the notice.
If it looks authentic but fails the Kerberos check, return -1.
If it looks authentic and passes the Kerberos check, return 1.
If it doesn't look authentic, return 0
When not using Kerberos, return true if the notice claims to be authentic.
Only used by clients; the server uses its own routine.
*/
#ifdef HAVE_KRB5
static Code_t Z_CheckZcodeAuthentication(ZNotice_t *notice,
struct sockaddr_in *from,
krb5_keyblock *keyblock)
{
krb5_error_code result;
krb5_enctype enctype;
krb5_cksumtype cksumtype;
krb5_data cksumbuf;
int valid;
char *cksum0_base, *cksum1_base = NULL, *cksum2_base;
char *x;
unsigned char *asn1_data, *key_data, *cksum_data;
int asn1_len, key_len, cksum0_len = 0, cksum1_len = 0, cksum2_len = 0;
/* Figure out what checksum type to use */
key_data = Z_keydata(keyblock);
key_len = Z_keylen(keyblock);
result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
if (result) {
return (ZAUTH_FAILED);
}
/* Assemble the things to be checksummed */
/* first part is from start of packet through z_default_format:
* - z_version
* - z_num_other_fields
* - z_kind
* - z_uid
* - z_port
* - z_auth
* - z_authent_len
* - z_ascii_authent
* - z_class
* - z_class_inst
* - z_opcode
* - z_sender
* - z_recipient
* - z_default_format
*/
cksum0_base = notice->z_packet;
x = notice->z_default_format;
cksum0_len = x + strlen(x) + 1 - cksum0_base;
/* second part is from z_multinotice through other fields:
* - z_multinotice
* - z_multiuid
* - z_sender_(sock)addr
* - z_charset
* - z_other_fields[]
*/
if (notice->z_num_hdr_fields > 15 ) {
cksum1_base = notice->z_multinotice;
if (notice->z_num_other_fields)
x = notice->z_other_fields[notice->z_num_other_fields - 1];
else {
/* see also server/kstuff.c:ZCheck{Realm,}Authentication */
/* XXXXXXXXXXXXXXXXXXXXXXX */
if (notice->z_num_hdr_fields > 16)
x = cksum1_base + strlen(cksum1_base) + 1; /* multinotice */
if (notice->z_num_hdr_fields > 17)
x = x + strlen(x) + 1; /* multiuid */
if (notice->z_num_hdr_fields > 18)
x = x + strlen(x) + 1; /* sender */
}
cksum1_len = x + strlen(x) + 1 - cksum1_base; /* charset / extra field */
}
/* last part is the message body */
cksum2_base = notice->z_message;
cksum2_len = notice->z_message_len;
/* The following code checks for old-style checksums, which will go
away once Kerberos 4 does. */
if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
key_len == 8 &&
(enctype == (krb5_enctype)ENCTYPE_DES_CBC_CRC ||
enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD4 ||
enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD5)) {
/* try old-format checksum (covers cksum0 only) */
ZChecksum_t our_checksum;
our_checksum = z_quad_cksum((unsigned char *)cksum0_base, NULL, cksum0_len, 0,
key_data);
if (our_checksum == notice->z_checksum) {
return ZAUTH_YES;
}
}
cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
cksumbuf.data = malloc(cksumbuf.length);
if (!cksumbuf.data) {
return ZAUTH_NO;
}
/* HOLDING: cksumbuf.data */
cksum_data = (unsigned char *)cksumbuf.data;
memcpy(cksum_data, cksum0_base, cksum0_len);
if (cksum1_len)
memcpy(cksum_data + cksum0_len, cksum1_base, cksum1_len);
memcpy(cksum_data + cksum0_len + cksum1_len,
cksum2_base, cksum2_len);
/* decode zcoded checksum */
/* The encoded form is always longer than the original */
asn1_len = strlen(notice->z_ascii_checksum) + 1;
asn1_data = malloc(asn1_len);
if (!asn1_data) {
free(cksumbuf.data);
return ZAUTH_FAILED;
}
/* HOLDING: asn1_data, cksumbuf.data */
result = ZReadZcode((unsigned char *)notice->z_ascii_checksum,
asn1_data, asn1_len, &asn1_len);
if (result != ZERR_NONE) {
free(asn1_data);
free(cksumbuf.data);
return ZAUTH_FAILED;
}
/* HOLDING: asn1_data, cksumbuf.data */
valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype,
Z_KEYUSAGE_SRV_CKSUM, asn1_data, asn1_len);
free(asn1_data);
free(cksumbuf.data);
if (valid)
return ZAUTH_YES;
else
return ZAUTH_FAILED;
}
#endif
Code_t ZCheckZcodeAuthentication(ZNotice_t *notice,
struct sockaddr_in *from)
{
#ifdef HAVE_KRB5
Code_t answer;
krb5_creds *creds;
struct _Z_SessionKey *savedkey, *todelete;
#endif
/* If the value is already known, return it. */
if (notice->z_checked_auth != ZAUTH_UNSET)
return (notice->z_checked_auth);
if (!notice->z_auth)
return (ZAUTH_NO);
if (!notice->z_ascii_checksum)
return (ZAUTH_NO);
#ifdef HAVE_KRB5
/* Try each of the saved session keys. */
for (savedkey = Z_keys_head; savedkey != NULL; savedkey = savedkey->next) {
answer = Z_CheckZcodeAuthentication(notice, from, savedkey->keyblock);
if (answer == ZAUTH_YES) {
/* Save the time of the first use of each key. */
if (!savedkey->first_use) {
savedkey->first_use = time(NULL);
} else {
/*
* Any keys sent sufficiently long before this one is stale. If
* we know it has been long enough since the server learned of
* this key, we can prune keys made stale by this one.
*/
if (time(NULL) > savedkey->first_use + KEY_TIMEOUT) {
while (Z_keys_tail &&
Z_keys_tail->send_time + KEY_TIMEOUT < savedkey->send_time) {
todelete = Z_keys_tail;
Z_keys_tail = Z_keys_tail->prev;
Z_keys_tail->next = NULL;
krb5_free_keyblock(Z_krb5_ctx, todelete->keyblock);
free(todelete);
}
}
}
return answer;
}
}
/*
* If each of those fails, pull from the ccache. This is to preserve the
* behavior of things like zwgc/zctl where another program actually
* generates the subscription notices.
*/
if (ZGetCreds(&creds))
return ZAUTH_NO;
answer = Z_CheckZcodeAuthentication(notice, from, Z_credskey(creds));
krb5_free_creds(Z_krb5_ctx, creds);
return answer;
#else
return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
#endif
}

29
lib/ZClosePort.c Normal file
View File

@ -0,0 +1,29 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZClosePort function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZClosePort_c[] = "$Id$";
#endif
Code_t
ZClosePort(void)
{
if (__Zephyr_fd >= 0 && __Zephyr_open)
(void) close(__Zephyr_fd);
__Zephyr_fd = -1;
__Zephyr_open = 0;
return (ZERR_NONE);
}

24
lib/ZCmpUID.c Normal file
View File

@ -0,0 +1,24 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZCompareUID function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZCompareUID_c[] = "$Id$";
#endif
#include <internal.h>
int
ZCompareUID(ZUnique_Id_t *uid1,
ZUnique_Id_t *uid2)
{
return (!memcmp((char *)uid1, (char *)uid2, sizeof (*uid1)));
}

31
lib/ZCmpUIDP.c Normal file
View File

@ -0,0 +1,31 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZCompareUIDPred function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZCompareUIDPred_c[] = "$Id$";
#endif
#include <internal.h>
int
ZCompareUIDPred(ZNotice_t *notice,
void *uid)
{
return (ZCompareUID(&notice->z_uid, (ZUnique_Id_t *) uid));
}
int
ZCompareMultiUIDPred(ZNotice_t *notice,
void *uid)
{
return (ZCompareUID(&notice->z_multiuid, (ZUnique_Id_t *) uid));
}

138
lib/ZDumpSession.c Normal file
View File

@ -0,0 +1,138 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the session dump and restore function.
*
* Created by: David Benjamin
*
* $Id$
*
* Copyright (c) 2013 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZDumpSession_c[] = "$Id$";
#endif
#include <internal.h>
#define SESSION_VERSION 1
Code_t
ZDumpSession(char **buffer,
int *ret_len)
{
#ifdef HAVE_KRB5
struct _Z_SessionKey *key;
uint32_t num_keys = 0;
#endif
char *ptr;
int len;
/*
* We serialize the port number and all keys. All numbers are
* stored in big-endian. Byte strings are prefixed with a 32-bit
* length. First field is 16-bit version number. Keys are stored
* in reverse.
*/
len = 2 + 2; /* version, port number */
#ifdef HAVE_KRB5
len += 4; /* num_keys */
for (key = Z_keys_head; key != NULL; key = key->next) {
num_keys++;
len += 4 + 4; /* enctype, length */
len += key->keyblock->length; /* contents */
}
#endif
*ret_len = len;
if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
return (ENOMEM);
ptr = *buffer;
*((uint16_t*) ptr) = htons(SESSION_VERSION); ptr += 2;
*((uint16_t*) ptr) = htons(__Zephyr_port); ptr += 2;
#ifdef HAVE_KRB5
*((uint32_t *)ptr) = htonl(num_keys); ptr += 4;
for (key = Z_keys_tail; key != NULL; key = key->prev) {
*((uint32_t*) ptr) = htonl(key->keyblock->enctype); ptr += 4;
*((uint32_t*) ptr) = htonl(key->keyblock->length); ptr += 4;
memcpy(ptr, key->keyblock->contents, key->keyblock->length);
ptr += key->keyblock->length;
}
#endif
return (ZERR_NONE);
}
Code_t
ZLoadSession(char *buffer, int len)
{
#ifdef HAVE_KRB5
struct _Z_SessionKey *key;
uint32_t num_keys, keylength;
krb5_enctype enctype;
int i;
#endif
Code_t ret;
uint16_t version, port;
if (len < 2) return (EINVAL);
version = ntohs(*((uint16_t *) buffer)); buffer += 2; len -= 2;
if (version != SESSION_VERSION)
return (EINVAL);
if (len < 2) return (EINVAL);
port = ntohs(*((uint16_t *) buffer)); buffer += 2; len -= 2;
if ((ret = ZOpenPort(&port)) != ZERR_NONE)
return ret;
#ifdef HAVE_KRB5
if (len < 4) return (EINVAL);
num_keys = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;
for (i = 0; i < num_keys; i++) {
key = (struct _Z_SessionKey *)malloc(sizeof(struct _Z_SessionKey));
if (!key)
return (ENOMEM);
if (len < 4) {
free(key);
return (EINVAL);
}
enctype = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;
if (len < 4) {
free(key);
return (EINVAL);
}
keylength = ntohl(*((uint32_t *) buffer)); buffer += 4; len -= 4;
if (len < keylength) {
free(key);
return (EINVAL);
}
ret = krb5_init_keyblock(Z_krb5_ctx, enctype, keylength, &key->keyblock);
if (ret) {
free(key);
return ret;
}
memcpy((char *)key->keyblock->contents, buffer, keylength);
buffer += keylength; len -= keylength;
/* Just set recent times. It means we might not be able to
retire the keys, but that's fine. */
key->send_time = time(NULL);
key->first_use = time(NULL);
/* Prepend to the key list. */
key->prev = NULL;
key->next = Z_keys_head;
if (Z_keys_head)
Z_keys_head->prev = key;
Z_keys_head = key;
if (!Z_keys_tail)
Z_keys_tail = key;
}
#endif
if (len)
return (EINVAL);
return (ZERR_NONE);
}

101
lib/ZExpnRlm.c Normal file
View File

@ -0,0 +1,101 @@
#include <internal.h>
#include <sys/param.h>
#include <ctype.h>
char *
ZExpandRealm(char *realm)
{
char *cp1, *cp2;
static char expand[REALM_SZ];
#ifdef HAVE_KRB5
krb5_error_code result;
char **list_realms;
result = krb5_get_host_realm(Z_krb5_ctx, realm, &list_realms);
if (result) {
/* Error, just return upper-cased realm */
cp2 = realm;
cp1 = expand;
while (*cp2) {
*cp1++ = toupper(*cp2++);
}
*cp1 = '\0';
return expand;
}
strncpy(expand, list_realms[0], sizeof(expand));
expand[sizeof(expand)-1] = '\0';
result = krb5_free_host_realm(Z_krb5_ctx, list_realms);
return expand;
#else
#ifndef HAVE_KRB4
struct hostent *he;
he = gethostbyname(realm);
if (!he || !he->h_name)
/* just use the raw realm */
cp2 = realm;
else
cp2 = he->h_name;
cp1 = expand;
while (*cp2) {
*cp1++ = toupper(*cp2++);
}
*cp1 = '\0';
return(expand);
#else
int retval;
FILE *rlm_file;
char krb_host[NS_MAXDNAME + 1];
static char krb_realm[REALM_SZ+1];
char linebuf[BUFSIZ];
char scratch[64];
/* upcase what we got */
cp2 = realm;
cp1 = expand;
while (*cp2) {
*cp1++ = toupper(*cp2++);
}
*cp1 = '\0';
if ((rlm_file = fopen("/etc/krb.conf", "r")) == (FILE *) 0) {
return(expand);
}
if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) {
/* error reading */
(void) fclose(rlm_file);
return(expand);
}
if (sscanf(linebuf, "%s", krb_realm) < 1) {
/* error reading */
(void) fclose(rlm_file);
return(expand);
}
if (!strncmp(krb_realm, expand, strlen(expand))) {
(void) fclose(rlm_file);
return(krb_realm);
}
while (1) {
/* run through the file, looking for admin host */
if (fgets(linebuf, BUFSIZ, rlm_file) == NULL) {
(void) fclose(rlm_file);
return(expand);
}
if (sscanf(linebuf, "%s %s admin %s", krb_realm, krb_host, scratch)
< 2)
continue;
if (!strncmp(krb_realm, expand, strlen(expand))) {
(void) fclose(rlm_file);
return(krb_realm);
}
}
#endif /* HAVE_KRB4 */
#endif
}

39
lib/ZFlsLocs.c Normal file
View File

@ -0,0 +1,39 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFlushLocations function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFlushLocations_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFlushLocations(void)
{
int i;
if (!__locate_list)
return (ZERR_NONE);
for (i=0;i<__locate_num;i++) {
free(__locate_list[i].host);
free(__locate_list[i].time);
free(__locate_list[i].tty);
}
free((char *)__locate_list);
__locate_list = 0;
__locate_num = 0;
return (ZERR_NONE);
}

40
lib/ZFlsSubs.c Normal file
View File

@ -0,0 +1,40 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFlushSubscriptions function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZFlushSubscriptions_c[] = "$Id$";
#endif
Code_t
ZFlushSubscriptions(void)
{
register int i;
if (!__subscriptions_list)
return (ZERR_NONE);
for (i=0;i<__subscriptions_num;i++) {
free(__subscriptions_list[i].zsub_class);
free(__subscriptions_list[i].zsub_classinst);
free(__subscriptions_list[i].zsub_recipient);
}
free((char *)__subscriptions_list);
__subscriptions_list = 0;
__subscriptions_num = 0;
return (ZERR_NONE);
}

134
lib/ZFmtAuth.c Normal file
View File

@ -0,0 +1,134 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatAuthenticNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatAuthenticNotice_c[] = "$Id$";
#endif
#include <internal.h>
#ifdef HAVE_KRB4
Code_t
ZFormatAuthenticNotice(ZNotice_t *notice,
char *buffer,
int buffer_len,
int *len,
C_Block session)
{
ZNotice_t newnotice;
char *ptr;
int retval, hdrlen;
newnotice = *notice;
newnotice.z_auth = 1;
newnotice.z_authent_len = 0;
newnotice.z_ascii_authent = "";
if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
&hdrlen, &ptr, NULL)) != ZERR_NONE)
return (retval);
newnotice.z_checksum =
(ZChecksum_t)des_quad_cksum((void *)buffer, NULL, ptr - buffer, 0, (C_Block *)session);
if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
&hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
ptr = buffer+hdrlen;
if (newnotice.z_message_len+hdrlen > buffer_len)
return (ZERR_PKTLEN);
(void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
*len = hdrlen+newnotice.z_message_len;
if (*len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
return (ZERR_NONE);
}
#endif
#ifdef HAVE_KRB5
Code_t
ZFormatAuthenticNoticeV5(ZNotice_t *notice,
register char *buffer,
register int buffer_len,
int *len,
krb5_keyblock *keyblock)
{
ZNotice_t newnotice;
char *ptr;
int retval, hdrlen, hdr_adj;
krb5_enctype enctype;
krb5_cksumtype cksumtype;
#ifdef HAVE_KRB4
int key_len;
#endif
char *cksum_start, *cstart, *cend;
int cksum_len;
#ifdef HAVE_KRB4
key_len = Z_keylen(keyblock);
#endif
retval = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
if (retval)
return (ZAUTH_FAILED);
#ifdef HAVE_KRB4
if (key_len == 8 && (enctype == (krb5_enctype)ENCTYPE_DES_CBC_CRC ||
enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD4 ||
enctype == (krb5_enctype)ENCTYPE_DES_CBC_MD5)) {
C_Block tmp;
memcpy(&tmp, Z_keydata(keyblock), key_len);
return ZFormatAuthenticNotice(notice, buffer, buffer_len, len,
tmp);
}
#endif
newnotice = *notice;
newnotice.z_auth = 1;
newnotice.z_authent_len = 0;
newnotice.z_ascii_authent = "";
if ((retval = Z_NewFormatRawHeader(&newnotice, buffer, buffer_len,
&hdrlen,
&cksum_start, &cksum_len, &cstart,
&cend)) != ZERR_NONE)
return (retval);
/* we know this is only called by the server */
retval = Z_InsertZcodeChecksum(keyblock, &newnotice, buffer,
cksum_start, cksum_len, cstart, cend,
buffer_len, &hdr_adj, 1);
if (retval)
return retval;
hdrlen += hdr_adj;
ptr = buffer+hdrlen;
if (newnotice.z_message_len+hdrlen > buffer_len)
return (ZERR_PKTLEN);
(void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
*len = hdrlen+newnotice.z_message_len;
if (*len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
return (ZERR_NONE);
}
#endif

59
lib/ZFmtList.c Normal file
View File

@ -0,0 +1,59 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatNoticeList function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZFormatNoticeList_c[] =
"$Id$";
#endif
Code_t
ZFormatNoticeList(ZNotice_t *notice,
register char **list,
int nitems,
char **buffer,
int *ret_len,
Z_AuthProc cert_routine)
{
char header[Z_MAXHEADERLEN];
register int i;
int hdrlen, size;
char *ptr;
Code_t retval;
if ((retval = Z_FormatHeader(notice, header, sizeof(header), &hdrlen,
cert_routine)) != ZERR_NONE)
return (retval);
size = 0;
for (i=0;i<nitems;i++)
size += strlen(list[i])+1;
*ret_len = hdrlen+size;
/* *ret_len can never be zero here, no need to worry about malloc(0). */
if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, header, hdrlen);
ptr = *buffer+hdrlen;
for (;nitems;nitems--, list++) {
i = strlen(*list)+1;
(void) memcpy(ptr, *list, i);
ptr += i;
}
return (ZERR_NONE);
}

69
lib/ZFmtNotice.c Normal file
View File

@ -0,0 +1,69 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFormatNotice(register ZNotice_t *notice,
char **buffer,
int *ret_len,
Z_AuthProc cert_routine)
{
char header[Z_MAXHEADERLEN];
int hdrlen;
Code_t retval;
if ((retval = Z_FormatHeader(notice, header, sizeof(header), &hdrlen,
cert_routine)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
/* Length can never be zero, don't have to worry about malloc(0). */
if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, header, hdrlen);
(void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
return (ZERR_NONE);
}
Code_t
ZNewFormatNotice(register ZNotice_t *notice,
char **buffer,
int *ret_len,
Z_AuthProc cert_routine)
{
char header[Z_MAXHEADERLEN];
int hdrlen;
Code_t retval;
if ((retval = Z_NewFormatHeader(notice, header, sizeof(header), &hdrlen,
cert_routine)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
/* Length can never be zero, don't have to worry about malloc(0). */
if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, header, hdrlen);
(void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
return (ZERR_NONE);
}

42
lib/ZFmtRaw.c Normal file
View File

@ -0,0 +1,42 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatRawNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatRawNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFormatRawNotice(register ZNotice_t *notice,
char **buffer,
int *ret_len)
{
char header[Z_MAXHEADERLEN];
int hdrlen;
Code_t retval;
if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
&hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
/* *ret_len is never 0, don't have to worry about malloc(0) */
if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, header, hdrlen);
(void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
return (ZERR_NONE);
}

55
lib/ZFmtRawLst.c Normal file
View File

@ -0,0 +1,55 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatRawNoticeList function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatRawNoticeList_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFormatRawNoticeList(ZNotice_t *notice,
char *list[],
int nitems,
char **buffer,
int *ret_len)
{
char header[Z_MAXHEADERLEN];
int hdrlen, i, size;
char *ptr;
Code_t retval;
if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
&hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
size = 0;
for (i=0;i<nitems;i++)
size += strlen(list[i])+1;
*ret_len = hdrlen+size;
if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, header, hdrlen);
ptr = *buffer+hdrlen;
for (;nitems;nitems--, list++) {
i = strlen(*list)+1;
(void) memcpy(ptr, *list, i);
ptr += i;
}
return (ZERR_NONE);
}

52
lib/ZFmtSmRLst.c Normal file
View File

@ -0,0 +1,52 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatSmallRawNoticeList function.
*
* Created by: John T. Kohl
*
* $Id$
*
* Copyright (c) 1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatRawNoticeList_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFormatSmallRawNoticeList(ZNotice_t *notice,
char *list[],
int nitems,
ZPacket_t buffer,
int *ret_len)
{
Code_t retval;
int hdrlen, i, size;
char *ptr;
if ((retval = Z_FormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
&hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
size = 0;
for (i=0;i<nitems;i++)
size += strlen(list[i])+1;
*ret_len = hdrlen+size;
if (*ret_len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
ptr = buffer+hdrlen;
for (;nitems;nitems--, list++) {
i = strlen(*list)+1;
(void) memcpy(ptr, *list, i);
ptr += i;
}
return (ZERR_NONE);
}

62
lib/ZFmtSmRaw.c Normal file
View File

@ -0,0 +1,62 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFormatSmallRawNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFormatRawNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFormatSmallRawNotice(ZNotice_t *notice,
ZPacket_t buffer,
int *ret_len)
{
Code_t retval;
int hdrlen;
if ((retval = Z_FormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
&hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
if (*ret_len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
(void) memcpy(buffer+hdrlen, notice->z_message, notice->z_message_len);
return (ZERR_NONE);
}
Code_t
ZNewFormatSmallRawNotice(ZNotice_t *notice,
ZPacket_t buffer,
int *ret_len)
{
Code_t retval;
int hdrlen;
if ((retval = Z_AsciiFormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
&hdrlen, NULL, NULL, NULL, NULL))
!= ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
if (*ret_len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
(void) memcpy(buffer+hdrlen, notice->z_message, notice->z_message_len);
return (ZERR_NONE);
}

24
lib/ZFreeNot.c Normal file
View File

@ -0,0 +1,24 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZFreeNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZFreeNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZFreeNotice(ZNotice_t *notice)
{
free(notice->z_packet);
return 0;
}

42
lib/ZGetLocs.c Normal file
View File

@ -0,0 +1,42 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetLocations function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZGetLocations_c[] = "$Id$";
#endif
#include <internal.h>
#define min(a,b) ((a)<(b)?(a):(b))
Code_t
ZGetLocations(ZLocations_t *location,
int *numlocs)
{
int i;
if (!__locate_list)
return (ZERR_NOLOCATIONS);
if (__locate_next == __locate_num)
return (ZERR_NOMORELOCS);
for (i=0;i<min(*numlocs, __locate_num-__locate_next);i++)
location[i] = __locate_list[i+__locate_next];
if (__locate_num-__locate_next < *numlocs)
*numlocs = __locate_num-__locate_next;
__locate_next += *numlocs;
return (ZERR_NONE);
}

77
lib/ZGetSender.c Normal file
View File

@ -0,0 +1,77 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetSender.c function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZGetSender_c[] =
"$Id$";
#endif
#include <pwd.h>
char *
ZGetSender(void)
{
struct passwd *pw;
static char *sender = NULL;
#ifdef HAVE_KRB5
krb5_ccache ccache;
krb5_principal principal;
char *prname;
int result;
#else
#ifdef HAVE_KRB4
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
#endif
#endif
/* Return it if already cached */
if (sender)
return (sender);
#ifdef HAVE_KRB5
result = krb5_cc_default(Z_krb5_ctx, &ccache);
if (!result) {
result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &principal);
if (!result) {
krb5_unparse_name(Z_krb5_ctx, principal, &prname);
sender = strdup(prname);
krb5_free_unparsed_name(Z_krb5_ctx, prname);
krb5_free_principal(Z_krb5_ctx, principal);
return sender;
}
krb5_cc_close(Z_krb5_ctx, ccache);
}
#else
#ifdef HAVE_KRB4
if (krb_get_tf_fullname((char *)TKT_FILE, pname, pinst, prealm) == KSUCCESS)
{
sender = malloc(ANAME_SZ+INST_SZ+REALM_SZ+3);
if (sender)
(void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
pinst, prealm);
return (sender);
}
#endif
#endif
/* XXX a uid_t is a u_short (now), but getpwuid
* wants an int. AARGH! */
pw = getpwuid((int) getuid());
if (!pw)
return ("unknown");
sender = malloc(strlen(pw->pw_name) + strlen(__Zephyr_realm) + 2);
if (sender)
(void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
return (sender);
}

44
lib/ZGetSubs.c Normal file
View File

@ -0,0 +1,44 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetSubscriptions function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZGetSubscriptions_c[] = "$Id$";
#endif
#include <internal.h>
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
Code_t
ZGetSubscriptions(ZSubscription_t *subscription,
int *numsubs)
{
int i;
if (!__subscriptions_list)
return (ZERR_NOSUBSCRIPTIONS);
if (__subscriptions_next == __subscriptions_num)
return (ZERR_NOMORESUBSCRIPTIONS);
for (i = 0; i < MIN(*numsubs, __subscriptions_num-__subscriptions_next); i++)
subscription[i] = __subscriptions_list[i+__subscriptions_next];
if (__subscriptions_num-__subscriptions_next < *numsubs)
*numsubs = __subscriptions_num-__subscriptions_next;
__subscriptions_next += *numsubs;
return (ZERR_NONE);
}

41
lib/ZGetWGPort.c Normal file
View File

@ -0,0 +1,41 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetWGPort function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZGetWGPort_c[] = "$Id$";
#endif
#include <internal.h>
int
ZGetWGPort(void)
{
char *envptr, name[128];
FILE *fp;
int wgport;
envptr = getenv("WGFILE");
if (!envptr) {
(void) sprintf(name, "/tmp/wg.%d", getuid());
envptr = name;
}
if (!(fp = fopen(envptr, "r")))
return (-1);
/* if fscanf fails, return -1 via wgport */
if (fscanf(fp, "%d", &wgport) != 1)
wgport = -1;
(void) fclose(fp);
return (wgport);
}

62
lib/ZIfNotice.c Normal file
View File

@ -0,0 +1,62 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZIfNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZIfNotice_c[] = "$Id$";
#endif
Code_t
ZIfNotice(ZNotice_t *notice,
struct sockaddr_in *from,
int (*predicate)(ZNotice_t *, void *),
void *args)
{
ZNotice_t tmpnotice;
Code_t retval;
char *buffer;
struct _Z_InputQ *qptr;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
return (retval);
qptr = Z_GetFirstComplete();
for (;;) {
while (qptr) {
if ((retval = ZParseNotice(qptr->packet, qptr->packet_len,
&tmpnotice)) != ZERR_NONE)
return (retval);
if ((*predicate)(&tmpnotice, args)) {
if (!(buffer = (char *) malloc((unsigned) qptr->packet_len)))
return (ENOMEM);
(void) memcpy(buffer, qptr->packet, qptr->packet_len);
if (from)
*from = qptr->from;
if ((retval = ZParseNotice(buffer, qptr->packet_len,
notice)) != ZERR_NONE) {
free(buffer);
return (retval);
}
Z_RemQueue(qptr);
return (ZERR_NONE);
}
qptr = Z_GetNextComplete(qptr);
}
if ((retval = Z_ReadWait()) != ZERR_NONE)
return (retval);
qptr = Z_GetFirstComplete(); /* need to look over all of
the queued messages, in case
a fragment has been reassembled */
}
}

435
lib/ZInit.c Normal file
View File

@ -0,0 +1,435 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZInitialize function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987, 1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZInitialize_c[] =
"$Id$";
#endif
#include <internal.h>
#include <sys/socket.h>
#ifdef HAVE_KRB4
#include <krb_err.h>
#endif
#ifdef HAVE_KRB5
#include <krb5.h>
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#if defined(HAVE_KRB5) && defined(KRB5_REFERRAL_REALM)
#include <profile.h>
static int z_get_host_realm_replacement(char *, char ***);
#endif
#if defined(HAVE_KRB5)
int Zauthtype = 5;
#elif defined(HAVE_KRB4)
int Zauthtype = 4;
#else
int Zauthtype = 0;
#endif
Code_t
ZInitialize(void)
{
struct servent *hmserv;
struct hostent *hostent;
char addr[4], hostname[NS_MAXDNAME];
struct in_addr servaddr;
struct sockaddr_in sin;
unsigned int sinsize = sizeof(sin);
int s;
Code_t code;
ZNotice_t notice;
#ifdef HAVE_KRB5
char **krealms = NULL;
#else
#ifdef HAVE_KRB4
char *krealm = NULL;
int krbval;
char d1[ANAME_SZ], d2[INST_SZ];
#endif
#endif
/* On OS X you don't need to initialize the Kerberos error tables
as long as you link with -framework Kerberos */
#if !(defined(__APPLE__) && defined(__MACH__))
#ifdef HAVE_KRB4
initialize_krb_error_table();
#endif
#ifdef HAVE_KRB5
initialize_krb5_error_table();
#endif
#endif
#if defined(__APPLE__) && defined(__MACH__)
add_error_table(&et_zeph_error_table);
#else
initialize_zeph_error_table();
#endif
(void) memset((char *)&__HM_addr, 0, sizeof(__HM_addr));
__HM_addr.sin_family = AF_INET;
/* Set up local loopback address for HostManager */
addr[0] = 127;
addr[1] = 0;
addr[2] = 0;
addr[3] = 1;
hmserv = (struct servent *)getservbyname(HM_SVCNAME, "udp");
__HM_addr.sin_port = (hmserv) ? hmserv->s_port : HM_SVC_FALLBACK;
(void) memcpy((char *)&__HM_addr.sin_addr, addr, 4);
__HM_set = 0;
/* Initialize the input queue */
__Q_Tail = NULL;
__Q_Head = NULL;
#ifdef HAVE_KRB5
if ((code = krb5_init_context(&Z_krb5_ctx)))
return(code);
#endif
/* if the application is a server, there might not be a zhm. The
code will fall back to something which might not be "right",
but this is is ok, since none of the servers call krb_rd_req. */
servaddr.s_addr = INADDR_NONE;
if (! __Zephyr_server) {
if ((code = ZOpenPort(NULL)) != ZERR_NONE)
return(code);
if ((code = ZhmStat(NULL, &notice)) != ZERR_NONE)
return(code);
ZClosePort();
/* the first field, which is NUL-terminated, is the server name.
If this code ever support a multiplexing zhm, this will have to
be made smarter, and probably per-message */
#ifdef HAVE_KRB5
#ifndef KRB5_REFERRAL_REALM
code = krb5_get_host_realm(Z_krb5_ctx, notice.z_message, &krealms);
if (code)
return(code);
#else
code = z_get_host_realm_replacement(notice.z_message, &krealms);
#endif
#else
#ifdef HAVE_KRB4
krealm = krb_realmofhost(notice.z_message);
#endif
#endif
hostent = gethostbyname(notice.z_message);
if (hostent && hostent->h_addrtype == AF_INET)
memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
ZFreeNotice(&notice);
}
#ifdef HAVE_KRB5
if (krealms) {
strcpy(__Zephyr_realm, krealms[0]);
krb5_free_host_realm(Z_krb5_ctx, krealms);
} else {
char *p; /* XXX define this somewhere portable */
/* XXX check ticket file here */
code = krb5_get_default_realm(Z_krb5_ctx, &p);
if (code)
return code;
strcpy(__Zephyr_realm, p);
#ifdef HAVE_KRB5_FREE_DEFAULT_REALM
krb5_free_default_realm(Z_krb5_ctx, p);
#else
free(p);
#endif
}
#else
#ifdef HAVE_KRB4
if (krealm) {
strcpy(__Zephyr_realm, krealm);
} else if ((krb_get_tf_fullname(TKT_FILE, d1, d2, __Zephyr_realm)
!= KSUCCESS) &&
((krbval = krb_get_lrealm(__Zephyr_realm, 1)) != KSUCCESS)) {
return (krbval);
}
#else
strcpy(__Zephyr_realm, "local-realm");
#endif
#endif
__My_addr.s_addr = INADDR_NONE;
if (servaddr.s_addr != INADDR_NONE) {
/* Try to get the local interface address by connecting a UDP
* socket to the server address and getting the local address.
* Some broken operating systems (e.g. Solaris 2.0-2.5) yield
* INADDR_ANY (zero), so we have to check for that. */
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s != -1) {
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, &servaddr, sizeof(servaddr));
sin.sin_port = HM_SRV_SVC_FALLBACK;
if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == 0
&& getsockname(s, (struct sockaddr *) &sin, &sinsize) == 0
&& sin.sin_addr.s_addr != 0)
memcpy(&__My_addr, &sin.sin_addr, sizeof(__My_addr));
close(s);
}
}
if (__My_addr.s_addr == INADDR_NONE) {
/* We couldn't figure out the local interface address by the
* above method. Try by resolving the local hostname. (This
* is a pretty broken thing to do, and unfortunately what we
* always do on server machines.) */
if (gethostname(hostname, sizeof(hostname)) == 0) {
hostent = gethostbyname(hostname);
if (hostent && hostent->h_addrtype == AF_INET)
memcpy(&__My_addr, hostent->h_addr, sizeof(__My_addr));
}
}
/* If the above methods failed, zero out __My_addr so things will
* sort of kind of work. */
if (__My_addr.s_addr == INADDR_NONE)
__My_addr.s_addr = 0;
/* Get the sender so we can cache it */
(void) ZGetSender();
return (ZERR_NONE);
}
const char * ZGetRealm (void) {
return __Zephyr_realm;
}
int ZGetFD (void) {
return __Zephyr_fd;
}
int ZQLength (void) {
return __Q_CompleteLength;
}
struct sockaddr_in ZGetDestAddr (void) {
return __HM_addr;
}
#if defined(HAVE_KRB5) && defined(KRB5_REFERRAL_REALM)
#include <ctype.h>
#include <netinet/in.h>
#include <resolv.h>
static int txt_lookup(char *qname, char **result) {
int ret, buflen, left;
void *buf = NULL;
void *bufend = NULL;
HEADER *hdr;
unsigned char *p;
char dname[NS_MAXDNAME];
int queries, answers;
ret = res_init();
if (ret < 0)
return -1;
buflen = 0;
do {
buflen = buflen ? buflen * 2 : 2048;
buf = (buf == NULL) ? malloc(buflen) : realloc(buf, buflen);
ret = res_search(qname, C_IN, T_TXT, buf, buflen);
} while (ret > buflen);
if (ret < 0)
return -1;
buflen = ret;
left = ret;
bufend = buflen + (unsigned char *)buf;
hdr = (HEADER *)buf;
p = buf;
queries = ntohs(hdr->qdcount);
answers = ntohs(hdr->ancount);
p += sizeof (HEADER);
left -= sizeof (HEADER);
while (queries--) {
ret = dn_expand(buf, bufend, p, dname, sizeof dname);
if (ret < 0 || (ret + 4) > left)
return -1;
p += ret + 4;
left -= ret + 4;
}
if (!ret || !answers)
return -1;
while (answers--) {
int class, type;
ret = dn_expand(buf, bufend, p, dname, sizeof dname);
if (ret < 0 || ret > left)
return -1;
p += ret;
left -= ret;
if (left < 10)
return -1;
type = ntohs(*(uint16_t *)p);
p += 2;
class = ntohs(*(uint16_t *)p);
p += 6;
ret = ntohs(*(uint16_t *)p);
p += 2;
left -= 10;
if (ret > left)
return -1;
if (class == C_IN && type == T_TXT) {
*result = malloc(ret);
if (*result == NULL)
return -1;
memcpy(*result, p + 1, ret - 1);
(*result)[ret - 1] = 0;
return 0;
}
p += ret;
}
return -1;
}
static int
z_get_host_realm_replacement(char *inhost, char ***krealms) {
char *host, *p;
char *realm = NULL;
char *default_realm = NULL;
char *tmp_realm;
char *qname;
profile_t prof;
int ret;
host = strdup(inhost);
for (p = host; *p; p++)
if (isupper(*p))
*p = tolower(*p);
p = host;
while (p && !default_realm) {
if (*p == '.') {
p++;
if (default_realm == NULL) {
default_realm = p;
}
} else {
p = strchr(p, '.');
}
}
p = host;
tmp_realm = NULL;
krb5_get_profile(Z_krb5_ctx, &prof);
while(p) {
ret = profile_get_string(prof, "domain_realm", p,
0, NULL, &tmp_realm);
if (ret) {
profile_abandon(prof);
free(host);
return ret;
}
if (tmp_realm != NULL)
break;
if (*p == '.')
p++;
else
p = strchr(p, '.');
}
if (tmp_realm != NULL) {
realm = strdup(tmp_realm);
profile_release_string(tmp_realm);
if (realm == NULL) {
free(host);
return errno;
}
}
profile_abandon(prof);
if (realm == NULL) {
p = host;
do {
qname = malloc(strlen(p) + strlen("_kerberos..") + 1);
if (qname == NULL) {
free(host);
return errno;
}
sprintf(qname, "_kerberos.%s.", p);
ret = txt_lookup(qname, &realm);
free(qname);
p = strchr(p,'.');
if (p)
p++;
} while (ret && p && p[0]);
}
if (realm == NULL) {
if (default_realm != NULL) {
realm = strdup(default_realm);
if (realm == NULL) {
free(host);
return errno;
}
for (p = realm; *p; p++)
if (islower(*p))
*p = toupper(*p);
} else {
ret = krb5_get_default_realm(Z_krb5_ctx, &realm);
if (ret) {
free(host);
return ret;
}
}
}
free(host);
if ((*krealms = calloc(2, sizeof(*krealms))) == NULL) {
if (realm)
free(realm);
return errno;
}
(*krealms)[0] = realm;
(*krealms)[1] = NULL;
return 0;
}
#endif

192
lib/ZLocations.c Normal file
View File

@ -0,0 +1,192 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSetLocation, ZUnsetLocation, and
* ZFlushMyLocations functions.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZLocations_c[] =
"$Id$";
#endif
#include <internal.h>
#include <pwd.h>
static char host[NS_MAXDNAME], *mytty = "space";
static int location_info_set = 0;
Code_t
ZInitLocationInfo(char *hostname,
char *tty)
{
char *ttyp, *p;
struct hostent *hent;
if (hostname) {
strcpy(host, hostname);
} else {
if (gethostname(host, sizeof(host)) < 0)
return (errno);
hent = gethostbyname(host);
if (hent) {
(void) strncpy(host, hent->h_name, sizeof(host));
host[sizeof(host) - 1] = '\0';
}
}
if (tty) {
mytty = strdup(tty);
} else {
ttyp = ttyname(0);
if (ttyp && *ttyp) {
p = strchr(ttyp + 1, '/');
mytty = strdup(p ? p + 1 : ttyp);
} else {
mytty = strdup("unknown");
}
}
if (mytty == NULL)
return errno;
location_info_set = 1;
return (ZERR_NONE);
}
Code_t
ZSetLocation(char *exposure)
{
return (Z_SendLocation(LOGIN_CLASS, exposure, ZGetSender(), ZAUTH,
"$sender logged in to $1 on $3 at $2"));
}
Code_t
ZUnsetLocation(void)
{
return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_LOGOUT, ZGetSender(),
ZNOAUTH, "$sender logged out of $1 on $3 at $2"));
}
Code_t
ZFlushMyLocations(void)
{
return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZGetSender(),
ZAUTH, ""));
}
Code_t
ZFlushUserLocations(char *target)
{
return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, target, ZAUTH, ""));
}
char *
ZParseExposureLevel(char *text)
{
if (!strcasecmp(text, EXPOSE_NONE))
return (EXPOSE_NONE);
else if (!strcasecmp(text, EXPOSE_OPSTAFF))
return (EXPOSE_OPSTAFF);
else if (!strcasecmp(text, EXPOSE_REALMVIS))
return (EXPOSE_REALMVIS);
else if (!strcasecmp(text, EXPOSE_REALMANN))
return (EXPOSE_REALMANN);
else if (!strcasecmp(text, EXPOSE_NETVIS))
return (EXPOSE_NETVIS);
else if (!strcasecmp(text, EXPOSE_NETANN))
return (EXPOSE_NETANN);
else
return(NULL);
}
/* lifted from lib/ZSendPkt.c wait_for_hmack, but waits for SERVACK instead */
static int
wait_for_srvack(ZNotice_t *notice, void *uid)
{
return ((notice->z_kind == SERVACK || notice->z_kind == SERVNAK)
&& ZCompareUID(&notice->z_uid, (ZUnique_Id_t *)uid));
}
Code_t
Z_SendLocation(char *class,
char *opcode,
char *target,
Z_AuthProc auth,
char *format)
{
int retval;
time_t ourtime;
ZNotice_t notice, retnotice;
char *bptr[3];
short wg_port = ZGetWGPort();
if (!location_info_set)
ZInitLocationInfo(NULL, NULL);
memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = ACKED;
notice.z_port = (u_short) ((wg_port == -1) ? 0 : wg_port);
notice.z_class = class;
notice.z_class_inst = target;
notice.z_opcode = opcode;
notice.z_sender = 0;
notice.z_recipient = "";
notice.z_num_other_fields = 0;
notice.z_default_format = format;
bptr[0] = host;
ourtime = time((time_t *)0);
bptr[1] = ctime(&ourtime);
bptr[1][strlen(bptr[1])-1] = '\0';
bptr[2] = mytty;
if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
return (retval);
retval = Z_WaitForNotice (&retnotice, wait_for_srvack, &notice.z_uid,
SRV_TIMEOUT);
if (retval != ZERR_NONE)
return retval;
if (retnotice.z_kind == SERVNAK) {
if (!retnotice.z_message_len) {
ZFreeNotice(&retnotice);
return (ZERR_SERVNAK);
}
if (!strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
ZFreeNotice(&retnotice);
return (ZERR_AUTHFAIL);
}
if (!strcmp(retnotice.z_message, ZSRVACK_FAIL)) {
ZFreeNotice(&retnotice);
return (ZERR_LOGINFAIL);
}
ZFreeNotice(&retnotice);
return (ZERR_SERVNAK);
}
if (retnotice.z_kind != SERVACK) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
if (!retnotice.z_message_len) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
if (strcmp(retnotice.z_message, ZSRVACK_SENT) &&
strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
ZFreeNotice(&retnotice);
return (ZERR_NONE);
}

92
lib/ZMakeAscii.c Normal file
View File

@ -0,0 +1,92 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZMakeAscii function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#include <assert.h>
#ifndef lint
static const char rcsid_ZMakeAscii_c[] = "$Id$";
#endif
static char *itox_chars = "0123456789ABCDEF";
Code_t
ZMakeAscii(register char *ptr,
int len,
unsigned char *field,
int num)
{
int i;
for (i=0;i<num;i++) {
/* we need to add "0x" if we are between 4 byte pieces */
if ((i & 3) == 0) {
if (len < (i?4:3))
return ZERR_FIELDLEN;
/* except at the beginning, put a space in before the "0x" */
if (i) {
*ptr++ = ' ';
len--;
}
*ptr++ = '0';
*ptr++ = 'x';
len -= 2;
}
if (len < 3)
return ZERR_FIELDLEN;
*ptr++ = itox_chars[(int) (field[i] >> 4)];
*ptr++ = itox_chars[(int) (field[i] & 0xf)];
len -= 2;
}
*ptr = '\0';
return ZERR_NONE;
}
Code_t
ZMakeAscii32(register char *ptr,
int len,
unsigned long value)
{
if (len < 11)
return ZERR_FIELDLEN;
*ptr++ = '0';
*ptr++ = 'x';
*ptr++ = itox_chars[(value >> 28) & 0xf];
*ptr++ = itox_chars[(value >> 24) & 0xf];
*ptr++ = itox_chars[(value >> 20) & 0xf];
*ptr++ = itox_chars[(value >> 16) & 0xf];
*ptr++ = itox_chars[(value >> 12) & 0xf];
*ptr++ = itox_chars[(value >> 8) & 0xf];
*ptr++ = itox_chars[(value >> 4) & 0xf];
*ptr++ = itox_chars[(value >> 0) & 0xf];
*ptr = 0;
return ZERR_NONE;
}
Code_t
ZMakeAscii16(register char *ptr,
int len,
unsigned int value)
{
if (len < 7)
return ZERR_FIELDLEN;
*ptr++ = '0';
*ptr++ = 'x';
*ptr++ = itox_chars[(value >> 12) & 0xf];
*ptr++ = itox_chars[(value >> 8) & 0xf];
*ptr++ = itox_chars[(value >> 4) & 0xf];
*ptr++ = itox_chars[(value >> 0) & 0xf];
*ptr = 0;
return ZERR_NONE;
}

80
lib/ZMakeZcode.c Normal file
View File

@ -0,0 +1,80 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZMakeZcode function.
*
* Created by: Jeffrey Hutzelman
*
* $Id$
*
* Copyright (c) 1987, 2002 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#include <assert.h>
#ifndef lint
static const char rcsid_ZMakeZcode_c[] = "$Id$";
#endif
Code_t
ZMakeZcode32(char *ptr,
int len,
unsigned long val)
{
unsigned char buf[4];
buf[0] = (val >> 24) & 0xff;
buf[1] = (val >> 16) & 0xff;
buf[2] = (val >> 8) & 0xff;
buf[3] = val & 0xff;
return ZMakeZcode(ptr, len, buf, 4);
}
Code_t
ZMakeZcode(register char *ptr,
int len,
unsigned char *field,
int num)
{
int i;
/*
* This optimistic check lets us discover quickly if the buffer
* is not even large enough to hold the field without escapes.
* It also insures we'll have space for the leading 'Z' and the
* trailing NUL. Note that this does _not_ remove the need for
* checking length as we encode.
*/
if (len < num + 2)
return ZERR_FIELDLEN;
*ptr++ = 'Z';
--len;
for (i=0;i<num;i++) {
switch (field[i]) {
case 0x00:
if (len < 3)
return ZERR_FIELDLEN;
*(unsigned char *)ptr++ = 0xff;
*(unsigned char *)ptr++ = 0xf0;
len -= 2;
continue;
case 0xff:
if (len < 3)
return ZERR_FIELDLEN;
*(unsigned char *)ptr++ = 0xff;
*(unsigned char *)ptr++ = 0xf1;
len -= 2;
continue;
default:
if (len < 2)
return ZERR_FIELDLEN;
*ptr++ = field[i];
len--;
}
}
*ptr = '\0';
return ZERR_NONE;
}

327
lib/ZMkAuth.c Normal file
View File

@ -0,0 +1,327 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZMakeAuthentication function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZMakeAuthentication_c[] = "$Id$";
#endif
#ifdef HAVE_KRB4
#include <krb_err.h>
#endif
#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
#define krb5_free_data(ctx, dat) free((dat)->data)
#endif
Code_t
ZResetAuthentication(void)
{
return ZERR_NONE;
}
Code_t
ZMakeAuthentication(register ZNotice_t *notice,
char *buffer,
int buffer_len,
int *len)
{
#ifdef HAVE_KRB5
return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
#else
#ifdef HAVE_KRB4
int result;
KTEXT_ST authent;
char *cstart, *cend;
ZChecksum_t checksum;
CREDENTIALS cred;
C_Block *session;
result = krb_mk_req(&authent, SERVER_SERVICE,
SERVER_INSTANCE, __Zephyr_realm, 0);
if (result != MK_AP_OK)
return (result+krb_err_base);
result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
__Zephyr_realm, &cred);
if (result != KSUCCESS)
return (result+krb_err_base);
session = (C_Block *)cred.session;
notice->z_auth = 1;
notice->z_authent_len = authent.length;
notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
/* zero length authent is an error, so malloc(0) is not a problem */
if (!notice->z_ascii_authent)
return (ENOMEM);
if ((result = ZMakeAscii(notice->z_ascii_authent,
authent.length*3,
authent.dat,
authent.length)) != ZERR_NONE) {
free(notice->z_ascii_authent);
return (result);
}
result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
&cend);
free(notice->z_ascii_authent);
notice->z_authent_len = 0;
if (result)
return(result);
/* Compute a checksum over the header and message. */
checksum = des_quad_cksum((unsigned char *)buffer, NULL, cstart - buffer, 0, session);
checksum ^= des_quad_cksum((unsigned char *)cend, NULL, buffer + *len - cend, 0,
session);
checksum ^= des_quad_cksum((unsigned char *)notice->z_message, NULL, notice->z_message_len,
0, session);
notice->z_checksum = checksum;
ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
return (ZERR_NONE);
#else
notice->z_checksum = 0;
notice->z_auth = 1;
notice->z_authent_len = 0;
notice->z_ascii_authent = "";
return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
#endif
#endif
}
Code_t
Z_MakeAuthenticationSaveKey(register ZNotice_t *notice,
char *buffer,
int buffer_len,
int *len)
{
#ifndef HAVE_KRB5
/* Key management not implemented for krb4. */
return ZMakeAuthentication(notice, buffer, buffer_len, len);
#else
Code_t result;
krb5_creds *creds = NULL;
krb5_keyblock *keyblock;
struct _Z_SessionKey *savedkey;
/* Look up creds and checksum the notice. */
if ((result = ZGetCreds(&creds)))
return result;
if ((result = Z_MakeZcodeAuthentication(notice, buffer, buffer_len, len,
creds))) {
krb5_free_creds(Z_krb5_ctx, creds);
return result;
}
/* Save the key. */
keyblock = Z_credskey(creds);
if (Z_keys_head &&
Z_keys_head->keyblock->enctype == keyblock->enctype &&
Z_keys_head->keyblock->length == keyblock->length &&
memcmp(Z_keys_head->keyblock->contents, keyblock->contents,
keyblock->length) == 0) {
/*
* Optimization: if the key hasn't changed, replace the current entry,
* rather than make a new one.
*/
Z_keys_head->send_time = time(NULL);
Z_keys_head->first_use = 0;
} else {
savedkey = (struct _Z_SessionKey *)malloc(sizeof(struct _Z_SessionKey));
if (!savedkey) {
krb5_free_creds(Z_krb5_ctx, creds);
return ENOMEM;
}
if ((result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &savedkey->keyblock))) {
free(savedkey);
krb5_free_creds(Z_krb5_ctx, creds);
return result;
}
savedkey->send_time = time(NULL);
savedkey->first_use = 0;
savedkey->prev = NULL;
savedkey->next = Z_keys_head;
if (Z_keys_head)
Z_keys_head->prev = savedkey;
Z_keys_head = savedkey;
if (!Z_keys_tail)
Z_keys_tail = savedkey;
}
krb5_free_creds(Z_krb5_ctx, creds);
return result;
#endif
}
/* only used by server? */
Code_t
ZMakeZcodeAuthentication(register ZNotice_t *notice,
char *buffer,
int buffer_len,
int *phdr_len)
{
return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
__Zephyr_realm);
}
Code_t
ZMakeZcodeRealmAuthentication(register ZNotice_t *notice,
char *buffer,
int buffer_len,
int *phdr_len,
char *realm)
{
#ifdef HAVE_KRB5
Code_t result;
krb5_creds *creds = NULL;
result = ZGetCredsRealm(&creds, realm);
if (!result)
result = Z_MakeZcodeAuthentication(notice, buffer, buffer_len, phdr_len,
creds);
if (creds != NULL)
krb5_free_creds(Z_krb5_ctx, creds);
return result;
#else /* HAVE_KRB5 */
return ZERR_INTERNAL;
#endif
}
#ifdef HAVE_KRB5
Code_t
Z_MakeZcodeAuthentication(register ZNotice_t *notice,
char *buffer,
int buffer_len,
int *phdr_len,
krb5_creds *creds)
{
krb5_error_code result = 0;
krb5_keyblock *keyblock;
krb5_auth_context authctx;
krb5_data *authent;
char *cksum_start, *cstart, *cend;
int cksum_len, zcode_len = 0, phdr_adj = 0;
notice->z_ascii_authent = NULL;
keyblock = Z_credskey(creds);
authent = (krb5_data *)malloc(sizeof(krb5_data));
if (authent == NULL)
result = ENOMEM;
authent->data = NULL; /* so that we can blithely krb5_fre_data_contents on
the way out */
if (!result)
result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
if (!result) {
result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */,
0 /* in_data */, creds, authent);
krb5_auth_con_free(Z_krb5_ctx, authctx);
}
if (!result || result == KRB5KRB_AP_ERR_TKT_EXPIRED) {
notice->z_auth = 1;
if (result == 0) {
notice->z_authent_len = authent->length;
} else {
notice->z_authent_len = 0;
result = 0;
}
zcode_len = notice->z_authent_len * 2 + 2; /* 2x growth plus Z and null */
notice->z_ascii_authent = (char *)malloc(zcode_len);
if (notice->z_ascii_authent == NULL)
result = ENOMEM;
}
if (!result)
result = ZMakeZcode(notice->z_ascii_authent, zcode_len,
(unsigned char *)authent->data, notice->z_authent_len);
/* format the notice header, with a zero checksum */
if (!result)
result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len,
&cksum_start, &cksum_len, &cstart, &cend);
notice->z_authent_len = 0;
if (!result)
result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
cksum_len, cstart, cend, buffer_len,
&phdr_adj, 0);
if (!result)
*phdr_len += phdr_adj;
if (notice->z_ascii_authent != NULL)
free(notice->z_ascii_authent);
krb5_free_data_contents(Z_krb5_ctx, authent);
if (authent != NULL)
free(authent);
return result;
}
int
ZGetCreds(krb5_creds **creds_out)
{
return ZGetCredsRealm(creds_out, __Zephyr_realm);
}
int
ZGetCredsRealm(krb5_creds **creds_out,
char *realm)
{
krb5_creds creds_in;
krb5_creds creds_tmp;
krb5_ccache ccache; /* XXX make this a global or static?*/
int result;
result = krb5_cc_default(Z_krb5_ctx, &ccache);
if (result)
return result;
memset((char *)&creds_in, 0, sizeof(creds_in));
result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
strlen(realm),
realm,
SERVER_SERVICE, SERVER_INSTANCE,
NULL);
if (result) {
krb5_cc_close(Z_krb5_ctx, ccache);
return result;
}
result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
if (!result) {
result = krb5_cc_retrieve_cred(Z_krb5_ctx, ccache,
#ifdef KRB5_TC_SUPPORTED_KTYPES
KRB5_TC_SUPPORTED_KTYPES, /* MIT */
#else
0, /* Heimdal or other Space KRB5 */
#endif
&creds_in, &creds_tmp);
if (!result) {
*creds_out = malloc(sizeof(creds_tmp));
if (*creds_out == NULL)
result = errno;
else
memcpy(*creds_out, &creds_tmp, sizeof(creds_tmp));
}
}
if (result == KRB5_CC_NOTFOUND || result == KRB5_CC_END)
result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
krb5_cc_close(Z_krb5_ctx, ccache);
krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
return result;
}
#endif

49
lib/ZNewLocU.c Normal file
View File

@ -0,0 +1,49 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZNewLocateUser function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZNewLocateUser_c[] =
"$Id$";
#endif
Code_t
ZLocateUser(char *user,
int *nlocs,
Z_AuthProc auth)
{
Code_t retval;
ZNotice_t notice;
ZAsyncLocateData_t zald;
(void) ZFlushLocations(); /* ZFlushLocations never fails (the library
is allowed to know this). */
if ((retval = ZRequestLocations(user, &zald, UNACKED, auth)) != ZERR_NONE)
return(retval);
retval = Z_WaitForNotice (&notice, ZCompareALDPred, &zald, SRV_TIMEOUT);
if (retval == ZERR_NONOTICE)
return ETIMEDOUT;
if (retval != ZERR_NONE)
return retval;
if ((retval = ZParseLocations(&notice, &zald, nlocs, NULL)) != ZERR_NONE) {
ZFreeNotice(&notice);
return(retval);
}
ZFreeNotice(&notice);
ZFreeALD(&zald);
return(ZERR_NONE);
}

73
lib/ZOpenPort.c Normal file
View File

@ -0,0 +1,73 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZOpenPort function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZOpenPort_c[] = "$Id$";
#endif
#include <internal.h>
#include <sys/socket.h>
Code_t
ZOpenPort(u_short *port)
{
struct sockaddr_in bindin;
unsigned int len;
int val = 1;
(void) ZClosePort();
if ((__Zephyr_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
__Zephyr_fd = -1;
return errno;
}
bindin.sin_family = AF_INET;
if (port && *port) {
bindin.sin_port = *port;
if (setsockopt(__Zephyr_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val) < 0)
return errno;
} else {
bindin.sin_port = 0;
}
bindin.sin_addr.s_addr = INADDR_ANY;
if (bind(__Zephyr_fd, (struct sockaddr *)&bindin, sizeof(bindin)) < 0) {
if (errno == EADDRINUSE && port && *port)
return ZERR_PORTINUSE;
else
return errno;
}
if (port && *port) {
/* turn SO_REUSEADDR back off so no one else can steal it */
val = 0;
if (setsockopt(__Zephyr_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val) < 0)
return errno;
}
if (!bindin.sin_port) {
len = sizeof(bindin);
if (getsockname(__Zephyr_fd, (struct sockaddr *)&bindin, &len))
return errno;
}
__Zephyr_port = bindin.sin_port;
__Zephyr_open = 1;
if (port)
*port = bindin.sin_port;
return ZERR_NONE;
}

315
lib/ZParseNot.c Normal file
View File

@ -0,0 +1,315 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZParseNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZParseNotice_c[] =
"$Id$";
#endif
#include <internal.h>
#include <syslog.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
inline static int
_bad_packet(int line, char *where, ZNotice_t *notice, char *what) {
if (__Zephyr_server) {
syslog(LOG_ERR, "ZParseNotice: bad packet (%s) from %s.%d at line %d",
what, inet_ntoa(notice->z_uid.zuid_addr), notice->z_port, line);
} else {
#ifdef Z_DEBUG
Z_debug("ZParseNotice: bad packet (%s) from %s.%d at line %d",
what, inet_ntoa(notice->z_uid.zuid_addr), notice->z_port, line);
#endif
}
return ZERR_BADPKT;
}
/* Skip to the next NUL-terminated field in the packet. */
inline static char *
next_field(char *ptr,
char *end)
{
while (ptr < end && *ptr != '\0')
ptr++;
if (ptr < end)
ptr++;
return (ptr);
}
Code_t
ZParseNotice(char *buffer,
int len,
ZNotice_t *notice)
{
char *ptr, *end;
unsigned long temp;
int maj, numfields, i;
#ifndef __LINE__
#define __LINE__ -1
#endif
#define BAD_PACKET(what) return _bad_packet(__LINE__, ptr, notice, what)
(void) memset((char *)notice, 0, sizeof(ZNotice_t));
ptr = buffer;
end = buffer+len;
notice->z_packet = buffer;
notice->z_version = ptr;
if (strncmp(ptr, ZVERSIONHDR, sizeof(ZVERSIONHDR) - 1))
return (ZERR_VERS);
ptr += sizeof(ZVERSIONHDR) - 1;
if (!*ptr)
BAD_PACKET("null version string");
maj = atoi(ptr);
if (maj != ZVERSIONMAJOR)
return (ZERR_VERS);
ptr = next_field(ptr, end);
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
BAD_PACKET("parsing num_hdr_fields");
numfields = temp;
notice->z_num_hdr_fields = numfields;
ptr = next_field(ptr, end);
/*XXX 3 */
numfields -= 2; /* numfields, version, and checksum */
if (numfields < 0)
BAD_PACKET("no header fields");
if (numfields && ptr < end) {
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
BAD_PACKET("parsing kind");
notice->z_kind = (ZNotice_Kind_t)temp;
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing kind");
if (numfields && ptr < end) {
if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
BAD_PACKET("parsing uid");
notice->z_time.tv_sec = ntohl((u_long) notice->z_uid.tv.tv_sec);
notice->z_time.tv_usec = ntohl((u_long) notice->z_uid.tv.tv_usec);
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing uid");
if (numfields && ptr < end) {
if (ZReadAscii16(ptr, end-ptr, &notice->z_port) == ZERR_BADFIELD)
BAD_PACKET("parsing port");
notice->z_port = htons(notice->z_port);
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing port");
if (numfields && ptr < end) {
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
BAD_PACKET("parsing auth");
notice->z_auth = temp;
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing auth");
notice->z_checked_auth = ZAUTH_UNSET;
if (numfields && ptr < end) {
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
BAD_PACKET("parsing authenticator length");
notice->z_authent_len = temp;
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing authenticator length");
if (numfields && ptr < end) {
notice->z_ascii_authent = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
BAD_PACKET("missing authenticator field");
if (numfields && ptr < end) {
notice->z_class = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_class = "";
if (numfields && ptr < end) {
notice->z_class_inst = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_class_inst = "";
if (numfields && ptr < end) {
notice->z_opcode = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_opcode = "";
if (numfields && ptr < end) {
notice->z_sender = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_sender = "";
if (numfields && ptr < end) {
notice->z_recipient = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_recipient = "";
if (numfields && ptr < end) {
notice->z_default_format = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_default_format = "";
if (numfields && ptr < end) {
notice->z_ascii_checksum = ptr;
if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
notice->z_checksum = 0;
else
notice->z_checksum = temp;
numfields--;
ptr = next_field (ptr, end);
}
else
{
notice->z_ascii_checksum = "";
notice->z_checksum = 0;
}
if (numfields && ptr < end) {
notice->z_multinotice = ptr;
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_multinotice = "";
if (numfields && ptr < end) {
if (ZReadAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
sizeof(ZUnique_Id_t)) == ZERR_BADFIELD)
BAD_PACKET("parsing multiuid");
notice->z_time.tv_sec = ntohl((u_long) notice->z_multiuid.tv.tv_sec);
notice->z_time.tv_usec = ntohl((u_long) notice->z_multiuid.tv.tv_usec);
numfields--;
ptr = next_field(ptr, end);
}
else
notice->z_multiuid = notice->z_uid;
if (numfields && ptr < end) {
/* we will take it on faith that ipv6 addresses are longer than ipv4
addresses */
unsigned char addrbuf[sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)];
int alen;
/* because we're paranoid about naughtily misformatted packets */
if (memchr(ptr, '\0', end - ptr) == NULL)
BAD_PACKET("unterminated address field");
if (*ptr == 'Z') {
if (ZReadZcode((unsigned char *)ptr, addrbuf,
sizeof(addrbuf), &alen) == ZERR_BADFIELD)
BAD_PACKET("parsing Zcode address");
} else {
alen = sizeof(notice->z_sender_sockaddr.ip4.sin_addr);
if (ZReadAscii(ptr, end - ptr, (unsigned char *)addrbuf,
alen) == ZERR_BADFIELD)
BAD_PACKET("parsing NetASCII address");
}
if (alen == sizeof(notice->z_sender_sockaddr.ip6.sin6_addr)) {
notice->z_sender_sockaddr.ip6.sin6_family = AF_INET6;
memcpy(&notice->z_sender_sockaddr.ip6.sin6_addr, addrbuf, alen);
#ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
notice->z_sender_sockaddr.ip6.sin6_len = sizeof(notice->z_sender_sockaddr.ip6);
#endif
} else if (alen == sizeof(notice->z_sender_sockaddr.ip4.sin_addr)) {
notice->z_sender_sockaddr.ip4.sin_family = AF_INET;
memcpy(&notice->z_sender_sockaddr.ip4.sin_addr, addrbuf, alen);
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
notice->z_sender_sockaddr.ip4.sin_len = sizeof(notice->z_sender_sockaddr.ip4);
#endif
} else
BAD_PACKET("address claims to be neither IPv4 or IPv6");
numfields--;
ptr = next_field(ptr, end);
} else {
memset(&notice->z_sender_sockaddr, 0,
sizeof notice->z_sender_sockaddr);
notice->z_sender_sockaddr.ip4.sin_family = AF_INET;
notice->z_sender_sockaddr.ip4.sin_addr = notice->z_uid.zuid_addr;
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
notice->z_sender_sockaddr.ip4.sin_len = sizeof(notice->z_sender_sockaddr.ip4);
#endif
}
if (numfields && ptr < end) {
if (ZReadAscii16(ptr, end-ptr, &notice->z_charset) == ZERR_BADFIELD)
BAD_PACKET("parsing charset");
notice->z_charset = htons(notice->z_charset);
numfields--;
ptr = next_field(ptr, end);
} else
notice->z_charset = ZCHARSET_UNKNOWN;
for (i=0;ptr < end && i<Z_MAXOTHERFIELDS && numfields;i++,numfields--) {
notice->z_other_fields[i] = ptr;
ptr = next_field(ptr, end);
}
notice->z_num_other_fields = i;
for (i=0;ptr < end && numfields;numfields--)
ptr = next_field(ptr, end);
if (numfields || *(ptr - 1) != '\0')
BAD_PACKET("end of headers");
notice->z_message = (void *)ptr;
notice->z_message_len = len-(ptr-buffer);
return (ZERR_NONE);
}

57
lib/ZPeekIfNot.c Normal file
View File

@ -0,0 +1,57 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZPeekIfNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZPeekIfNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZPeekIfNotice(ZNotice_t *notice,
struct sockaddr_in *from,
int (*predicate)(ZNotice_t *, char *),
char *args)
{
ZNotice_t tmpnotice;
Code_t retval;
char *buffer;
struct _Z_InputQ *qptr;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
return (retval);
for (;;) {
qptr = Z_GetFirstComplete();
while (qptr) {
if ((retval = ZParseNotice(qptr->packet, qptr->packet_len,
&tmpnotice)) != ZERR_NONE)
return (retval);
if ((*predicate)(&tmpnotice, args)) {
if (!(buffer = (char *) malloc((unsigned) qptr->packet_len)))
return (ENOMEM);
(void) memcpy(buffer, qptr->packet, qptr->packet_len);
if (from)
*from = qptr->from;
if ((retval = ZParseNotice(buffer, qptr->packet_len,
notice)) != ZERR_NONE) {
free(buffer);
return (retval);
}
return (ZERR_NONE);
}
qptr = Z_GetNextComplete(qptr);
}
if ((retval = Z_ReadWait()) != ZERR_NONE)
return (retval);
}
}

31
lib/ZPeekNot.c Normal file
View File

@ -0,0 +1,31 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for ZPeekNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZPeekNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZPeekNotice(ZNotice_t *notice,
struct sockaddr_in *from)
{
char *buffer;
int len;
Code_t retval;
if ((retval = ZPeekPacket(&buffer, &len, from)) != ZERR_NONE)
return (retval);
return (ZParseNotice(buffer, len, notice));
}

43
lib/ZPeekPkt.c Normal file
View File

@ -0,0 +1,43 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for ZPeekPacket function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZPeekPacket_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZPeekPacket(char **buffer,
int *ret_len,
struct sockaddr_in *from)
{
Code_t retval;
struct _Z_InputQ *nextq;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
return (retval);
nextq =Z_GetFirstComplete();
*ret_len = nextq->packet_len;
if (!(*buffer = (char *) malloc((unsigned) *ret_len)))
return (ENOMEM);
(void) memcpy(*buffer, nextq->packet, *ret_len);
if (from)
*from = nextq->from;
return (ZERR_NONE);
}

35
lib/ZPending.c Normal file
View File

@ -0,0 +1,35 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZPending function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZPending_c[] = "$Id$";
#endif
#include <internal.h>
int
ZPending(void)
{
int retval;
if (ZGetFD() < 0) {
errno = ZERR_NOPORT;
return (-1);
}
if ((retval = Z_ReadEnqueue()) != ZERR_NONE) {
errno = retval;
return (-1);
}
return(ZQLength());
}

88
lib/ZReadAscii.c Normal file
View File

@ -0,0 +1,88 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZReadAscii function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987, 1990 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZReadAscii_c[] = "$Id$";
#endif /* lint */
#include <internal.h>
#include <assert.h>
#define Z_cnvt_xtoi(c) ((temp=(c)-'0'),(temp<10)?temp:((temp-='A'-'9'-1),(temp<16)?temp:-1))
Code_t
ZReadAscii(char *ptr,
int len,
unsigned char *field,
int num)
{
int i;
unsigned int hexbyte;
register int c1, c2;
register int temp;
for (i=0;i<num;i++) {
if (len >= 1 && *ptr == ' ') {
ptr++;
len--;
}
if (len >= 2 && ptr[0] == '0' && ptr[1] == 'x') {
ptr += 2;
len -= 2;
}
if (len < 2)
return ZERR_BADFIELD;
c1 = Z_cnvt_xtoi(ptr[0]);
if (c1 < 0)
return ZERR_BADFIELD;
c2 = Z_cnvt_xtoi(ptr[1]);
if (c2 < 0)
return ZERR_BADFIELD;
hexbyte = (c1 << 4) | c2;
field[i] = hexbyte;
ptr += 2;
len -= 2;
}
return *ptr ? ZERR_BADFIELD : ZERR_NONE;
}
Code_t
ZReadAscii32(char *ptr,
int len,
unsigned long *value_ptr)
{
unsigned char buf[4];
Code_t retval;
retval = ZReadAscii(ptr, len, buf, 4);
if (retval != ZERR_NONE)
return retval;
*value_ptr = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
return ZERR_NONE;
}
Code_t
ZReadAscii16(char *ptr,
int len,
unsigned short *value_ptr)
{
unsigned char buf[2];
Code_t retval;
retval = ZReadAscii(ptr, len, buf, 2);
if (retval != ZERR_NONE)
return retval;
*value_ptr = (buf[0] << 8) | buf[1];
return ZERR_NONE;
}

48
lib/ZReadZcode.c Normal file
View File

@ -0,0 +1,48 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZReadZcode function.
*
* Created by: Jeffrey Hutzelman
*
* $Id$
*
* Copyright (c) 1987, 1990, 2002 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZReadZcode_c[] = "$Id$";
#endif /* lint */
#include <internal.h>
#include <assert.h>
Code_t
ZReadZcode(unsigned char *ptr,
unsigned char *field,
int max,
int *len)
{
int n = 0;
if (*ptr++ != 'Z')
return ZERR_BADFIELD;
while (*ptr && n < max) {
if (*ptr == 0xff) {
ptr++;
switch (*ptr++) {
case 0xf0: field[n++] = 0x00; continue;
case 0xf1: field[n++] = 0xff; continue;
default: return ZERR_BADFIELD;
}
} else {
field[n++] = *ptr++;
}
}
if (*ptr)
return (ZERR_BADFIELD);
*len = n;
return (ZERR_NONE);
}

52
lib/ZRecvNot.c Normal file
View File

@ -0,0 +1,52 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for ZReceiveNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZReceiveNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZReceiveNotice(ZNotice_t *notice,
struct sockaddr_in *from)
{
char *buffer;
struct _Z_InputQ *nextq;
int len, auth;
Code_t retval;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
return (retval);
nextq = Z_GetFirstComplete();
if (!nextq)
return (ENOMEM);
len = nextq->packet_len;
if (!(buffer = (char *) malloc((unsigned) len)))
return (ENOMEM);
if (from)
*from = nextq->from;
(void) memcpy(buffer, nextq->packet, len);
auth = nextq->auth;
Z_RemQueue(nextq);
if ((retval = ZParseNotice(buffer, len, notice)) != ZERR_NONE)
return (retval);
notice->z_checked_auth = auth;
return ZERR_NONE;
}

44
lib/ZRecvPkt.c Normal file
View File

@ -0,0 +1,44 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for ZReceivePacket function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZReceivePacket_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZReceivePacket(ZPacket_t buffer,
int *ret_len,
struct sockaddr_in *from)
{
Code_t retval;
struct _Z_InputQ *nextq;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
return (retval);
nextq = Z_GetFirstComplete();
*ret_len = nextq->packet_len;
if (*ret_len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
(void) memcpy(buffer, nextq->packet, *ret_len);
if (from)
*from = nextq->from;
Z_RemQueue(nextq);
return (ZERR_NONE);
}

185
lib/ZRetSubs.c Normal file
View File

@ -0,0 +1,185 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZRetrieveSubscriptions and
* ZRetrieveDefaultSubscriptions functions.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZRetrieveSubscriptions_c[] =
"$Id$";
#endif
static Code_t Z_RetSubs (register ZNotice_t *, int *, Z_AuthProc);
/* Need STDC definition when possible for unsigned short argument. */
Code_t
ZRetrieveSubscriptions(unsigned short port,
int *nsubs)
{
int retval;
ZNotice_t notice;
char asciiport[50];
if (!port) /* use default port */
port = __Zephyr_port;
retval = ZMakeAscii16(asciiport, sizeof(asciiport), ntohs(port));
if (retval != ZERR_NONE)
return (retval);
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_message = asciiport;
notice.z_message_len = strlen(asciiport)+1;
notice.z_opcode = CLIENT_GIMMESUBS;
return(Z_RetSubs(&notice, nsubs, ZAUTH));
}
Code_t
ZRetrieveDefaultSubscriptions(int *nsubs)
{
ZNotice_t notice;
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_message = (char *) 0;
notice.z_message_len = 0;
notice.z_opcode = CLIENT_GIMMEDEFS;
return(Z_RetSubs(&notice, nsubs, ZNOAUTH));
}
static Code_t
Z_RetSubs(register ZNotice_t *notice,
int *nsubs,
Z_AuthProc auth_routine)
{
register int i;
int retval,nrecv,gimmeack;
ZNotice_t retnotice;
char *ptr,*end,*ptr2;
ZSubscription_t *list = __subscriptions_list;
retval = ZFlushSubscriptions();
if (retval != ZERR_NONE && retval != ZERR_NOSUBSCRIPTIONS)
return (retval);
if (ZGetFD() < 0)
if ((retval = ZOpenPort((u_short *)0)) != ZERR_NONE)
return (retval);
notice->z_kind = ACKED;
notice->z_port = __Zephyr_port;
notice->z_class = ZEPHYR_CTL_CLASS;
notice->z_class_inst = ZEPHYR_CTL_CLIENT;
notice->z_sender = 0;
notice->z_recipient = "";
notice->z_default_format = "";
if ((retval = ZSendNotice(notice,auth_routine)) != ZERR_NONE)
return (retval);
nrecv = 0;
gimmeack = 0;
list = (ZSubscription_t *) 0;
while (!nrecv || !gimmeack) {
retval = Z_WaitForNotice (&retnotice, ZCompareMultiUIDPred,
&notice->z_multiuid, SRV_TIMEOUT);
if (retval == ZERR_NONOTICE)
return ETIMEDOUT;
else if (retval != ZERR_NONE)
return retval;
if (retnotice.z_kind == SERVNAK) {
ZFreeNotice(&retnotice);
return (ZERR_SERVNAK);
}
/* non-matching protocol version numbers means the
server is probably an older version--must punt */
if (strcmp(notice->z_version,retnotice.z_version)) {
ZFreeNotice(&retnotice);
return(ZERR_VERS);
}
if (retnotice.z_kind == SERVACK &&
!strcmp(retnotice.z_opcode,notice->z_opcode)) {
ZFreeNotice(&retnotice);
gimmeack = 1;
continue;
}
if (retnotice.z_kind != ACKED) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
nrecv++;
end = retnotice.z_message+retnotice.z_message_len;
__subscriptions_num = 0;
for (ptr=retnotice.z_message;ptr<end;ptr++)
if (!*ptr)
__subscriptions_num++;
__subscriptions_num = __subscriptions_num / 3;
list = (ZSubscription_t *)
malloc(__subscriptions_num * sizeof(ZSubscription_t));
if (__subscriptions_num && !list) {
ZFreeNotice(&retnotice);
return (ENOMEM);
}
ptr = retnotice.z_message;
for (i = 0; i < __subscriptions_num; i++) {
list[i].zsub_class = (char *)
malloc(strlen(ptr) + 1);
if (!list[i].zsub_class) {
ZFreeNotice(&retnotice);
return (ENOMEM);
}
strcpy(list[i].zsub_class, ptr);
ptr += strlen(ptr)+1;
list[i].zsub_classinst = (char *)
malloc(strlen(ptr) + 1);
if (!list[i].zsub_classinst) {
ZFreeNotice(&retnotice);
return (ENOMEM);
}
strcpy(list[i].zsub_classinst, ptr);
ptr += strlen(ptr)+1;
ptr2 = ptr;
list[i].zsub_recipient = (char *)
malloc(strlen(ptr2) + 2);
if (!list[i].zsub_recipient) {
ZFreeNotice(&retnotice);
return (ENOMEM);
}
if (*ptr2 == '@' || *ptr2 == 0) {
*list[i].zsub_recipient = '*';
strcpy(list[i].zsub_recipient + 1, ptr2);
} else {
strcpy(list[i].zsub_recipient, ptr2);
}
ptr += strlen(ptr)+1;
}
ZFreeNotice(&retnotice);
}
__subscriptions_list = list;
__subscriptions_next = 0;
*nsubs = __subscriptions_num;
return (ZERR_NONE);
}

52
lib/ZSendList.c Normal file
View File

@ -0,0 +1,52 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSendList function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSendList_c[] = "$Id$";
#endif
#include <internal.h>
Code_t ZSendList(ZNotice_t *notice,
char *list[],
int nitems,
Z_AuthProc cert_routine)
{
return(ZSrvSendList(notice, list, nitems, cert_routine, Z_XmitFragment));
}
Code_t
ZSrvSendList(ZNotice_t *notice,
char *list[],
int nitems,
Z_AuthProc cert_routine,
Code_t (*send_routine)(ZNotice_t *, char *, int, int))
{
Code_t retval;
ZNotice_t newnotice;
char *buffer;
int len;
if ((retval = ZFormatNoticeList(notice, list, nitems, &buffer,
&len, cert_routine)) != ZERR_NONE)
return (retval);
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
send_routine);
free(buffer);
return (retval);
}

53
lib/ZSendNot.c Normal file
View File

@ -0,0 +1,53 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSendNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSendNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZSendNotice(ZNotice_t *notice,
Z_AuthProc cert_routine)
{
return(ZSrvSendNotice(notice, cert_routine, Z_XmitFragment));
}
/* Despite its name, this is not used by the server */
Code_t
ZSrvSendNotice(ZNotice_t *notice,
Z_AuthProc cert_routine,
Code_t (*send_routine)(ZNotice_t *, char *, int, int))
{
Code_t retval;
ZNotice_t newnotice;
char *buffer;
int len;
if ((retval = ZFormatNotice(notice, &buffer, &len,
cert_routine)) != ZERR_NONE)
return (retval);
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE) {
free(buffer);
return (retval);
}
retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
send_routine);
free(buffer);
return (retval);
}

68
lib/ZSendPkt.c Normal file
View File

@ -0,0 +1,68 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSendPacket function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSendPacket_c[] =
"$Id$";
#endif
#include <internal.h>
#include <sys/socket.h>
static int wait_for_hmack(ZNotice_t *, void *);
Code_t
ZSendPacket(char *packet,
int len,
int waitforack)
{
Code_t retval;
struct sockaddr_in dest;
ZNotice_t notice, acknotice;
if (!packet || len < 0)
return (ZERR_ILLVAL);
if (len > Z_MAXPKTLEN)
return (ZERR_PKTLEN);
if (ZGetFD() < 0)
if ((retval = ZOpenPort((u_short *)0)) != ZERR_NONE)
return (retval);
dest = ZGetDestAddr();
if (sendto(ZGetFD(), packet, len, 0, (struct sockaddr *)&dest,
sizeof(dest)) < 0)
return (errno);
if (!waitforack)
return (ZERR_NONE);
if ((retval = ZParseNotice(packet, len, &notice)) != ZERR_NONE)
return (retval);
retval = Z_WaitForNotice(&acknotice, wait_for_hmack, &notice.z_uid,
HM_TIMEOUT);
if (retval == ETIMEDOUT)
return ZERR_HMDEAD;
if (retval == ZERR_NONE)
ZFreeNotice (&acknotice);
return retval;
}
static int
wait_for_hmack(ZNotice_t *notice,
void *uid)
{
return (notice->z_kind == HMACK && ZCompareUID(&notice->z_uid, (ZUnique_Id_t *)uid));
}

48
lib/ZSendRLst.c Normal file
View File

@ -0,0 +1,48 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSendRawNotice function.
*
* Created by: John T. Kohl
*
* $Id$
*
* Copyright (c) 1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSendRawList_c[] = "$Id$";
#endif
#include <internal.h>
Code_t ZSendRawList(ZNotice_t *notice,
char *list[],
int nitems)
{
return(ZSrvSendRawList(notice, list, nitems, Z_XmitFragment));
}
Code_t ZSrvSendRawList(ZNotice_t *notice,
char *list[],
int nitems,
Code_t (*send_routine)(ZNotice_t *, char *, int, int))
{
Code_t retval;
ZNotice_t newnotice;
char *buffer;
int len;
if ((retval = ZFormatRawNoticeList(notice, list, nitems, &buffer,
&len)) != ZERR_NONE)
return (retval);
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
retval = Z_SendFragmentedNotice(&newnotice, len, NULL, send_routine);
free(buffer);
return (retval);
}

39
lib/ZSendRaw.c Normal file
View File

@ -0,0 +1,39 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSendRawNotice function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSendRawNotice_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZSendRawNotice(ZNotice_t *notice)
{
Code_t retval;
ZNotice_t newnotice;
char *buffer;
int len;
if ((retval = ZFormatRawNotice(notice, &buffer, &len)) !=
ZERR_NONE)
return (retval);
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
retval = Z_SendFragmentedNotice(&newnotice, len, NULL, Z_XmitFragment);
free(buffer);
return (retval);
}

27
lib/ZSetDest.c Normal file
View File

@ -0,0 +1,27 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSetDestAddr function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSetDestAddr_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZSetDestAddr(struct sockaddr_in *addr)
{
__HM_addr = *addr;
__HM_set = 1;
return (ZERR_NONE);
}

28
lib/ZSetFD.c Normal file
View File

@ -0,0 +1,28 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSetFD function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSetFD_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZSetFD(int fd)
{
(void) ZClosePort();
__Zephyr_fd = fd;
__Zephyr_open = 0;
return (ZERR_NONE);
}

25
lib/ZSetSrv.c Normal file
View File

@ -0,0 +1,25 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSetServerState function.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZSetServerState_c[] = "$Id$";
#endif
#include <internal.h>
Code_t
ZSetServerState(int state)
{
__Zephyr_server = state;
return (ZERR_NONE);
}

258
lib/ZSubs.c Normal file
View File

@ -0,0 +1,258 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZSubscribeTo, ZUnsubscribeTo, and
* ZCancelSubscriptions functions.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#ifndef lint
static const char rcsid_ZSubscriptions_c[] = "$Id$";
#endif
static Code_t Z_SendAndWaitForServer(ZNotice_t *notice, char *buf, int len,
int waitforack);
#ifdef CMU_ZCTL_PUNT
Code_t
ZPunt(ZSubscription_t *sublist,
int nitems,
unsigned int port)
{
return (ZSubscriptions(sublist, nitems, port, "SUPPRESS",
Z_SendAndWaitForServer));
}
#endif
Code_t
ZSubscribeTo(ZSubscription_t *sublist,
int nitems,
unsigned int port)
{
return (ZSubscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE,
Z_SendAndWaitForServer));
}
Code_t
ZSubscribeToSansDefaults(ZSubscription_t *sublist,
int nitems,
unsigned int port)
{
return (ZSubscriptions(sublist, nitems, port, CLIENT_SUBSCRIBE_NODEFS,
Z_SendAndWaitForServer));
}
Code_t
ZUnsubscribeTo(ZSubscription_t *sublist,
int nitems,
unsigned int port)
{
return (ZSubscriptions(sublist, nitems, port, CLIENT_UNSUBSCRIBE,
Z_SendAndWaitForServer));
}
Code_t
ZCancelSubscriptions(unsigned int port)
{
return (ZSubscriptions((ZSubscription_t *)0, 0, port, CLIENT_CANCELSUB,
Z_SendAndWaitForServer));
}
/*
* This routine must do its own fragmentation. Subscriptions must
* not be broken across packet boundaries, or else the server will
* mis-interpret them.
*/
Code_t
ZSubscriptions(register ZSubscription_t *sublist,
int nitems,
unsigned int port,
char *opcode,
Code_t (*send_routine)(ZNotice_t *, char *, int, int))
{
register int i, j;
int retval;
ZNotice_t notice;
char header[Z_MAXHEADERLEN];
char **list;
char *recip;
int hdrlen;
/* Space available for data, adjusted below. Take off Z_FRAGFUDGE twice.
The first is to account for Z_SendFragmentedNotice's space. The second
to account for hdrlen not being constant. Zcode escapes bytes 0x00 and
0xFF, so some bytes are encoded as two bytes. */
int size_avail = Z_MAXPKTLEN-Z_FRAGFUDGE-Z_FRAGFUDGE;
int size, start, numok;
Z_AuthProc cert_routine;
/* nitems = 0 means cancel all subscriptions; still need to allocate a */
/* array for one item so we can cancel, however. */
list = (char **)malloc((unsigned)((nitems==0)?1:nitems)*3*sizeof(char *));
if (!list)
return (ENOMEM);
(void) memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = ACKED;
notice.z_port = port;
notice.z_class = ZEPHYR_CTL_CLASS;
notice.z_class_inst = ZEPHYR_CTL_CLIENT;
notice.z_opcode = opcode;
notice.z_sender = 0;
notice.z_recipient = "";
notice.z_default_format = "";
notice.z_message_len = 0;
/* format the header to figure out how long it is */
retval = Z_FormatHeader(&notice, header, sizeof(header), &hdrlen, ZAUTH);
if (retval != ZERR_NONE) {
free((char *)list);
return(retval);
}
/* if a subscription request, we save the key */
if (strcmp(opcode, CLIENT_SUBSCRIBE) == 0 ||
strcmp(opcode, CLIENT_SUBSCRIBE_NODEFS) == 0) {
cert_routine = ZSUBAUTH;
} else {
cert_routine = ZAUTH;
}
/* compute amount of room left */
size_avail -= hdrlen;
size = size_avail;
/* assemble subs into an array of pointers */
for (i=0;i<nitems;i++) {
list[i*3] = sublist[i].zsub_class;
list[i*3+1] = sublist[i].zsub_classinst;
recip = sublist[i].zsub_recipient;
if (recip && *recip == '*')
recip++;
if (!recip || (*recip != 0 && *recip != '@'))
recip = ZGetSender();
list[i*3+2] = recip;
}
start = -1;
i = 0;
numok = 0;
if (!nitems) {
/* there aren't really any, but we need to xmit anyway */
retval = ZSrvSendList(&notice, list, 0, cert_routine, send_routine);
free((char *)list);
return(retval);
}
while(i < nitems) {
if (start == -1) {
size = size_avail;
start = i;
numok = 0;
}
if ((j = strlen(list[i*3])
+ strlen(list[i*3+1])
+ strlen(list[i*3+2]) + 3) <= size) {
/* it will fit in this packet */
size -= j;
numok++;
i++;
continue;
}
if (!numok) { /* a single subscription won't
fit into one packet */
free((char *)list);
return(ZERR_FIELDLEN);
}
retval = ZSrvSendList(&notice, &list[start*3], numok * 3,
cert_routine, send_routine);
if (retval) {
free((char *)list);
return(retval);
}
start = -1;
}
if (numok)
retval = ZSrvSendList(&notice, &list[start*3], numok * 3,
cert_routine, send_routine);
free((char *)list);
return(retval);
}
static Code_t
Z_SendAndWaitForServer(ZNotice_t *notice,
char *buf, int len,
int waitforack)
{
Code_t retval;
ZNotice_t retnotice;
retval = ZSendPacket(buf, len, waitforack);
if (retval != ZERR_NONE)
return (retval);
/* Z_ReadWait drops non-initial SERVACKs and SERVNAKs on the floor. We
should never see a non-initial one here, but be defensive about bugs in the
sharding code above. */
if (!ZCompareUID(&notice->z_multiuid, &notice->z_uid))
return (retval);
if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0,
ZCompareUIDPred, (char *)&notice->z_uid)) !=
ZERR_NONE)
return (retval);
if (retnotice.z_kind == SERVNAK) {
ZFreeNotice(&retnotice);
return (ZERR_SERVNAK);
}
if (retnotice.z_kind != SERVACK) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
ZFreeNotice(&retnotice);
return (ZERR_NONE);
}
Code_t
ZFlushUserSubscriptions(char *recip)
{
register Code_t retval;
ZNotice_t notice, retnotice;
(void)memset((char *)&notice, 0, sizeof(notice));
notice.z_kind = ACKED;
notice.z_class = ZEPHYR_CTL_CLASS;
notice.z_class_inst = ZEPHYR_CTL_CLIENT;
notice.z_opcode = CLIENT_FLUSHSUBS;
notice.z_recipient = "";
notice.z_default_format = "";
if (recip) {
notice.z_message = recip;
notice.z_message_len = strlen(recip) + 1;
} else {
notice.z_message_len = 0;
}
if ((retval = ZSendNotice(&notice, ZAUTH)) != ZERR_NONE)
return (retval);
if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *)0,
ZCompareUIDPred, (char *)&notice.z_uid)) !=
ZERR_NONE)
return (retval);
if (retnotice.z_kind == SERVNAK) {
ZFreeNotice(&retnotice);
return (ZERR_SERVNAK);
}
if (retnotice.z_kind != SERVACK) {
ZFreeNotice(&retnotice);
return (ZERR_INTERNAL);
}
ZFreeNotice(&retnotice);
return (ZERR_NONE);
}

195
lib/ZVariables.c Normal file
View File

@ -0,0 +1,195 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetVariable, ZSetVariable, and ZUnsetVariable
* functions.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_ZVariables_c[] = "$Id$";
#endif
#include <internal.h>
#include <ctype.h>
#include <pwd.h>
Code_t get_localvarfile(char *bfr);
static char *get_varval(char *fn, char *val);
static int varline(char *bfr, char *var);
char *
ZGetVariable(char *var)
{
char varfile[128], *ret;
Code_t code;
code = get_localvarfile(varfile);
if (code)
return ((char *)0);
if ((ret = get_varval(varfile, var)) != ZERR_NONE)
return (ret);
sprintf(varfile, "%s/zephyr/zephyr.vars", SYSCONFDIR);
return (get_varval(varfile, var));
}
Code_t
ZSetVariable(char *var, char *value)
{
int written;
FILE *fpin, *fpout;
char varfile[128], varfilebackup[128], varbfr[512];
Code_t code;
written = 0;
code = get_localvarfile(varfile);
if (code)
return code;
(void) strcpy(varfilebackup, varfile);
(void) strcat(varfilebackup, ".backup");
if (!(fpout = fopen(varfilebackup, "w")))
return (errno);
if ((fpin = fopen(varfile, "r")) != NULL) {
while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
if (varbfr[strlen(varbfr)-1] < ' ')
varbfr[strlen(varbfr)-1] = '\0';
if (varline(varbfr, var)) {
fprintf(fpout, "%s = %s\n", var, value);
written = 1;
}
else
fprintf(fpout, "%s\n", varbfr);
}
(void) fclose(fpin); /* don't care about errs on input */
}
if (!written)
fprintf(fpout, "%s = %s\n", var, value);
if (fclose(fpout) == EOF)
return(EIO); /* can't rely on errno */
if (rename(varfilebackup, varfile))
return (errno);
return (ZERR_NONE);
}
Code_t
ZUnsetVariable(char *var)
{
FILE *fpin, *fpout;
char varfile[128], varfilebackup[128], varbfr[512];
Code_t code;
code = get_localvarfile(varfile);
if (code)
return code;
(void) strcpy(varfilebackup, varfile);
(void) strcat(varfilebackup, ".backup");
if (!(fpout = fopen(varfilebackup, "w")))
return (errno);
if ((fpin = fopen(varfile, "r")) != NULL) {
while (fgets(varbfr, sizeof varbfr, fpin) != (char *) 0) {
if (varbfr[strlen(varbfr)-1] < ' ')
varbfr[strlen(varbfr)-1] = '\0';
if (!varline(varbfr, var))
fprintf(fpout, "%s\n", varbfr);
}
(void) fclose(fpin); /* don't care about read close errs */
}
if (fclose(fpout) == EOF)
return(EIO); /* errno isn't reliable */
if (rename(varfilebackup, varfile))
return (errno);
return (ZERR_NONE);
}
Code_t
get_localvarfile(char *bfr)
{
char *envptr;
struct passwd *pwd;
envptr = getenv("ZEPHYR_VARS");
if (envptr)
(void) strcpy(bfr, envptr);
else {
envptr = getenv("HOME");
if (envptr)
(void) strcpy(bfr, envptr);
else {
if (!(pwd = getpwuid((int) getuid())))
return errno;
(void) strcpy(bfr, pwd->pw_dir);
}
(void) strcat(bfr, "/");
(void) strcat(bfr, ".zephyr.vars");
}
return (0);
}
static char *
get_varval(char *fn, char *var)
{
FILE *fp;
static char varbfr[512];
int i;
fp = fopen(fn, "r");
if (!fp)
return ((char *)0);
while (fgets(varbfr, sizeof varbfr, fp) != (char *) 0) {
if (varbfr[strlen(varbfr)-1] < ' ')
varbfr[strlen(varbfr)-1] = '\0';
if (!(i = varline(varbfr, var)))
continue;
(void) fclose(fp); /* open read-only, don't care */
return (varbfr+i);
}
(void) fclose(fp); /* open read-only, don't care */
return ((char *)0);
}
/* If the variable in the line bfr[] is the same as var, return index to
the variable value, else return 0. */
static int
varline(char *bfr, char *var)
{
register char *cp;
size_t namelen;
if (!bfr[0] || bfr[0] == '#') /* comment or null line */
return (0);
cp = bfr;
while (*cp && !isspace(*cp) && (*cp != '='))
cp++;
#define max(a,b) ((a > b) ? (a) : (b))
namelen = cp - bfr;
if (strncasecmp(bfr, var, max(strlen(var), namelen)))
return(0); /* var is not the var in
bfr ==> no match */
cp = strchr(bfr, '=');
if (!cp)
return(0);
cp++;
while (*cp && isspace(*cp)) /* space up to variable value */
cp++;
return (cp - bfr); /* return index */
}

70
lib/ZWait4Not.c Normal file
View File

@ -0,0 +1,70 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains the ZCheckIfNotice/select loop used for waiting for
* a notice, with a timeout.
*
* Created by: <Joe Random Hacker>
*
* $Id$
*
* Copyright (c) 1991 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include "mit-copyright.h"
#ifndef lint
static const char rcsid_ZWaitForNotice_c[] = "$Id$";
#endif
#include <internal.h>
#include <sys/socket.h>
Code_t
Z_WaitForNotice(ZNotice_t *notice,
int (*pred) __P((ZNotice_t *, void *)),
void *arg,
int timeout)
{
Code_t retval;
struct timeval tv, t0;
fd_set fdmask;
int i, fd;
retval = ZCheckIfNotice (notice, (struct sockaddr_in *) 0, pred,
(char *) arg);
if (retval == ZERR_NONE)
return ZERR_NONE;
if (retval != ZERR_NONOTICE)
return retval;
fd = ZGetFD ();
FD_ZERO (&fdmask);
tv.tv_sec = timeout;
tv.tv_usec = 0;
gettimeofday (&t0, (struct timezone *) 0);
t0.tv_sec += timeout;
while (1) {
FD_SET (fd, &fdmask);
i = select (fd + 1, &fdmask, (fd_set *) 0, (fd_set *) 0, &tv);
if (i == 0)
return ETIMEDOUT;
if (i < 0 && errno != EINTR)
return errno;
if (i > 0) {
retval = ZCheckIfNotice (notice, (struct sockaddr_in *) 0, pred,
(char *) arg);
if (retval != ZERR_NONOTICE) /* includes ZERR_NONE */
return retval;
}
gettimeofday (&tv, (struct timezone *) 0);
tv.tv_usec = t0.tv_usec - tv.tv_usec;
if (tv.tv_usec < 0) {
tv.tv_usec += 1000000;
tv.tv_sec = t0.tv_sec - tv.tv_sec - 1;
}
else
tv.tv_sec = t0.tv_sec - tv.tv_sec;
}
/*NOTREACHED*/
}

72
lib/ZhmStat.c Normal file
View File

@ -0,0 +1,72 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains the ZhmStat() function.
*
* Created by: Marc Horowitz
*
* $Id$
*
* Copyright (c) 1996 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <internal.h>
#include <sys/socket.h>
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001
#endif
Code_t
ZhmStat(struct in_addr *hostaddr,
ZNotice_t *notice)
{
struct servent *sp;
struct sockaddr_in sin;
ZNotice_t req;
Code_t code;
struct timeval tv;
fd_set readers;
(void) memset((char *)&sin, 0, sizeof(struct sockaddr_in));
sp = getservbyname(HM_SVCNAME, "udp");
sin.sin_port = (sp) ? sp->s_port : HM_SVC_FALLBACK;
sin.sin_family = AF_INET;
if (hostaddr)
sin.sin_addr = *hostaddr;
else
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
(void) memset((char *)&req, 0, sizeof(req));
req.z_kind = STAT;
req.z_port = 0;
req.z_class = HM_STAT_CLASS;
req.z_class_inst = HM_STAT_CLIENT;
req.z_opcode = HM_GIMMESTATS;
req.z_sender = "";
req.z_recipient = "";
req.z_default_format = "";
req.z_message_len = 0;
if ((code = ZSetDestAddr(&sin)) != ZERR_NONE)
return(code);
if ((code = ZSendNotice(&req, ZNOAUTH)) != ZERR_NONE)
return(code);
/* Wait up to ten seconds for a response. */
FD_ZERO(&readers);
FD_SET(ZGetFD(), &readers);
tv.tv_sec = 10;
tv.tv_usec = 0;
code = select(ZGetFD() + 1, &readers, NULL, NULL, &tv);
if (code < 0 && errno != EINTR)
return(errno);
if (code == 0 || (code < 0 && errno == EINTR) || ZPending() == 0)
return(ZERR_HMDEAD);
return(ZReceiveNotice(notice, (struct sockaddr_in *) 0));
}

1422
lib/Zinternal.c Normal file

File diff suppressed because it is too large Load Diff

139
lib/charset.c Normal file
View File

@ -0,0 +1,139 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains source for the ZGetCharset function.
*
* Created by: Karl Ramm
*
* $Id$
*
* Copyright (c) 2009 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#ifndef lint
static const char rcsid_charset_c[] = "$Id$";
#endif /* lint */
#include <internal.h>
#include <string.h>
#include <locale.h>
#include <langinfo.h>
#include <ctype.h>
#include <iconv.h>
#include <errno.h>
const char *
ZGetCharsetString(char *charset)
{
char *p;
static int once = 1;
if (charset == NULL)
charset = getenv("ZEPHYR_CHARSET");
if (charset == NULL) {
if (once) {
setlocale(LC_ALL, "");
once = 0;
}
charset = nl_langinfo(CODESET);
}
if (charset == NULL)
return ZCHARSET_UNKNOWN;
charset = strdup(charset);
for (p = charset; *p; p++)
*p = toupper(*p);
return charset;
}
unsigned short
ZGetCharset(char *charset)
{
short retval;
charset = (char *)ZGetCharsetString(charset);
if (!strcmp(charset, "NONE") || !strcmp(charset, "UNKNOWN"))
retval = ZCHARSET_UNKNOWN;
else if (!strcmp(charset, "ANSI_X3.4-1968"))
retval = ZCHARSET_ISO_8859_1; /* A hack. */
else if (!strcmp(charset, "ISO-8859-1"))
retval = ZCHARSET_ISO_8859_1;
else if (!strcmp(charset, "UTF-8"))
retval = ZCHARSET_UTF_8;
else
retval = ZCHARSET_UNKNOWN;
free(charset);
return retval;
}
const char *
ZCharsetToString(unsigned short charset)
{
if (charset == ZCHARSET_UNKNOWN)
return "UNKNOWN";
else if (charset == ZCHARSET_ISO_8859_1)
return "ISO-8859-1";
else if (charset == ZCHARSET_UTF_8)
return "UTF-8";
return "UNKNOWN";
}
Code_t
ZTransliterate(char *in, int inlen, char *inset, char *outset, char **out, int *outlen)
{
iconv_t ih;
char *outset_t, *inp, *outp;
int retval;
size_t size, inleft, outleft;
*out = NULL;
*outlen = 0;
outset_t = malloc(strlen(outset) + 11);
if (outset_t == NULL)
return errno;
sprintf(outset_t, "%s//TRANSLIT", outset);
ih = iconv_open(outset_t, inset);
free(outset_t);
if (ih == (iconv_t)-1)
return errno;
size = inlen; /* doubling this should be enough, but.. */
do {
size = size * 2;
*out = malloc(size);
if (*out == NULL) {
iconv_close(ih);
return errno;
}
inleft = inlen;
outleft = size;
inp = in;
outp = *out;
retval = iconv(ih, &inp, &inleft, &outp, &outleft);
if (retval < 0)
free(*out);
} while (retval < 0 && errno == E2BIG);
iconv_close(ih);
if (retval < 0)
return errno;
*outlen = size - outleft;
return ZERR_NONE;
}

24
lib/mit-copyright.h Normal file
View File

@ -0,0 +1,24 @@
/*
Copyright 1987,1988 by the Massachusetts Institute of Technology
All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the Massachusetts
Institute of Technology (M.I.T.) not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
*/

196
lib/quad_cksum.c Normal file
View File

@ -0,0 +1,196 @@
/* Lifted from the krb5 1.6 source tree and hacked slightly to fit in here
Karl Ramm 12/21/08 */
/*
* lib/des425/quad_cksum.c
*
* Copyright 1985, 1986, 1987, 1988,1990 by the Massachusetts Institute
* of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*
* This routine does not implement:
*
*
* Quadratic Congruential Manipulation Dectection Code
*
* ref: "Message Authentication"
* R.R. Jueneman, S. M. Matyas, C.H. Meyer
* IEEE Communications Magazine,
* Sept 1985 Vol 23 No 9 p 29-40
*
* This routine, part of the Athena DES library built for the Kerberos
* authentication system, calculates a manipulation detection code for
* a message. It is a much faster alternative to the DES-checksum
* method. No guarantees are offered for its security.
*
* Implementation for 4.2bsd
* by S.P. Miller Project Athena/MIT
*/
/*
* Algorithm (per paper):
* define:
* message to be composed of n m-bit blocks X1,...,Xn
* optional secret seed S in block X1
* MDC in block Xn+1
* prime modulus N
* accumulator Z
* initial (secret) value of accumulator C
* N, C, and S are known at both ends
* C and , optionally, S, are hidden from the end users
* then
* (read array references as subscripts over time)
* Z[0] = c;
* for i = 1...n
* Z[i] = (Z[i+1] + X[i])**2 modulo N
* X[n+1] = Z[n] = MDC
*
* Then pick
* N = 2**31 -1
* m = 16
* iterate 4 times over plaintext, also use Zn
* from iteration j as seed for iteration j+1,
* total MDC is then a 128 bit array of the four
* Zn;
*
* return the last Zn and optionally, all
* four as output args.
*
* Modifications:
* To inhibit brute force searches of the seed space, this
* implementation is modified to have
* Z = 64 bit accumulator
* C = 64 bit C seed
* N = 2**63 - 1
* S = S seed is not implemented here
* arithmetic is not quite real double integer precision, since we
* cant get at the carry or high order results from multiply,
* but nontheless is 64 bit arithmetic.
*/
/*
* This code purports to implement the above algorithm, but fails.
*
* First of all, there was an implicit mod 2**32 being done on the
* machines where this was developed because of their word sizes, and
* for compabitility this has to be done on machines with 64-bit
* words, so we make it explicit.
*
* Second, in the squaring operation, I really doubt the carry-over
* from the low 31-bit half of the accumulator is being done right,
* and using a modulus of 0x7fffffff on the low half of the
* accumulator seems completely wrong. And I challenge anyone to
* explain where the number 83653421 comes from.
*
* --Ken Raeburn 2001-04-06
*/
/* System include files */
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <internal.h>
/* Definitions for byte swapping */
/* vax byte order is LSB first. This is not performance critical, and
is far more readable this way. */
#define four_bytes_vax_to_nets(x) ((((((x[3]<<8)|x[2])<<8)|x[1])<<8)|x[0])
#define vaxtohl(x) four_bytes_vax_to_nets(((const unsigned char *)(x)))
#define two_bytes_vax_to_nets(x) ((x[1]<<8)|x[0])
#define vaxtohs(x) two_bytes_vax_to_nets(((const unsigned char *)(x)))
/*** Routines ***************************************************** */
#ifdef HAVE_KRB5
unsigned long
z_quad_cksum(const unsigned char *in, /* input block */
uint32_t *out, /* optional longer output */
long length, /* original length in bytes */
int out_count, /* number of iterations */
unsigned char *c_seed /* secret seed, 8 bytes */
)
{
/*
* this routine both returns the low order of the final (last in
* time) 32bits of the checksum, and if "out" is not a null
* pointer, a longer version, up to entire 32 bytes of the
* checksum is written unto the address pointed to.
*/
register uint32_t z;
register uint32_t z2;
register uint32_t x;
register uint32_t x2;
const unsigned char *p;
register int32_t len;
register int i;
/* use all 8 bytes of seed */
z = vaxtohl(c_seed);
z2 = vaxtohl((const char *)c_seed+4);
if (out == NULL)
out_count = 1; /* default */
/* This is repeated n times!! */
for (i = 1; i <=4 && i<= out_count; i++) {
len = length;
p = in;
while (len) {
/*
* X = Z + Input ... sort of. Carry out from low half
* isn't done, so we're using all 32 bits of x now.
*/
if (len > 1) {
x = (z + vaxtohs(p));
p += 2;
len -= 2;
}
else {
x = (z + *(const unsigned char *)p++);
len = 0;
}
x2 = z2;
/*
* I think this is supposed to be a squaring operation.
* What it really is, I haven't figured out yet.
*
* Explicit mod 2**32 is for backwards compatibility. Why
* mod 0x7fffffff and not 0x80000000 on the low half of
* the (supposed) accumulator? And where does the number
* 83653421 come from??
*/
z = (((x * x) + (x2 * x2)) & 0xffffffff) % 0x7fffffff;
z2 = ((x * (x2+83653421)) & 0xffffffff) % 0x7fffffff; /* modulo */
}
if (out != NULL) {
*out++ = z;
*out++ = z2;
}
}
/* return final z value as 32 bit version of checksum */
return z;
}
#endif

64
lib/smwgc.c Normal file
View File

@ -0,0 +1,64 @@
/* Copyright (c) 1988 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*/
#include <zephyr/zephyr.h>
main()
{
FILE *fp;
char buf[512],*ptr;
int auth,retval;
u_short port;
ZNotice_t notice;
ZSubscription_t sub;
struct sockaddr_in from;
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err("foo",retval,"initing");
exit(1);
}
port = 0;
if ((retval = ZOpenPort(&port)) != ZERR_NONE) {
com_err("foo",retval,"opening port");
exit(1);
}
printf("Using port %d\n",(int)port);
sprintf(buf,"/tmp/wg.%d",getuid());
fp = fopen(buf,"w");
if (!fp) {
com_err("foo",errno,"opening file");
exit(1);
}
fprintf(fp,"%d\n",(int)port);
fclose(fp);
printf("All ready...\n");
sub.class = "MESSAGE";
sub.classinst = "PERSONAL";
sub.recipient = ZGetSender();
if ((retval = ZSubscribeTo(&sub,1,port)) != ZERR_NONE) {
com_err("foo",retval,"subscribing");
exit(1);
}
for (;;) {
if ((retval = ZReceiveNotice(&notice,&from)) != ZERR_NONE) {
com_err("foo",retval,"receiving packet");
continue;
}
auth = ZCheckAuthentication(&notice,&from);
printf("Class = %s Instance = %s Sender = %s\nTime = %s Auth = %d\n",
notice.z_class,notice.z_class_inst,notice.z_sender,
ctime(&notice.z_time.tv_sec),auth);
printf("Len = %d\n",notice.z_message_len);
/* ptr = notice.z_message;
for (;ptr<notice.z_message+notice.z_message_len;) {
printf("%s\n",ptr);
ptr += strlen(ptr)+1;
}
printf("\n");*/
ZFreeNotice(&notice);
}
}

93
lib/zephyr.1 Normal file
View File

@ -0,0 +1,93 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.TH ZEPHYR 1 "July 1, 1988" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zephyr \- Zephyr Notification Service
.SH DESCRIPTION
.PP
Zephyr is a notice transport and delivery system developed at MIT
which runs under 4.3BSD Unix.
.PP
A Notice Transport and Delivery system is a method of getting small
quantities of time sensitive information efficiently from one client
(or server) on a network to another. The object is to accomplish this
with the highest possible fan-out (i.e., client to server ratio) while
maintaining both network and server performance. Zephyr is a
multi-cast notice transport and delivery system based upon an
authenticated datagram protocol. Localized Zephyr servers provide
routing, queueing and dispatching services to clients which
communicate with them via the Zephyr Client Library. Two special
purpose Zephyr clients, the WindowGram client and the HostManager
client provide user and client host communication support.
.PP
.I Zephyrd(8)
servers run on designated server machines. These servers maintain a
database of subscriptions and locations for every user using Zephyr.
The servers stay in contact with one another, and provide a reliable
backup system (via duplication) in the event of network failures.
.PP
Each client machine on the network runs a
.I zhm(8)
HostManager client program which is the link between the Zephyr
servers and the users. User programs send notices to the HostManager,
and the HostManager forwards these notices to the nearest server for
action. The HostManager is responsible for ensuring that the notices
reach a server, and for finding a new one if its server fails to respond.
.PP
Each user on the network usually runs a WindowGram client program
automatically upon login.
.I Zwgc(1)
displays notices to the user, and handles user
responses. Only notices to which the user has subscribed will be sent
to the WindowGram client.
.PP
Subscriptions are handled through the
.I zctl(1)
program. This program allows the user to add or delete subscriptions
from Zephyr, to add the subscriptions to a file, and to perform other
miscellaneous functions.
.SH SEE ALSO
kerberosintro(1)
.br
zaway(1), zctl(1), zleave(1), zlocate(1), znol(1), zwgc(1),
zwrite(1), zmailnotify(1)
.br
zhm(8), zephyrd(8), zinit(8), zstat(8), zpopnotify(8),
zshutdown_notify(8), syslogd(8)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH AUTHORS
.PP
.br
Tony Della Fera (MIT-Project Athena, DEC),
Mark W. Eichin (MIT-Project Athena),
Robert S. French (MIT-Project Athena),
David C. Jedlinsky (MIT-Project Athena),
John T. Kohl (MIT-Project Athena, DEC),
William E. Sommerfeld (MIT-Project Athena).
.SH RESTRICTIONS
Copyright (c) 1987,1988,1989 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of the Massachusetts
Institute of Technology not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
.br
M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.

57
lib/zephyr_err.et Normal file
View File

@ -0,0 +1,57 @@
# Copyright 1987,1988 Massachusetts Institute of Technology
#
# For copying and distribution information, see the file
# "mit-copyright.h".
#
# $Id$
#
et zeph
ec ZERR_PKTLEN,
"Packet too long or buffer too small"
ec ZERR_HEADERLEN,
"Notice header too large"
ec ZERR_ILLVAL,
"Illegal value in notice"
ec ZERR_HMPORT,
"Can't get host manager port"
ec ZERR_PORTINUSE,
"Can't assign port"
ec ZERR_BADPKT,
"Bad packet format"
ec ZERR_VERS,
"Incompatible version numbers"
ec ZERR_NOPORT,
"No port opened"
ec ZERR_NONOTICE,
"No notices match criteria"
ec ZERR_QLEN,
"Input queue too long"
ec ZERR_HMDEAD,
"Hostmanager not responding"
ec ZERR_INTERNAL,
"Internal error"
ec ZERR_NOLOCATIONS,
"No previous call to ZLocateUser"
ec ZERR_NOMORELOCS,
"No more locations available"
ec ZERR_FIELDLEN,
"Field too long for buffer"
ec ZERR_BADFIELD,
"Improperly formatted field"
ec ZERR_SERVNAK,
"SERVNAK received"
ec ZERR_AUTHFAIL,
"Server could not verify authentication"
ec ZERR_LOGINFAIL,
"Not logged-in"
ec ZERR_NOSUBSCRIPTIONS,
"No previous call to ZRetrieveSubscriptions"
ec ZERR_NOMORESUBSCRIPTIONS,
"No more subscriptions available"
ec ZERR_TOOMANYSUBS,
"Too many subscriptions to transmit"
ec ZERR_EOF,
"End of file detected during read"
end

12
lib/zephyr_run_doctests Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/python
import sys, doctest
failures, tests = doctest.testfile("zephyr_tests.txt")
print failures, 'failures out of', tests, 'tests.'
if failures:
sys.exit(1)

187
lib/zephyr_tests.py Executable file
View File

@ -0,0 +1,187 @@
#!/usr/bin/python
# zephyr test suite
#
# Operates on libraries in the build tree. To test purely internal
# interfaces, stuff them in a testing library...
"""Test Suite for libzephyr"""
import optparse
import os
import socket
import ctypes
import ctypes.util
import time
from ctypes import c_int, c_char, POINTER, c_char_p, sizeof
from zephyr_ctypes import *
__revision__ = "$Id$"
try:
__version__ = "%s/%s" % (__revision__.split()[3], __revision__.split()[2])
except IndexError:
__version__ = "unknown"
# TODO: pick some real framework later, we're just poking around for now
class TestSuite(object):
"""test collection and runner"""
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
def run(self):
tests = sorted([testname for testname in dir(self)
if testname.startswith("test_")])
failures = []
for test in tests:
try:
print "===", "starting", test, "==="
getattr(self, test)()
print "===", "done", test, "==="
except TestFailure, tf:
print "===", "FAILED", test, "==="
failures.append([test, tf])
return failures
class TestFailure(Exception):
pass
def py_make_ascii(input):
"""reference ZMakeAscii expressed as python..."""
hexes = ["%02X" % ord(ch) for ch in input]
output = []
for i in range(0, len(hexes), 4):
output.append("0x" + "".join(hexes[i:i+4]))
return " ".join(output)
def py_make_zcode(input):
"""reference ZMakeZcode expressed as python..."""
return "Z" + input.replace("\xff", "\xff\xf1").replace("\0", "\xff\xf0")
def find_libzephyr(builddir='.'):
# find the library
libzephyr_paths = ['libzephyr.so', 'libzephyr.dylib']
libzephyr_paths += [os.path.join('.libs', i) for i in libzephyr_paths]
libzephyr_paths = [os.path.join(builddir, i) for i in libzephyr_paths]
libzephyr_paths = [i for i in libzephyr_paths if os.path.exists(i)]
return libzephyr_paths[0]
class ZephyrTestSuite(TestSuite):
"""Tests for libzephyr"""
def setup(self):
self._libzephyr = libZephyr(find_libzephyr(self.builddir))
def cleanup(self):
# no cleanup needed yet
pass
def test_zinit(self):
"""test that ZInitialize did something"""
print "fd", self._libzephyr.ZGetFD()
realm = self._libzephyr.ZGetRealm()
print "realm", realm
if not realm:
raise TestFailure("empty realm %s" % realm)
if self._libzephyr.Zauthtype and realm == 'local-realm':
raise TestFailure("useless realm %s" % realm)
if self._libzephyr.Zauthtype == 0 and realm != 'local-realm':
raise TestFailure("wrong realm %s (should be local-realm)" % realm)
print self._libzephyr.ZGetSender()
def test_notices(self):
"""test notice construct/destruct"""
notice = ZNotice_t()
print "sizeof ZNotice_t", sizeof(notice)
zbuf = c_char_p(0)
zbuflen = c_int(0)
st = self._libzephyr.ZFormatNotice(notice, zbuf, zbuflen, ZNOAUTH)
print "ZFormatNotice:", "retval", st
print "\tzbuflen", zbuflen
print "\tzbuf", repr(zbuf.value)
new_notice = ZNotice_t()
st = self._libzephyr.ZParseNotice(zbuf, zbuflen, new_notice)
print "ZParseNotice:", "retval", st
print "\tz_version", new_notice.z_version
ctypes_pprint(new_notice)
def test_z_compare_uid(self):
"""test ZCompareUID"""
uid1 = ZUnique_Id_t()
uid2 = ZUnique_Id_t()
assert self._libzephyr.ZCompareUID(uid1, uid2), "null uids don't match"
# there's no ZUnique_Id_t constructor - Z_FormatHeader and Z_NewFormatHeader initialize notice->z_uid directly
notice1 = ZNotice_t()
zbuf = c_char_p(0)
zbuflen = c_int(0)
st = self._libzephyr.ZFormatNotice(notice1, zbuf, zbuflen, ZNOAUTH)
assert st == 0, "ZFormatNotice notice1 failed"
notice2 = ZNotice_t()
zbuf = c_char_p(0)
zbuflen = c_int(0)
st = self._libzephyr.ZFormatNotice(notice2, zbuf, zbuflen, ZNOAUTH)
assert st == 0, "ZFormatNotice notice2 failed"
assert not self._libzephyr.ZCompareUID(notice1.z_uid, notice2.z_uid), "distinct notices don't compare as distinct"
# ctypes_pprint(notice1.z_uid)
def test_zauthtype(self):
"""Make sure Zauthtype is an acceptable value"""
assert self._libzephyr.Zauthtype in (0, 4, 5)
def test_z_expand_realm(self):
"""test ZExpandRealm"""
if self._libzephyr.Zauthtype:
assert self._libzephyr.ZExpandRealm("") == ""
assert self._libzephyr.ZExpandRealm("localhost") == ""
assert self._libzephyr.ZExpandRealm("bitsy.mit.edu") == "ATHENA.MIT.EDU"
else:
assert self._libzephyr.ZExpandRealm("") == ""
assert self._libzephyr.ZExpandRealm("localhost") == socket.getfqdn("localhost").upper()
assert self._libzephyr.ZExpandRealm("bitsy.mit.edu") == "BITSY.MIT.EDU"
def find_buildpath():
parser = optparse.OptionParser(usage=__doc__,
version = "%%prog %s" % __version__)
parser.add_option("--builddir", default="..",
help="where to find the top of the build tree")
parser.add_option("--verbose", "-v", action="store_true",
help="pass through for doctest.testfile")
opts, args = parser.parse_args()
assert not args, "no args yet"
return os.path.join(opts.builddir, "lib")
def getsockname(fd):
"""wrapped C lib getsocketname (works on raw fd)"""
libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))
call_getsockname = libc.getsockname
call_getsockname.argtypes = [
c_int, # int s
POINTER(sockaddr), # struct sockaddr *name
POINTER(c_int), # socklen_t *namelen
]
name = sockaddr(0)
namelen = c_int(sizeof(name))
ret = call_getsockname(fd, name, namelen)
if ret == 0:
return name
# we can't get at errno until python 2.6...
print ret
raise EnvironmentError("getsockname failed")
if __name__ == "__main__":
tester = ZephyrTestSuite(builddir=find_buildpath())
tester.setup()
failures = tester.run()
tester.cleanup()
for failure, exc in failures:
print "FAIL:", failure, str(exc)

362
lib/zephyr_tests.txt Normal file
View File

@ -0,0 +1,362 @@
Zephyr Library Tests
This file is a collection of doctests for the zephyr library.
Minimum coverage goal is "every non-static function, and every data
structure that shows up in those function prototypes."
This file is also a test of the practicality of rich doctests as API
documentation. It will start out as a bunch of snippets, and later be
edited to use actual chapters and appendices - narrative structure
beyond "here's a test! here's another test!" At that point we'll also
pick a formatting language (probably ReStructured Text but for now, we
need no more than whitespace separated paragraphs to be
comprehensible.)
Generic library setup that should be moved into zephyr_tests.py:
>>> import os, socket
>>> import zephyr_tests
>>> buildpath = zephyr_tests.find_buildpath()
>>> libzephyr_path = zephyr_tests.find_libzephyr()
>>> _z = zephyr_tests.libZephyr(libzephyr_path)
ZInit() got run by libZephyr, internally. Make sure other things
actually got set up:
>>> assert _z.ZGetFD() == -1
>>> Zauthtype = _z.Zauthtype
>>> assert Zauthtype in (0, 4, 5)
>>> realm = _z.ZGetRealm()
>>> assert realm
>>> if Zauthtype: assert realm != 'local-realm'
>>> if not Zauthtype: assert realm == 'local-realm'
>>> assert _z.ZGetSender()
>>> assert "@" in _z.ZGetSender()
ZNotice_t structure pseudo-round-trip (needs a lot more explicit
settings and assertions to be a real round-trip test...)
>>> notice = zephyr_tests.ZNotice_t()
>>> from ctypes import sizeof
>>> assert sizeof(notice) > 150
>>> from ctypes import c_char_p, c_int
>>> zbuf = c_char_p(0)
>>> zbuflen = c_int(0)
>>> st = _z.ZFormatNotice(notice, zbuf, zbuflen, zephyr_tests.ZNOAUTH)
>>> assert st == 0
>>> assert zbuf.value.startswith("ZEPH")
>>> new_notice = zephyr_tests.ZNotice_t()
>>> st = _z.ZParseNotice(zbuf, zbuflen, new_notice)
>>> assert st == 0
>>> assert new_notice.z_version.startswith("ZEPH")
Should we check for ZEPH0.2 now, or leave that open?
>>> notice = zephyr_tests.ZNotice_t()
>>> notice.z_kind = zephyr_tests.ZNotice_Kind_t.UNSAFE
>>> notice.z_class = c_char_p("testclass")
>>> notice.z_class_inst = c_char_p("testinstance")
>>> notice.z_opcode = c_char_p("TESTOPCODE")
>>> notice.z_sender = c_char_p("someone")
>>> notice.z_recipient = c_char_p("someone_else")
>>> notice.z_message = c_char_p("short message body")
>>> notice.z_message_len = c_int(len("short message body"))
>>> zbuf = c_char_p(0)
>>> zbuflen = c_int(0)
>>> st = _z.ZFormatNotice(notice, zbuf, zbuflen, zephyr_tests.ZNOAUTH)
>>> assert st == 0
>>> assert zbuf.value.startswith("ZEPH")
>>> new_notice = zephyr_tests.ZNotice_t()
>>> st = _z.ZParseNotice(zbuf, zbuflen, new_notice)
>>> assert st == 0
>>> assert new_notice.z_version.startswith("ZEPH")
>>> new_notice.z_class
'testclass'
>>> new_notice.z_class_inst
'testinstance'
>>> new_notice.z_opcode
'TESTOPCODE'
>>> new_notice.z_message[:new_notice.z_message_len]
'short message body'
Simple test of ZCompareUID:
>>> uid1 = zephyr_tests.ZUnique_Id_t()
>>> uid2 = zephyr_tests.ZUnique_Id_t()
>>> assert _z.ZCompareUID(uid1, uid2), "null uids don't match"
There's no ZUnique_Id_t constructor - Z_FormatHeader and
Z_NewFormatHeader initialize notice->z_uid directly, so cheat and use
ZNotice_t as the constructor...
>>> notice1 = zephyr_tests.ZNotice_t()
>>> zbuf = c_char_p(0)
>>> zbuflen = c_int(0)
>>> st = _z.ZFormatNotice(notice1, zbuf, zbuflen, zephyr_tests.ZNOAUTH)
>>> assert st == 0, "ZFormatNotice notice1 failed"
>>> notice2 = zephyr_tests.ZNotice_t()
>>> zbuf = c_char_p(0)
>>> zbuflen = c_int(0)
>>> st = _z.ZFormatNotice(notice2, zbuf, zbuflen, zephyr_tests.ZNOAUTH)
>>> assert st == 0, "ZFormatNotice notice1 failed"
>>> assert not _z.ZCompareUID(notice1.z_uid, notice2.z_uid), "distinct notices don't compare as distinct"
Trivial test of ZExpandRealm, using terribly well known hostnames:
>>> assert _z.ZExpandRealm("") == ""
>>> if Zauthtype: assert _z.ZExpandRealm("localhost") == ""
>>> if Zauthtype: assert _z.ZExpandRealm("bitsy.mit.edu") == "ATHENA.MIT.EDU"
>>> if not Zauthtype: assert _z.ZExpandRealm("localhost") == socket.getfqdn("localhost").upper()
>>> if not Zauthtype: assert _z.ZExpandRealm("bitsy.mit.edu") == "BITSY.MIT.EDU"
ZGetCharsetString is a utility function for clients that need to know the
full name of the output character set, e.g. zwgc. Calling it
with NULL will get it from $ZEPHYR_CHARSET or the locale.
Trivial testing of ZGetCharsetString:
>>> os.environ['LANG'] = 'C'
>>> assert _z.ZGetCharsetString(None) == 'ANSI_X3.4-1968', "charset is " + _z.ZGetCharsetString(None)
>>> os.environ['ZEPHYR_CHARSET'] = 'ISO-8859-1'
>>> assert _z.ZGetCharsetString(None) == 'ISO-8859-1'
>>> assert _z.ZGetCharsetString('UTF-8') == 'UTF-8'
ZGetCharset is a utility function for clients that need to know the
registry number of a character set, e.g. zwrite. It gets its defaults from
alal the places that ZGetCharsetString does, because it calls it.
Trivial testing of ZGetCharset:
>>> assert _z.ZGetCharset(None) == 4
>>> assert _z.ZGetCharset('NONE') == 0
>>> assert _z.ZGetCharset('UNKNOWN') == 0
>>> assert _z.ZGetCharset('ANSI_X3.4-1968') == 4
>>> assert _z.ZGetCharset('ISO-8859-1') == 4
>>> assert _z.ZGetCharset('UTF-8') == 106
>>> assert _z.ZGetCharset('GIANT RUBBER PANTS') == 0
ZCharsetToString converts the registry numbers of the "allowed" character
sets into strings.
Trivial testing of ZCharsetToString:
>>> assert _z.ZCharsetToString(0) == 'UNKNOWN'
>>> assert _z.ZCharsetToString(4) == 'ISO-8859-1'
>>> assert _z.ZCharsetToString(106) == 'UTF-8'
>>> assert _z.ZCharsetToString(1701) == 'UNKNOWN'
ZTransliterate does character set conversion for display purposes, and when
it works, it sticks a malloc'd buffer in to **bufp.
"Trivial" testing of ZTransliterate:
>>> from ctypes import c_char_p, c_int, byref, string_at
>>> from errno import EINVAL, EILSEQ
>>> bufp = c_char_p(None)
>>> length = c_int(0)
>>> assert _z.ZTransliterate('test', 4, 'ANSI_X3.4-1968', 'ANSI_X3.4-1968', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 'test'
>>> assert _z.ZTransliterate('test', 4, 'ANSI_X3.4-1968', 'UTF-8', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 'test'
>>> assert _z.ZTransliterate('test', 4, 'ISO-8859-1', 'ANSI_X3.4-1968', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 'test'
>>> assert _z.ZTransliterate('test', 4, 'ISO-8859-1', 'ANSI_X3.4-1968', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 'test'
>>> assert _z.ZTransliterate('t\xebst', 4, 'ISO-8859-1', 'ANSI_X3.4-1968', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 't?st', "transliterated string is " + string_at(bufp, length)
>>> assert _z.ZTransliterate('t\xebst', 4, 'ISO-8859-1', 'UTF-8', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 't\xc3\xabst'
>>> assert _z.ZTransliterate('t\xc3\xabst', 5, 'UTF-8', 'ISO-8859-1', byref(bufp), byref(length)) == 0
>>> assert string_at(bufp, length) == 't\xebst'
>>> assert _z.ZTransliterate('t\xc3\xabst', 5, 'UTF-8', 'Oh, my bees', byref(bufp), byref(length)) == EINVAL
>>> assert _z.ZTransliterate('t\xc3x\xabst', 5, 'UTF-8', 'ISO-8859-1', byref(bufp), byref(length)) == EILSEQ
Trivial test of ZOpenPort and ZClosePort:
>>> from ctypes import c_ushort
>>> port = c_ushort(0)
>>> st = _z.ZOpenPort(port)
>>> assert st == 0
>>> assert _z.ZGetFD() != -1
>>> zsock = zephyr_tests.getsockname(_z.ZGetFD())
>>> assert zsock
>>> from socket import AF_INET
>>> assert zsock.sa_family.value == AF_INET, zsock.sa_family.value
(Here we're actually using getsockname as an "is that file descriptor
a socket" test; the wrapper is weak in that it can't check for
ENOTSOCK without requiring Python 2.6, so it just throws an exception
on any return of -1. If ctypes.cast worked on sockaddr, we could
also cast it to sockaddr_in and look at the address and port...)
>>> assert port != 0
>>> print type(_z.ZGetDestAddr())
<class 'zephyr_ctypes.sockaddr_in'>
>>> print _z.ZGetDestAddr().sin_family.pformat()
['AF_INET(2)']
>>> print _z.ZGetDestAddr().sin_addr.pformat()
['127.0.0.1']
>>> assert _z.ZClosePort() == 0
>>> assert _z.ZGetFD() == -1
ZMakeAscii takes a target buffer and length and an input buffer and
length, and generates the "special" Zephyr encoding.
TODO: use the "reference" implementation to run a bunch of
random-value comparison tests.
>>> sample = "test\0message"
>>> ref = zephyr_tests.py_make_ascii(sample)
>>> from ctypes import create_string_buffer
>>> outlen = len(sample) * 6
>>> outbuf = create_string_buffer(outlen)
>>> st = _z.ZMakeAscii(outbuf, outlen, sample, len(sample))
>>> assert st == 0
>>> assert outbuf.value == ref, "%r != %r" % (outbuf.value, ref)
A few simple string tests:
>>> def zma(sample):
... outlen = len(sample) * 6
... outbuf = create_string_buffer(outlen)
... st = _z.ZMakeAscii(outbuf, outlen, sample, len(sample))
... assert st == 0
... return outbuf.value
>>> zma("")
''
>>> zma("j")
'0x6A'
>>> zma("jK")
'0x6A4B'
>>> zma("jK__\0")
'0x6A4B5F5F 0x00'
Same thing with ZMakeZcode, a compact binary format that is still NUL-terminated...
>>> sample = "test\0message"
>>> ref = zephyr_tests.py_make_zcode(sample)
>>> from ctypes import create_string_buffer
>>> outlen = len(sample) * 2
>>> outbuf = create_string_buffer(outlen)
>>> st = _z.ZMakeZcode(outbuf, outlen, sample, len(sample))
>>> assert st == 0
>>> assert outbuf.value == ref, "%r != %r" % (outbuf.value, ref)
Queued Packet Tests
===================
Eventually we'll want tests that install a realm (or several) and
actually send and receive packets against them, so-called "system
tests". In the meantime, a faster and more local test that
synthesizes packets and feeds them through the queuing mechanism will
get us some more coverage.
>>> from socket import SOCK_DGRAM, socket, ntohs
>>> port = c_ushort(0)
>>> st = _z.ZOpenPort(port)
>>> port = ntohs(port.value)
>>> assert port
>>> sock = socket(AF_INET, SOCK_DGRAM)
>>> assert sock
>>> assert _z.ZPending() == 0
TODO: cook up test-specific notices, but for now we've got some lying
around from above...
>>> zwhole = string_at(zbuf, size=zbuflen)
>>> wrote = sock.sendto(zwhole, ('127.0.0.1', port))
>>> assert wrote == zbuflen.value, "%s != %s" % (wrote, zbuflen.value)
>>> zcount = _z.ZPending()
>>> assert zcount == 1
Coverage:
Files complete:
ZOpenPort.c
ZClosePort.c
ZExpnRlm.c
ZCmpUID.c
charset.c
ZGetSender.c (needs richer test)
Pending:
ZRequestLocations (ZAsyncLocate.c)
ZParseLocations (ZAsyncLocate.c)
ZCompareALDPred (ZAsyncLocate.c)
ZFreeALD (ZAsyncLocate.c)
ZCheckAuthentication (ZCkAuth.c)
ZCheckIfNotice (ZCkIfNot.c)
ZCheckZcodeAuthentication (ZCkZAut.c)
ZCompareUIDPred (ZCmpUIDP.c)
ZCompareMultiUIDPred (ZCmpUIDP.c)
ZFlushLocations (ZFlsLocs.c)
ZFlushSubscriptions (ZFlsSubs.c)
ZFormatAuthenticNotice (ZFmtAuth.c)
ZFormatAuthenticNoticeV5 (ZFmtAuth.c)
ZFormatNoticeList (ZFmtList.c)
ZFormatNotice (ZFmtNotice.c)
ZNewFormatNotice (ZFmtNotice.c)
ZFormatRawNotice (ZFmtRaw.c)
ZFormatRawNoticeList (ZFmtRawLst.c)
ZFormatSmallRawNoticeList (ZFmtSmRLst.c)
ZFormatSmallRawNotice (ZFmtSmRaw.c)
ZNewFormatSmallRawNotice (ZFmtSmRaw.c)
ZFreeNotice (ZFreeNot.c)
ZGetLocations (ZGetLocs.c)
ZGetSubscriptions (ZGetSubs.c)
ZGetWGPort (ZGetWGPort.c)
ZIfNotice (ZIfNotice.c)
ZGetRealm (ZInit.c)
ZQLength (ZInit.c)
ZInitLocationInfo (ZLocations.c)
ZSetLocation (ZLocations.c)
ZUnsetLocation (ZLocations.c)
ZFlushMyLocations (ZLocations.c)
ZParseExposureLevel (ZLocations.c)
Z_SendLocation (ZLocations.c)
ZMakeAscii32 (ZMakeAscii.c)
ZMakeAscii16 (ZMakeAscii.c)
ZMakeZcode32 (ZMakeZcode.c)
ZMakeZcode (ZMakeZcode.c)
ZResetAuthentication (ZMkAuth.c)
ZMakeAuthentication (ZMkAuth.c)
ZMakeZcodeAuthentication (ZMkAuth.c)
ZMakeZcodeRealmAuthentication (ZMkAuth.c)
ZGetCreds (ZMkAuth.c)
ZGetCredsRealm (ZMkAuth.c)
ZLocateUser (ZNewLocU.c)
ZParseNotice (ZParseNot.c)
ZPeekIfNotice (ZPeekIfNot.c)
ZPeekNotice (ZPeekNot.c)
ZPeekPacket (ZPeekPkt.c)
ZPending (ZPending.c)
ZReadAscii (ZReadAscii.c)
ZReadAscii32 (ZReadAscii.c)
ZReadAscii16 (ZReadAscii.c)
ZReadZcode (ZReadZcode.c)
ZReceiveNotice (ZRecvNot.c)
ZReceivePacket (ZRecvPkt.c)
ZRetrieveSubscriptions (ZRetSubs.c)
ZRetrieveDefaultSubscriptions (ZRetSubs.c)
ZSendList (ZSendList.c)
ZSrvSendList (ZSendList.c)
ZSendNotice (ZSendNot.c)
ZSrvSendNotice (ZSendNot.c)
ZSendPacket (ZSendPkt.c)
ZSendRawList (ZSendRLst.c)
ZSrvSendRawList (ZSendRLst.c)
ZSendRawNotice (ZSendRaw.c)
ZSetDestAddr (ZSetDest.c)
ZSetFD (ZSetFD.c)
ZSetServerState (ZSetSrv.c)
ZPunt (ZSubs.c)
ZSubscribeTo (ZSubs.c)
ZSubscribeToSansDefaults (ZSubs.c)
ZUnsubscribeTo (ZSubs.c)
ZCancelSubscriptions (ZSubs.c)
ZGetVariable (ZVariables.c)
ZSetVariable (ZVariables.c)
ZUnsetVariable (ZVariables.c)
Z_WaitForNotice (ZWait4Not.c)
ZhmStat (ZhmStat.c)
(...continue with Zinternal.c...)