diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ZFmtAuth.c | 6 | ||||
-rw-r--r-- | lib/ZFmtRaw.c | 2 | ||||
-rw-r--r-- | lib/ZFmtRawLst.c | 2 | ||||
-rw-r--r-- | lib/ZFmtSmRLst.c | 2 | ||||
-rw-r--r-- | lib/ZFmtSmRaw.c | 2 | ||||
-rw-r--r-- | lib/ZMkAuth.c | 31 | ||||
-rw-r--r-- | lib/ZParseNot.c | 1 | ||||
-rw-r--r-- | lib/ZRecvNot.c | 8 | ||||
-rw-r--r-- | lib/ZSendList.c | 3 | ||||
-rw-r--r-- | lib/ZSendNot.c | 3 | ||||
-rw-r--r-- | lib/ZSendRLst.c | 2 | ||||
-rw-r--r-- | lib/ZSendRaw.c | 2 | ||||
-rw-r--r-- | lib/Zinternal.c | 171 |
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(¬ice.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(¬ice.z_uid, notice.z_kind)) + return(ZERR_NONE); } + + /* Check authentication on the notice. */ + notice.z_checked_auth = ZCheckAuthentication(¬ice, &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(¬ice->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); } |