summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Karl Ramm <kcr@mit.edu>2007-12-25 05:37:11 +0000
committerGravatar Karl Ramm <kcr@mit.edu>2007-12-25 05:37:11 +0000
commit627ed4a556b987aba5452199ec6f7931dec944fe (patch)
tree47312625d2deea3441ab7e3c0f2a7d3ba95164b2
parent75b16e5d8122b87a3dc301c692529d7e9594c8b8 (diff)
these should have been added when the branch was merged. *sigh*
-rw-r--r--lib/ZCkZAut.c180
-rw-r--r--lib/ZMakeZcode.c80
-rw-r--r--lib/ZReadZcode.c66
3 files changed, 326 insertions, 0 deletions
diff --git a/lib/ZCkZAut.c b/lib/ZCkZAut.c
new file mode 100644
index 0000000..069c1ea
--- /dev/null
+++ b/lib/ZCkZAut.c
@@ -0,0 +1,180 @@
+/* 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 char rcsid_ZCheckAuthentication_c[] =
+ "$Zephyr: /mit/zephyr/src/lib/RCS/ZCheckAuthentication.c,v 1.14 89/03/24 14:17:38 jtkohl Exp Locker: raeburn $";
+#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 ZCheckZcodeAuthentication(notice, from)
+ ZNotice_t *notice;
+ struct sockaddr_in *from;
+{
+ /* 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
+ {
+ krb5_error_code result;
+ krb5_creds *creds;
+ krb5_keyblock *keyblock;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ krb5_data cksumbuf;
+ int valid;
+ char *cksum0_base, *cksum1_base, *cksum2_base;
+ char *svcinst, *x, *y;
+ char *asn1_data, *key_data;
+ int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len;
+
+ result = ZGetCreds(&creds);
+
+ if (result)
+ return (ZAUTH_NO);
+ /* HOLDING: creds */
+
+ /* Figure out what checksum type to use */
+ keyblock = Z_credskey(creds);
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (ZAUTH_FAILED);
+ }
+ /* HOLDING: creds */
+
+ /* 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_other_fields[]
+ */
+ cksum1_base = notice->z_multinotice;
+ if (notice->z_num_other_fields)
+ x = notice->z_other_fields[notice->z_num_other_fields];
+ else
+ x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */
+ cksum1_len = x + strlen(x) + 1 - cksum1_base;
+
+ /* last part is the message body */
+ cksum2_base = notice->z_message;
+ cksum2_len = notice->z_message_len;
+
+ if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
+ key_len == 8 &&
+ (enctype == ENCTYPE_DES_CBC_CRC ||
+ enctype == ENCTYPE_DES_CBC_MD4 ||
+ enctype == ENCTYPE_DES_CBC_MD5)) {
+ /* try old-format checksum (covers cksum0 only) */
+
+ ZChecksum_t our_checksum;
+
+ our_checksum = des_quad_cksum(cksum0_base, NULL, cksum0_len, 0,
+ key_data);
+ if (our_checksum == notice->z_checksum) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return ZAUTH_YES;
+ }
+ }
+ /* HOLDING: creds */
+
+ cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
+ cksumbuf.data = malloc(cksumbuf.length);
+ if (!cksumbuf.data) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return ZAUTH_NO;
+ }
+ /* HOLDING: creds, cksumbuf.data */
+
+ memcpy(cksumbuf.data, cksum0_base, cksum0_len);
+ memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len);
+ memcpy(cksumbuf.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) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: creds, asn1_data, cksumbuf.data */
+ result = ZReadZcode(notice->z_ascii_checksum,
+ asn1_data, asn1_len, &asn1_len);
+ if (result != ZERR_NONE) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ free(asn1_data);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: creds, asn1_data, cksumbuf.data */
+
+ valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype,
+ asn1_data, asn1_len);
+
+ free(asn1_data);
+ krb5_free_creds(Z_krb5_ctx, creds);
+ free(cksumbuf.data);
+
+ if (valid)
+ return ZAUTH_YES;
+ else
+ return ZAUTH_FAILED;
+ }
+#endif /* HAVE_KRB5 */
+ return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
+}
diff --git a/lib/ZMakeZcode.c b/lib/ZMakeZcode.c
new file mode 100644
index 0000000..6229bef
--- /dev/null
+++ b/lib/ZMakeZcode.c
@@ -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(ptr, len, val)
+ 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(ptr, len, field, num)
+ 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;
+ *ptr++ = 0xff;
+ *ptr++ = 0xf0;
+ len -= 2;
+ continue;
+
+ case 0xff:
+ if (len < 3)
+ return ZERR_FIELDLEN;
+ *ptr++ = 0xff;
+ *ptr++ = 0xf1;
+ len -= 2;
+ continue;
+
+ default:
+ if (len < 2)
+ return ZERR_FIELDLEN;
+ *ptr++ = field[i];
+ len--;
+ }
+ }
+
+ *ptr = '\0';
+ return ZERR_NONE;
+}
diff --git a/lib/ZReadZcode.c b/lib/ZReadZcode.c
new file mode 100644
index 0000000..ed3a283
--- /dev/null
+++ b/lib/ZReadZcode.c
@@ -0,0 +1,66 @@
+/* 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 char rcsid_ZReadZcode_c[] = "$Id$";
+#endif /* lint */
+
+#include <internal.h>
+#include <assert.h>
+
+
+#if 0
+Code_t
+ZReadAsciiOrZcode(char *buf, int buflen, unsigned char *data, int datalen)
+{
+ if (buf[0] == 'Z')
+ return ZReadZcode(buf, buflen, data, datalen);
+ else
+ return ZReadAscii(buf, buflen, data, datalen);
+}
+
+Code_t ZReadZcode32(ptr, value_ptr)
+ unsigned char *ptr;
+ unsigned long *value_ptr;
+{
+ abort();
+}
+#endif
+
+Code_t ZReadZcode(ptr, field, max, len)
+ 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);
+}