summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar David Benjamin <davidben@mit.edu>2013-06-27 23:45:24 -0400
committerGravatar Karl Ramm <kcr@1ts.org>2013-09-28 15:01:30 -0400
commite6a545e75963456834f120cfc62983eb4d001490 (patch)
tree8c6aeec80dfab0b9e600833f54a2f04dc7c8b8f1
parentb13d9822d947d09749d7a0231d49705e2c2a3c17 (diff)
Implement ZDumpSession and ZLoadSession
This is unlikely to ever get merged, but it'll be handy for roost.
-rw-r--r--h/zephyr/zephyr.h2
-rw-r--r--lib/Makefile.in3
-rw-r--r--lib/ZDumpSession.c139
3 files changed, 143 insertions, 1 deletions
diff --git a/h/zephyr/zephyr.h b/h/zephyr/zephyr.h
index 28baa7f..06cf541 100644
--- a/h/zephyr/zephyr.h
+++ b/h/zephyr/zephyr.h
@@ -259,6 +259,8 @@ Code_t ZTransliterate(char *in, int inlen, char *inset, char *outset, char **out
void Z_debug(const char *, ...);
#endif
char *ZExpandRealm(char *realm);
+Code_t ZDumpSession(char **buffer, int *ret_len);
+Code_t ZLoadSession(char *buffer, int len);
/* Compatibility */
#define ZNewLocateUser ZLocateUser
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 79c8173..d76f2a9 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -41,7 +41,8 @@ OBJS = zephyr_err.lo ZAsyncLocate.lo ZCkAuth.lo ZCkIfNot.lo ZClosePort.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
+ ZReadZcode.lo ZCkZAut.lo quad_cksum.lo charset.lo ZExpnRlm.lo \
+ ZDumpSession.lo
.SUFFIXES: .lo
diff --git a/lib/ZDumpSession.c b/lib/ZDumpSession.c
new file mode 100644
index 0000000..f4dfc76
--- /dev/null
+++ b/lib/ZDumpSession.c
@@ -0,0 +1,139 @@
+/* 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;
+ int i;
+#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;
+#endif
+ int i;
+ 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);
+}