summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ZFmtAuth.c6
-rw-r--r--lib/ZFmtRaw.c2
-rw-r--r--lib/ZFmtRawLst.c2
-rw-r--r--lib/ZFmtSmRLst.c2
-rw-r--r--lib/ZFmtSmRaw.c2
-rw-r--r--lib/ZMkAuth.c31
-rw-r--r--lib/ZParseNot.c1
-rw-r--r--lib/ZRecvNot.c8
-rw-r--r--lib/ZSendList.c3
-rw-r--r--lib/ZSendNot.c3
-rw-r--r--lib/ZSendRLst.c2
-rw-r--r--lib/ZSendRaw.c2
-rw-r--r--lib/Zinternal.c171
13 files changed, 180 insertions, 55 deletions
diff --git a/lib/ZFmtAuth.c b/lib/ZFmtAuth.c
index fb893f3..cf3dc8f 100644
--- a/lib/ZFmtAuth.c
+++ b/lib/ZFmtAuth.c
@@ -28,7 +28,7 @@ Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
C_Block session;
{
ZNotice_t newnotice;
- char *ptr;
+ char *ptr
int retval, hdrlen;
newnotice = *notice;
@@ -37,7 +37,7 @@ Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
newnotice.z_ascii_authent = "";
if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
- &hdrlen, &ptr)) != ZERR_NONE)
+ &hdrlen, &ptr, NULL)) != ZERR_NONE)
return (retval);
#ifdef NOENCRYPTION
@@ -47,7 +47,7 @@ Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
(ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, session);
#endif
if ((retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len,
- &hdrlen, (char **) 0)) != ZERR_NONE)
+ &hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
ptr = buffer+hdrlen;
diff --git a/lib/ZFmtRaw.c b/lib/ZFmtRaw.c
index 5d4c0a3..49d82db 100644
--- a/lib/ZFmtRaw.c
+++ b/lib/ZFmtRaw.c
@@ -28,7 +28,7 @@ Code_t ZFormatRawNotice(notice, buffer, ret_len)
Code_t retval;
if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
- &hdrlen, (char **) 0)) != ZERR_NONE)
+ &hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
diff --git a/lib/ZFmtRawLst.c b/lib/ZFmtRawLst.c
index eb8a969..2773f50 100644
--- a/lib/ZFmtRawLst.c
+++ b/lib/ZFmtRawLst.c
@@ -33,7 +33,7 @@ Code_t ZFormatRawNoticeList(notice, list, nitems, buffer, ret_len)
Code_t retval;
if ((retval = Z_FormatRawHeader(notice, header, sizeof(header),
- &hdrlen, (char **)0)) != ZERR_NONE)
+ &hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
size = 0;
diff --git a/lib/ZFmtSmRLst.c b/lib/ZFmtSmRLst.c
index f3ab7cb..67d50a9 100644
--- a/lib/ZFmtSmRLst.c
+++ b/lib/ZFmtSmRLst.c
@@ -32,7 +32,7 @@ Code_t ZFormatSmallRawNoticeList(notice, list, nitems, buffer, ret_len)
char *ptr;
if ((retval = Z_FormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
- &hdrlen, (char **) 0)) != ZERR_NONE)
+ &hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
size = 0;
diff --git a/lib/ZFmtSmRaw.c b/lib/ZFmtSmRaw.c
index 7269b42..aa6ac60 100644
--- a/lib/ZFmtSmRaw.c
+++ b/lib/ZFmtSmRaw.c
@@ -29,7 +29,7 @@ Code_t ZFormatSmallRawNotice(notice, buffer, ret_len)
int hdrlen;
if ((retval = Z_FormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
- &hdrlen, (char **) 0)) != ZERR_NONE)
+ &hdrlen, NULL, NULL)) != ZERR_NONE)
return (retval);
*ret_len = hdrlen+notice->z_message_len;
diff --git a/lib/ZMkAuth.c b/lib/ZMkAuth.c
index 3c19e26..a11b87b 100644
--- a/lib/ZMkAuth.c
+++ b/lib/ZMkAuth.c
@@ -37,9 +37,12 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
int *len;
{
#ifdef Z_HaveKerberos
- int retval, result;
+ int result;
long now,time();
KTEXT_ST authent;
+ char *cstart, *cend;
+ long checksum;
+ CREDENTIALS cred;
now = time(0);
if (last_authent_time == 0 || (now - last_authent_time > 120)) {
@@ -61,19 +64,37 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
/* zero length authent is an error, so malloc(0) is not a problem */
if (!notice->z_ascii_authent)
return (ENOMEM);
- if ((retval = ZMakeAscii(notice->z_ascii_authent,
+ if ((result = ZMakeAscii(notice->z_ascii_authent,
authent.length*3,
authent.dat,
authent.length)) != ZERR_NONE) {
free(notice->z_ascii_authent);
- return (retval);
+ return (result);
}
- retval = Z_FormatRawHeader(notice, buffer, buffer_len, len, (char **) 0);
+ result = Z_FormatRawHeader(notice, buffer, buffer_len, len, &cstart,
+ &cend);
free(notice->z_ascii_authent);
notice->z_authent_len = 0;
+ if (result)
+ return(result);
- return (retval);
+ /* Compute a checksum over the header and message. */
+ if (result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
+ __Zephyr_realm, &cred))
+ return result;
+ checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, cred.session);
+ checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
+ cred.session);
+ checksum ^= des_quad_cksum(notice->z_message, NULL, notice->message_len, 0,
+ cred.session);
+ notice->z_checksum = (ZChecksum_t) checksum;
+ checksum = htonl(checksum);
+ ZMakeAscii(cptr, buffer + buffer_len - cptr, (unsigned char *) &checksum,
+ sizeof(checksum));
+
+ return (ZERR_NONE);
#else
+ notice->z_checksum = 0;
notice->z_auth = 1;
notice->z_authent_len = 0;
notice->z_ascii_authent = "";
diff --git a/lib/ZParseNot.c b/lib/ZParseNot.c
index 6c47dc7..5717d11 100644
--- a/lib/ZParseNot.c
+++ b/lib/ZParseNot.c
@@ -195,6 +195,7 @@ Code_t ZParseNotice(buffer, len, notice)
}
else
BAD;
+ notice->z_checked_auth = ZAUTH_UNSET;
if (numfields) {
if (ZReadAscii(ptr, end-ptr, (unsigned char *)&temp.i,
diff --git a/lib/ZRecvNot.c b/lib/ZRecvNot.c
index 0b1b278..34de47b 100644
--- a/lib/ZRecvNot.c
+++ b/lib/ZRecvNot.c
@@ -26,7 +26,7 @@ Code_t ZReceiveNotice(notice, from)
{
char *buffer;
struct _Z_InputQ *nextq;
- int len;
+ int len, auth;
Code_t retval;
if ((retval = Z_WaitForComplete()) != ZERR_NONE)
@@ -44,7 +44,11 @@ Code_t ZReceiveNotice(notice, from)
(void) memcpy(buffer, nextq->packet, len);
+ auth = nextq->auth;
Z_RemQueue(nextq);
- return (ZParseNotice(buffer, len, notice));
+ if ((retval = ZParseNotice(buffer, len, notice)) != ZERR_NONE)
+ return (retval);
+ notice->z_checked_auth = auth;
+ return ZERR_NONE;
}
diff --git a/lib/ZSendList.c b/lib/ZSendList.c
index bdfec14..a7accfb 100644
--- a/lib/ZSendList.c
+++ b/lib/ZSendList.c
@@ -48,7 +48,8 @@ Code_t ZSrvSendList(notice, list, nitems, cert_routine, send_routine)
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
- retval = Z_SendFragmentedNotice(&newnotice, len, send_routine);
+ retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
+ send_routine);
free(buffer);
diff --git a/lib/ZSendNot.c b/lib/ZSendNot.c
index 0889290..3bd6f8a 100644
--- a/lib/ZSendNot.c
+++ b/lib/ZSendNot.c
@@ -44,7 +44,8 @@ Code_t ZSrvSendNotice(notice, cert_routine, send_routine)
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
- retval = Z_SendFragmentedNotice(&newnotice, len, send_routine);
+ retval = Z_SendFragmentedNotice(&newnotice, len, cert_routine,
+ send_routine);
free(buffer);
diff --git a/lib/ZSendRLst.c b/lib/ZSendRLst.c
index 02049f6..b148a11 100644
--- a/lib/ZSendRLst.c
+++ b/lib/ZSendRLst.c
@@ -46,7 +46,7 @@ Code_t ZSrvSendRawList(notice, list, nitems, send_routine)
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
- retval = Z_SendFragmentedNotice(&newnotice, len, send_routine);
+ retval = Z_SendFragmentedNotice(&newnotice, len, NULL, send_routine);
free(buffer);
diff --git a/lib/ZSendRaw.c b/lib/ZSendRaw.c
index 25a07fd..b9a633d 100644
--- a/lib/ZSendRaw.c
+++ b/lib/ZSendRaw.c
@@ -35,7 +35,7 @@ Code_t ZSendRawNotice(notice)
if ((retval = ZParseNotice(buffer, len, &newnotice)) != ZERR_NONE)
return (retval);
- retval = Z_SendFragmentedNotice(&newnotice, len, Z_XmitFragment);
+ retval = Z_SendFragmentedNotice(&newnotice, len, NULL, Z_XmitFragment);
free(buffer);
diff --git a/lib/Zinternal.c b/lib/Zinternal.c
index 331e9a3..69ca8c5 100644
--- a/lib/Zinternal.c
+++ b/lib/Zinternal.c
@@ -22,10 +22,12 @@ static char copyright[] =
#include <zephyr/zephyr_internal.h>
#include <netdb.h>
+#include <arpa/inet.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <utmp.h>
+#include <krb.h>
#ifdef SOLARIS
#include <sys/filio.h>
@@ -69,6 +71,78 @@ void (*__Z_debug_print) Zproto((const char *fmt, va_list args, void *closure));
#define min(a,b) ((a)<(b)?(a):(b))
+/* Find or insert uid in the old uids buffer. The buffer is a sorted
+ * circular queue. We make the assumption that most packets arrive in
+ * order, so we can usually search for a uid or insert it into the buffer
+ * by looking back just a few entries from the end. Since this code is
+ * only executed by the client, the implementation isn't microoptimized. */
+static int find_or_insert_uid(uid, kind)
+ ZUnique_Id_t *uid;
+ ZNotice_Kind_t kind;
+{
+ static struct _filter {
+ ZUnique_Id_t uid;
+ ZNotice_Kind_t kind;
+ time_t t;
+ } *buffer;
+ static long size;
+ static long start;
+ static long num;
+
+ time_t now;
+ struct _filter *new;
+ long i, j, new_size;
+ int result;
+
+ /* Initialize the uid buffer if it hasn't been done already. */
+ if (!buffer) {
+ size = Z_INITFILTERSIZE;
+ buffer = (struct _filter *) malloc(size * sizeof(*buffer));
+ if (!buffer)
+ return 0;
+ }
+
+ /* Age the uid buffer, discarding any uids older than the clock skew. */
+ time(&now);
+ while (num && (now - buffer[start % size].t) > CLOCK_SKEW)
+ start++, num--;
+ start %= size;
+
+ /* Make room for a new uid, since we'll probably have to insert one. */
+ if (num == size) {
+ new_size = size * 2 + 2;
+ new = (struct _filter *) malloc(new_size * sizeof(*new));
+ if (!new)
+ return 0;
+ for (i = 0; i < num; i++)
+ new[i] = buffer[(start + i) % size];
+ free(buffer);
+ buffer = new;
+ size = new_size;
+ start = 0;
+ }
+
+ /* Search for this uid in the buffer, starting from the end. */
+ for (i = start + num - 1; i >= start; i--) {
+ result = memcmp(uid, &buffer[i % size].uid, sizeof(*uid));
+ if (result == 0 && buffer[i % size].kind == kind)
+ return 1;
+ if (result > 0)
+ break;
+ }
+
+ /* We didn't find it; insert the uid into the buffer after i. */
+ i++;
+ for (j = start + num; j > i; j--)
+ buffer[j % size] = buffer[(j - 1) % size];
+ buffer[i % size].uid = *uid;
+ buffer[i % size].kind = kind;
+ buffer[i % size].t = now;
+ num++;
+
+ return 0;
+}
+
/* Get the address of the local host and cache it */
Code_t Z_GetMyAddr()
@@ -192,10 +266,6 @@ Code_t Z_ReadWait()
int from_len, packet_len, part, partof;
char *slash;
Code_t retval;
- static struct _filter {
- ZUnique_Id_t uid;
- ZNotice_Kind_t kind;
- } old_uids[Z_FILTERDEPTH];
static int filter_idx = -1;
register int i;
@@ -237,12 +307,17 @@ Code_t Z_ReadWait()
ZNotice_t tmpnotice;
ZPacket_t pkt;
int len;
+ time_t now;
tmpnotice = notice;
tmpnotice.z_kind = CLIENTACK;
tmpnotice.z_message_len = 0;
olddest = __HM_addr;
__HM_addr = from;
+ time(&now);
+ printf("%d seconds elapsed between packet and ack.\n",
+ now - tmpnotice.z_time.tv_sec);
+ fflush(stdout);
if ((retval = ZFormatSmallRawNotice(&tmpnotice, pkt, &len))
!= ZERR_NONE)
return(retval);
@@ -250,23 +325,13 @@ Code_t Z_ReadWait()
return (retval);
__HM_addr = olddest;
}
- if (filter_idx == -1) {
- (void) memset((char *) old_uids, 0,
- Z_FILTERDEPTH*(sizeof(struct _filter)));
- old_uids[0].uid = notice.z_uid;
- old_uids[0].kind = notice.z_kind;
- filter_idx = 1;
- } else {
- for (i = 0; i < Z_FILTERDEPTH; i++)
- if (old_uids[i].uid.tv.tv_sec != 0)
- if (ZCompareUID(&notice.z_uid, &old_uids[i].uid) &&
- (notice.z_kind == old_uids[i].kind))
- return(ZERR_NONE);
- old_uids[filter_idx].uid = notice.z_uid;
- old_uids[filter_idx++].kind = notice.z_kind;
- filter_idx %= Z_FILTERDEPTH;
- }
+ if (find_or_insert_uid(&notice.z_uid, notice.z_kind))
+ return(ZERR_NONE);
}
+
+ /* Check authentication on the notice. */
+ notice.z_checked_auth = ZCheckAuthentication(&notice, &from);
+
/*
* Parse apart the z_multinotice field - if the field is blank for
* some reason, assume this packet stands by itself.
@@ -359,12 +424,11 @@ Code_t Z_ReadWait()
__Q_Head = qptr;
- /* Copy the from field... */
+ /* Copy the from field, multiuid, kind, and checked authentication. */
qptr->from = from;
- /* And the multiuid... */
qptr->uid = notice.z_multiuid;
- /* And the kind... */
qptr->kind = notice.z_kind;
+ qptr->auth = notice.z_checked_auth;
/*
* If this is the first part of the notice, we take the header
@@ -444,6 +508,12 @@ Code_t Z_AddNoticeToEntry(qptr, notice, part)
struct _Z_Hole *hole, *lasthole;
struct timeval tv;
+ /* Incorporate this notice's checked authentication. */
+ if (notice->z_checked_auth == ZAUTH_FAILED)
+ qptr->auth = ZAUTH_FAILED;
+ else if (notice->z_checked_auth == ZAUTH_NO && qptr->auth != ZAUTH_FAILED)
+ qptr->auth = ZAUTH_NO;
+
(void) gettimeofday(&tv, (struct timezone *)0);
qptr->timep = tv.tv_sec;
@@ -551,10 +621,24 @@ Code_t Z_FormatHeader(notice, buffer, buffer_len, len, cert_routine)
{
Code_t retval;
static char version[BUFSIZ]; /* default init should be all \0 */
-
+ struct sockaddr_in name;
+ int namelen = sizeof(name);
+
if (!notice->z_sender)
notice->z_sender = ZGetSender();
+ if (notice->z_port == 0) {
+ if (ZGetFD() < 0) {
+ retval = ZOpenPort((u_short *)0);
+ if (retval != ZERR_NONE)
+ return (retval);
+ }
+ retval = getsockname(ZGetFD(), (struct sockaddr *) &name, &namelen);
+ if (retval != 0)
+ return (retval);
+ notice->z_port = name.sin_port;
+ }
+
notice->z_multinotice = "";
(void) gettimeofday(&notice->z_uid.tv, (struct timezone *)0);
@@ -573,24 +657,34 @@ Code_t Z_FormatHeader(notice, buffer, buffer_len, len, cert_routine)
ZVERSIONMINOR);
notice->z_version = version;
+ return Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
+}
+
+Code_t Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *len;
+ int (*cert_routine)();
+{
if (!cert_routine) {
notice->z_auth = 0;
notice->z_authent_len = 0;
notice->z_ascii_authent = "";
notice->z_checksum = 0;
return (Z_FormatRawHeader(notice, buffer, buffer_len,
- len, (char **) 0));
+ len, NULL, NULL));
}
return ((*cert_routine)(notice, buffer, buffer_len, len));
}
-Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, sumend_ptr)
+Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, cstart, cend)
ZNotice_t *notice;
char *buffer;
int buffer_len;
int *len;
- char **sumend_ptr;
+ char **cstart, **cend;
{
union {
int i;
@@ -681,14 +775,15 @@ Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, sumend_ptr)
return (ZERR_HEADERLEN);
/* copy back the end pointer location for crypto checksum */
- if (sumend_ptr)
- *sumend_ptr = ptr;
-
+ if (cstart)
+ *cstart = ptr;
temp.sum = htonl(notice->z_checksum);
if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&temp.sum,
sizeof(temp.sum)) == ZERR_FIELDLEN)
return (ZERR_HEADERLEN);
ptr += strlen(ptr)+1;
+ if (cend)
+ *cend = ptr;
if (Z_AddField(&ptr, notice->z_multinotice, end))
return (ZERR_HEADERLEN);
@@ -810,15 +905,16 @@ void Z_RemQueue(qptr)
return;
}
-Code_t Z_SendFragmentedNotice(notice, len, send_func)
+Code_t Z_SendFragmentedNotice(notice, len, cert_func, send_func)
ZNotice_t *notice;
int len;
+ Code_t (*cert_func)();
Code_t (*send_func)();
{
ZNotice_t partnotice;
ZPacket_t buffer;
char multi[64];
- int offset, hdrsize, fragsize, ret_len, waitforack;
+ int offset, hdrsize, fragsize, ret_len, message_len, waitforack;
Code_t retval;
hdrsize = len-notice->z_message_len;
@@ -846,14 +942,15 @@ Code_t Z_SendFragmentedNotice(notice, len, send_func)
(void) memcpy((char *)&partnotice.z_uid.zuid_addr, __My_addr,
__My_length);
}
+ message_len = min(notice->z_message_len-offset, fragsize);
partnotice.z_message = notice->z_message+offset;
- partnotice.z_message_len = min(notice->z_message_len-offset,
- fragsize);
- if ((retval = ZFormatSmallRawNotice(&partnotice, buffer,
- &ret_len)) != ZERR_NONE) {
+ partnotice.z_message_len = message_len;
+ if ((retval = Z_FormatAuthHeader(&partnotice, buffer, Z_MAXHEADERLEN,
+ &ret_len, cert_func)) != ZERR_NONE) {
return (retval);
}
- if ((retval = (*send_func)(&partnotice, buffer, ret_len,
+ memcpy(buffer + ret_len, partnotice.z_message, message_len);
+ if ((retval = (*send_func)(&partnotice, buffer, ret_len+message_len,
waitforack)) != ZERR_NONE) {
return (retval);
}