From e6a545e75963456834f120cfc62983eb4d001490 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Thu, 27 Jun 2013 23:45:24 -0400 Subject: Implement ZDumpSession and ZLoadSession This is unlikely to ever get merged, but it'll be handy for roost. --- h/zephyr/zephyr.h | 2 + lib/Makefile.in | 3 +- lib/ZDumpSession.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 lib/ZDumpSession.c 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 + +#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); +} -- cgit v1.2.3