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. --- lib/ZDumpSession.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 lib/ZDumpSession.c (limited to 'lib/ZDumpSession.c') 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