+Tue May 9 15:21:49 EDT 1995 Paul Park (pjpark@mit.edu)
+ * adm_conn.c - use profile information to locate the admin_server.
+ Also, return the correct value from krb5_adm_connect
+ instead of always returning zero.
+ * adm_{kw,kt}_{enc,dec}.c - New modules to [en/de]code administrative
+ protocol keyword=value pairs and keytab entries.
+
+
Fri Apr 28 09:47:29 EDT 1995 Paul Park (pjpark@mit.edu)
Create a new library consisting of functions which communicate with
all:: $(OBJS)
OBJS= adm_conn.o \
+ adm_kw_dec.o \
+ adm_kw_enc.o \
+ adm_kt_dec.o \
+ adm_kt_enc.o \
adm_rw.o
SRCS= $(srcdir)/adm_conn.c \
+ $(srcdir)/adm_kw_dec.c \
+ $(srcdir)/adm_kw_enc.c \
+ $(srcdir)/adm_kt_dec.c \
+ $(srcdir)/adm_kt_enc.c \
$(srcdir)/adm_rw.c
libkadm.a: ${OBJS}
--- /dev/null
+/*
+ * lib/kadm/adm_kt_dec.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * adm_kt_dec.c - Decode keytab entry according to protocol.
+ */
+#include "k5-int.h"
+#include "adm.h"
+\f
+/*
+ * krb5_adm_proto_to_ktent() - Convert a list of reply components to
+ * a keytab entry according to procotol.
+ *
+ * Successful callers of this routine should free ktentp->principal
+ * and ktentp->key.contents.
+ */
+krb5_error_code
+krb5_adm_proto_to_ktent(kcontext, ncomp, complist, ktentp)
+ krb5_context kcontext;
+ krb5_int32 ncomp;
+ krb5_data *complist;
+ krb5_keytab_entry *ktentp;
+{
+ krb5_error_code kret;
+ char *v;
+
+ /*
+ * Clear out the keytab entry.
+ */
+ memset((char *) ktentp, 0, sizeof(krb5_keytab_entry));
+
+ /*
+ * Figure out how many components we have. We expect KRB5_ADM_KT_NCOMPS
+ * components.
+ */
+ if (ncomp != KRB5_ADM_KT_NCOMPS)
+ return(EINVAL);
+
+ /* Parse the supplied principal name */
+ if (kret = krb5_parse_name(kcontext,
+ complist[KRB5_ADM_KT_PRINCIPAL].data,
+ &ktentp->principal))
+ goto done;
+
+ /* Parse the supplied timestamp */
+ if (complist[KRB5_ADM_KT_TIMESTAMP].length < sizeof(krb5_timestamp)) {
+ kret = EINVAL;
+ goto done;
+ }
+ v = complist[KRB5_ADM_KT_TIMESTAMP].data;
+ ktentp->timestamp = (krb5_timestamp)
+ (((krb5_int32) ((unsigned char) v[0]) << 24) +
+ ((krb5_int32) ((unsigned char) v[1]) << 16) +
+ ((krb5_int32) ((unsigned char) v[2]) << 8) +
+ ((krb5_int32) ((unsigned char) v[3])));
+
+ /* Parse the supplied vno */
+ if (complist[KRB5_ADM_KT_VNO].length < sizeof(krb5_kvno)) {
+ kret = EINVAL;
+ goto done;
+ }
+ v = complist[KRB5_ADM_KT_VNO].data;
+ ktentp->vno = (krb5_kvno)
+ (((krb5_int32) ((unsigned char) v[0]) << 24) +
+ ((krb5_int32) ((unsigned char) v[1]) << 16) +
+ ((krb5_int32) ((unsigned char) v[2]) << 8) +
+ ((krb5_int32) ((unsigned char) v[3])));
+
+ /* Parse the supplied key_keytype */
+ if (complist[KRB5_ADM_KT_KEY_KEYTYPE].length < sizeof(krb5_keytype)) {
+ kret = EINVAL;
+ goto done;
+ }
+ v = complist[KRB5_ADM_KT_KEY_KEYTYPE].data;
+ ktentp->key.keytype = (krb5_keytype)
+ (((krb5_int32) ((unsigned char) v[0]) << 24) +
+ ((krb5_int32) ((unsigned char) v[1]) << 16) +
+ ((krb5_int32) ((unsigned char) v[2]) << 8) +
+ ((krb5_int32) ((unsigned char) v[3])));
+
+ /* Parse the supplied key_etype */
+ if (complist[KRB5_ADM_KT_KEY_ETYPE].length < sizeof(krb5_enctype)) {
+ kret = EINVAL;
+ goto done;
+ }
+ v = complist[KRB5_ADM_KT_KEY_ETYPE].data;
+ ktentp->key.etype = (krb5_enctype)
+ (((krb5_int32) ((unsigned char) v[0]) << 24) +
+ ((krb5_int32) ((unsigned char) v[1]) << 16) +
+ ((krb5_int32) ((unsigned char) v[2]) << 8) +
+ ((krb5_int32) ((unsigned char) v[3])));
+
+ /* Finally, shuck the key contents */
+ if (ktentp->key.contents = (krb5_octet *)
+ malloc((size_t) complist[KRB5_ADM_KT_KEY_KEY].length)) {
+ ktentp->key.length = complist[KRB5_ADM_KT_KEY_KEY].length;
+ memcpy(ktentp->key.contents,
+ complist[KRB5_ADM_KT_KEY_KEY].data,
+ (size_t) ktentp->key.length);
+ kret = 0;
+ }
+ else
+ kret = ENOMEM;
+
+ done:
+ if (kret) {
+ if (ktentp->principal)
+ krb5_free_principal(kcontext, ktentp->principal);
+ if (ktentp->key.contents) {
+ memset((char *) ktentp->key.contents, 0,
+ (size_t) ktentp->key.length);
+ krb5_xfree(ktentp->key.contents);
+ }
+ memset((char *) ktentp, 0, sizeof(krb5_keytab_entry));
+ }
+ return(kret);
+}
--- /dev/null
+/*
+ * lib/kadm/adm_kt_enc.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * adm_kt_enc.c - Encode keytab entry according to protocol.
+ */
+#include "k5-int.h"
+#include "adm.h"
+\f
+/*
+ * krb5_adm_ktent_to_proto() - Convert a keytab entry into an external
+ * list of reply components.
+ *
+ * Successful callers must free the storage for complistp and complistp->data
+ * either manually or by using krb5_free_adm_data().
+ */
+krb5_error_code
+krb5_adm_ktent_to_proto(kcontext, ktentp, ncompp, complistp)
+ krb5_context kcontext;
+ krb5_keytab_entry *ktentp;
+ krb5_int32 *ncompp;
+ krb5_data **complistp;
+{
+ krb5_error_code kret;
+ krb5_data *clist;
+ krb5_int32 nents;
+
+ kret = ENOMEM;
+ nents = 0;
+ if (clist = (krb5_data *) malloc((size_t) KRB5_ADM_KT_NCOMPS *
+ sizeof(krb5_data))) {
+ memset((char *) clist, 0, ((size_t) KRB5_ADM_KT_NCOMPS *
+ sizeof(krb5_data)));
+ /*
+ * Fill in the principal field.
+ */
+ if (kret = krb5_unparse_name(kcontext,
+ ktentp->principal,
+ &clist[KRB5_ADM_KT_PRINCIPAL].data))
+ goto done;
+ clist[KRB5_ADM_KT_PRINCIPAL].length =
+ strlen(clist[KRB5_ADM_KT_PRINCIPAL].data);
+ nents++;
+
+ /*
+ * Fill in timestamp.
+ */
+ if (kret = krb5_timeofday(kcontext, &ktentp->timestamp))
+ goto done;
+ if (clist[KRB5_ADM_KT_TIMESTAMP].data =
+ (char *) malloc(sizeof(krb5_ui_4))) {
+ clist[KRB5_ADM_KT_TIMESTAMP].length = sizeof(krb5_ui_4);
+ clist[KRB5_ADM_KT_TIMESTAMP].data[0] =
+ (ktentp->timestamp >> 24) && 0xff;
+ clist[KRB5_ADM_KT_TIMESTAMP].data[1] =
+ (ktentp->timestamp >> 16) && 0xff;
+ clist[KRB5_ADM_KT_TIMESTAMP].data[2] =
+ (ktentp->timestamp >> 8) && 0xff;
+ clist[KRB5_ADM_KT_TIMESTAMP].data[3] =
+ ktentp->timestamp && 0xff;
+ nents++;
+ }
+ else {
+ kret = ENOMEM;
+ goto done;
+ }
+
+ /*
+ * Fill in vno.
+ */
+ if (clist[KRB5_ADM_KT_VNO].data =
+ (char *) malloc(sizeof(krb5_ui_4))) {
+ clist[KRB5_ADM_KT_VNO].length = sizeof(krb5_ui_4);
+ clist[KRB5_ADM_KT_VNO].data[0] = (ktentp->vno >> 24) && 0xff;
+ clist[KRB5_ADM_KT_VNO].data[1] = (ktentp->vno >> 16) && 0xff;
+ clist[KRB5_ADM_KT_VNO].data[2] = (ktentp->vno >> 8) && 0xff;
+ clist[KRB5_ADM_KT_VNO].data[3] = ktentp->vno && 0xff;
+ nents++;
+ }
+ else {
+ kret = ENOMEM;
+ goto done;
+ }
+
+ /*
+ * Fill in key_keytype.
+ */
+ if (clist[KRB5_ADM_KT_KEY_KEYTYPE].data =
+ (char *) malloc(sizeof(krb5_ui_4))) {
+ clist[KRB5_ADM_KT_KEY_KEYTYPE].length = sizeof(krb5_ui_4);
+ clist[KRB5_ADM_KT_KEY_KEYTYPE].data[0] =
+ (ktentp->key.keytype >> 24) && 0xff;
+ clist[KRB5_ADM_KT_KEY_KEYTYPE].data[1] =
+ (ktentp->key.keytype >> 16) && 0xff;
+ clist[KRB5_ADM_KT_KEY_KEYTYPE].data[2] =
+ (ktentp->key.keytype >> 8) && 0xff;
+ clist[KRB5_ADM_KT_KEY_KEYTYPE].data[3] =
+ ktentp->key.keytype && 0xff;
+ nents++;
+ }
+ else {
+ kret = ENOMEM;
+ goto done;
+ }
+
+ /*
+ * Fill in key_etype.
+ */
+ if (clist[KRB5_ADM_KT_KEY_ETYPE].data =
+ (char *) malloc(sizeof(krb5_ui_4))) {
+ clist[KRB5_ADM_KT_KEY_ETYPE].length = sizeof(krb5_ui_4);
+ clist[KRB5_ADM_KT_KEY_ETYPE].data[0] =
+ (ktentp->key.etype >> 24) && 0xff;
+ clist[KRB5_ADM_KT_KEY_ETYPE].data[1] =
+ (ktentp->key.etype >> 16) && 0xff;
+ clist[KRB5_ADM_KT_KEY_ETYPE].data[2] =
+ (ktentp->key.etype >> 8) && 0xff;
+ clist[KRB5_ADM_KT_KEY_ETYPE].data[3] =
+ ktentp->key.etype && 0xff;
+ nents++;
+ }
+ else {
+ kret = ENOMEM;
+ goto done;
+ }
+
+ /*
+ * Fill in key_key.
+ */
+ if (clist[KRB5_ADM_KT_KEY_KEY].data =
+ (char *) malloc((size_t) ktentp->key.length)) {
+ memcpy(clist[KRB5_ADM_KT_KEY_KEY].data,
+ ktentp->key.contents,
+ (size_t) ktentp->key.length);
+ clist[KRB5_ADM_KT_KEY_KEY].length = ktentp->key.length;
+ nents++;
+ kret = 0;
+ }
+ else
+ kret = ENOMEM;
+ }
+ done:
+ if (kret) {
+ if (clist) {
+ int i;
+ for (i=0; i<KRB5_ADM_KT_NCOMPS; i++) {
+ if (clist[i].data) {
+ memset(clist[i].data, 0, (size_t) clist[i].length);
+ krb5_xfree(clist[i].data);
+ }
+ }
+ krb5_xfree(clist);
+ }
+ clist = (krb5_data *) NULL;
+ nents = 0;
+ }
+ *complistp = clist;
+ *ncompp = nents;
+ return(kret);
+}
--- /dev/null
+/*
+ * lib/kadm/adm_kw_dec.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * adm_kw_dec.c - routines to decode keyword-value pairs.
+ */
+#include "k5-int.h"
+#include "adm.h"
+
+#define char2int(c) ((c) - '0')
+\f
+/*
+ * string_to_salt_type() - Convert from salt string to salt type.
+ */
+static krb5_int32
+string_to_salt_type(sstring, retp)
+ char *sstring;
+ krb5_error_code *retp;
+{
+ krb5_error_code kret;
+ krb5_int32 stype;
+
+ kret = EINVAL;
+ stype = -1;
+ if (!strcmp(sstring, KRB5_ADM_SALTTYPE_NORMAL))
+ stype = KRB5_KDB_SALTTYPE_NORMAL;
+ else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_V4))
+ stype = KRB5_KDB_SALTTYPE_V4;
+ else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_NOREALM))
+ stype = KRB5_KDB_SALTTYPE_NOREALM;
+ else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_ONLYREALM))
+ stype = KRB5_KDB_SALTTYPE_ONLYREALM;
+ else if (!strcmp(sstring, KRB5_ADM_SALTTYPE_SPECIAL))
+ stype = KRB5_KDB_SALTTYPE_SPECIAL;
+
+ if (stype != -1)
+ kret = 0;
+
+ *retp = kret;
+ return(stype);
+}
+\f
+/*
+ * keyword_value() - Find index of keyword value if keyword is present.
+ *
+ * If a value is required, then the index of the keyword value is returned,
+ * otherwise the index of the first character past the end of the keyword
+ * string is returned.
+ */
+static off_t
+keyword_value(dataentp, keyword, value_req)
+ krb5_data *dataentp;
+ char *keyword;
+ krb5_boolean value_req;
+{
+ off_t len_req;
+
+ len_req = strlen(keyword);
+ if (value_req)
+ len_req++;
+ if ((dataentp->length >= len_req) &&
+ (!strncmp(dataentp->data, keyword, strlen(keyword))) &&
+ (!value_req || (dataentp->data[strlen(keyword)] == '=')))
+ return(len_req);
+ else
+ return(-1);
+}
+\f
+/*
+ * decode_kw_string() - Decode a keyword=<string> pair and return the
+ * string value if the pair is present.
+ *
+ * Note: successful callers must free the string storage.
+ */
+static krb5_error_code
+decode_kw_string(dataentp, keyword, stringp)
+ krb5_data *dataentp;
+ char *keyword;
+ char **stringp;
+{
+ krb5_error_code kret;
+ off_t valueoff;
+ size_t len2copy;
+
+ kret = ENOENT;
+ if ((valueoff = keyword_value(dataentp, keyword, 1)) >= 0) {
+ kret = ENOMEM;
+ len2copy = dataentp->length - valueoff;
+ *stringp = (char *) malloc(len2copy+1);
+ if (*stringp) {
+ strncpy(*stringp, &dataentp->data[valueoff], len2copy);
+ (*stringp)[len2copy] = '\0';
+ kret = 0;
+ }
+ }
+ return(kret);
+}
+\f
+/*
+ * decode_kw_integer() - Decode a keyword=<integer> pair and return the value
+ * if the pair is present.
+ */
+static krb5_error_code
+decode_kw_integer(dataentp, keyword, uintp)
+ krb5_data *dataentp;
+ char *keyword;
+ krb5_ui_4 *uintp;
+{
+ krb5_error_code kret;
+ off_t voff;
+ size_t len2copy;
+
+ kret = ENOENT;
+ if ((voff = keyword_value(dataentp, keyword, 1)) >= 0) {
+ kret = EINVAL;
+ len2copy = dataentp->length - voff;
+ if (len2copy == sizeof(krb5_ui_4)) {
+ *uintp = (((krb5_int32) ((unsigned char) dataentp->data[voff])
+ << 24) +
+ ((krb5_int32) ((unsigned char) dataentp->data[voff+1])
+ << 16) +
+ ((krb5_int32) ((unsigned char) dataentp->data[voff+2])
+ << 8) +
+ ((krb5_int32) ((unsigned char) dataentp->data[voff+3])));
+ kret = 0;
+ }
+ }
+ return(kret);
+}
+\f
+/*
+ * decode_kw_gentime() - Decode a keyword=<general-time> pair and return the
+ * time result if the pair is present.
+ *
+ * XXX - this knows too much about how Kerberos time is encoded.
+ */
+static krb5_error_code
+decode_kw_gentime(dataentp, keyword, gtimep)
+ krb5_data *dataentp;
+ char *keyword;
+ krb5_timestamp *gtimep;
+{
+ krb5_error_code kret;
+ char *timestring;
+ struct tm tval;
+ time_t temp_time;
+
+ memset((char *) &tval, 0, sizeof(tval));
+ timestring = (char *) NULL;
+ if (!(kret = decode_kw_string(dataentp, keyword, ×tring))) {
+ kret = EINVAL;
+ if ((strlen(timestring) == 15) &&
+ (timestring[14] == 'Z')) {
+ tval.tm_year = 1000*char2int(timestring[0]) +
+ 100*char2int(timestring[1]) +
+ 10*char2int(timestring[2]) +
+ char2int(timestring[3]) - 1900;
+ tval.tm_mon = 10*char2int(timestring[4]) +
+ char2int(timestring[5]) - 1;
+ tval.tm_mday = 10*char2int(timestring[6]) +
+ char2int(timestring[7]);
+ tval.tm_hour = 10*char2int(timestring[8]) +
+ char2int(timestring[9]);
+ tval.tm_min = 10*char2int(timestring[10]) +
+ char2int(timestring[11]);
+ tval.tm_sec = 10*char2int(timestring[12]) +
+ char2int(timestring[13]);
+ tval.tm_isdst = -1;
+ temp_time = gmt_mktime(&tval);
+ if (temp_time >= 0) {
+ kret = 0;
+ *gtimep = (krb5_timestamp) temp_time;
+ }
+ }
+ free(timestring);
+ }
+ return(kret);
+}
+\f
+/*
+ * decode_kw_salttype() - Decode a keyword=<salttype> pair and fill in the
+ * salt type values if the pair is present.
+ */
+static krb5_error_code
+decode_kw_salttype(dataentp, keyword, dbentp)
+ krb5_data *dataentp;
+ char *keyword;
+ krb5_db_entry *dbentp;
+{
+ krb5_error_code kret;
+ char *saltstring;
+ char *sentp;
+
+ saltstring = (char *) NULL;
+ if (!(kret = decode_kw_string(dataentp, keyword, &saltstring))) {
+ kret = EINVAL;
+ if (sentp = strchr(saltstring, (int) ',')) {
+ *sentp = '\0';
+ sentp++;
+ }
+ dbentp->salt_type = string_to_salt_type(saltstring, &kret);
+ if (!kret && sentp) {
+ dbentp->alt_salt_type = string_to_salt_type(sentp, &kret);
+ }
+ free(saltstring);
+ }
+ return(kret);
+}
+\f
+/*
+ * krb5_adm_proto_to_dbent() - Convert external attribute list into a
+ * database entry.
+ *
+ * Scan through the keyword=value pairs in "data" until either the end of
+ * the list (as determined from "nent") is reached, or an error occurs.
+ * Return a mask of attributes which are set in "validp", the actual
+ * attribute values in "dbentp" and "pwordp" if a password is specified.
+ *
+ * Successful callers must allocate the storage for "validp", "dbentp" and
+ * must free the storage allocated for "pwordp" if a password is specified
+ * and free the storage allocated for "validp->mod_name" if a modifier name
+ * is specified.
+ */
+krb5_error_code
+krb5_adm_proto_to_dbent(kcontext, nent, data, validp, dbentp, pwordp)
+ krb5_context kcontext; /* Kerberos context */ /* In */
+ krb5_int32 nent; /* Number of components */ /* In */
+ krb5_data *data; /* Component list */ /* In */
+ krb5_ui_4 *validp; /* Valid bitmask */ /* Out */
+ krb5_db_entry *dbentp; /* Database entry */ /* Out */
+ char **pwordp; /* Password string */ /* Out */
+{
+ int i;
+ krb5_error_code retval;
+ krb5_ui_4 parsed_mask;
+ char *modifier_name;
+
+ /* Initialize */
+ retval = 0;
+ parsed_mask = 0;
+ *pwordp = (char *) NULL;
+
+ /* Loop through all the specified keyword=value pairs. */
+ for (i=0; i<nent; i++) {
+ /* Check for password */
+ if (!(retval = decode_kw_string(&data[i],
+ KRB5_ADM_KW_PASSWORD,
+ pwordp))) {
+ parsed_mask |= KRB5_ADM_M_PASSWORD;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for key version number */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_KVNO,
+ (krb5_ui_4 *) &dbentp->kvno))) {
+ parsed_mask |= KRB5_ADM_M_KVNO;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for maximum lifetime */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_MAXLIFE,
+ (krb5_ui_4 *) &dbentp->max_life))) {
+ parsed_mask |= KRB5_ADM_M_MAXLIFE;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for maximum renewable lifetime */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_MAXRENEWLIFE,
+ (krb5_ui_4 *)
+ &dbentp->max_renewable_life))) {
+ parsed_mask |= KRB5_ADM_M_MAXRENEWLIFE;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for principal expiration */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_EXPIRATION,
+ &dbentp->expiration))) {
+ parsed_mask |= KRB5_ADM_M_EXPIRATION;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for password expiration */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_PWEXPIRATION,
+ &dbentp->pw_expiration))) {
+ parsed_mask |= KRB5_ADM_M_PWEXPIRATION;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* random key - value optional */
+ if (keyword_value(&data[i],
+ KRB5_ADM_KW_RANDOMKEY,
+ 0) >= 0) {
+ krb5_ui_4 value;
+
+ if (retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_RANDOMKEY,
+ &value)) {
+ value = 1;
+ retval = 0;
+ }
+ if (value)
+ parsed_mask |= KRB5_ADM_M_RANDOMKEY;
+ else
+ parsed_mask &= ~KRB5_ADM_M_RANDOMKEY;
+ continue;
+ }
+
+ /* Check for flags */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_FLAGS,
+ (krb5_ui_4 *) &dbentp->attributes))) {
+ parsed_mask |= KRB5_ADM_M_FLAGS;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for salttype */
+ if (!(retval = decode_kw_salttype(&data[i],
+ KRB5_ADM_KW_SALTTYPE,
+ dbentp))) {
+ parsed_mask |= KRB5_ADM_M_SALTTYPE;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for master key version number */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_MKVNO,
+ (krb5_ui_4 *) &dbentp->mkvno))) {
+ parsed_mask |= KRB5_ADM_M_MKVNO;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for last password change */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_LASTPWCHANGE,
+ &dbentp->last_pwd_change))) {
+ parsed_mask |= KRB5_ADM_M_LASTPWCHANGE;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for last successful password entry */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_LASTSUCCESS,
+ &dbentp->last_success))) {
+ parsed_mask |= KRB5_ADM_M_LASTSUCCESS;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for last failed entry */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_LASTFAILED,
+ &dbentp->last_failed))) {
+ parsed_mask |= KRB5_ADM_M_LASTFAILED;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for failure count */
+ if (!(retval = decode_kw_integer(&data[i],
+ KRB5_ADM_KW_FAILCOUNT,
+ (krb5_ui_4 *)
+ &dbentp->fail_auth_count))) {
+ parsed_mask |= KRB5_ADM_M_FAILCOUNT;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for modification principal */
+ if (!(retval = decode_kw_string(&data[i],
+ KRB5_ADM_KW_MODNAME,
+ &modifier_name))) {
+ krb5_principal modifier;
+ retval = krb5_parse_name(kcontext, modifier_name, &modifier);
+ free(modifier_name);
+ if (!retval) {
+ if (dbentp->mod_name)
+ krb5_free_principal(kcontext, dbentp->mod_name);
+ dbentp->mod_name = modifier;
+ parsed_mask |= KRB5_ADM_M_MODNAME;
+ continue;
+ }
+ else
+ break;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* Check for modification time */
+ if (!(retval = decode_kw_gentime(&data[i],
+ KRB5_ADM_KW_MODDATE,
+ &dbentp->mod_date))) {
+ parsed_mask |= KRB5_ADM_M_MODDATE;
+ continue;
+ }
+ else {
+ if (retval != ENOENT)
+ break;
+ }
+
+ /* If we fall through here, we've got something unrecognized */
+ if (retval) {
+ retval = EINVAL;
+ break;
+ }
+ }
+
+ if (retval) {
+ if (*pwordp) {
+ memset(*pwordp, 0, strlen(*pwordp));
+ free(*pwordp);
+ *pwordp = (char *) NULL;
+ }
+ parsed_mask = 0;
+ }
+ *validp |= parsed_mask;
+ return(retval);
+}
--- /dev/null
+/*
+ * lib/kadm/adm_kw_enc.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * adm_kw_enc.c - routines to encode principal attributes in keyword-value
+ * pairs.
+ */
+#include "k5-int.h"
+#include "adm.h"
+
+\f
+/*
+ * salt_type_to_string() - Return a string for a given salt type.
+ *
+ * Add support for different salt types here.
+ */
+static char *
+salt_type_to_string(stype)
+ krb5_int32 stype;
+{
+ char *retval = (char *) NULL;
+
+ switch (stype) {
+ case KRB5_KDB_SALTTYPE_NORMAL:
+ retval = KRB5_ADM_SALTTYPE_NORMAL; break;
+ case KRB5_KDB_SALTTYPE_V4:
+ retval = KRB5_ADM_SALTTYPE_V4; break;
+ case KRB5_KDB_SALTTYPE_NOREALM:
+ retval = KRB5_ADM_SALTTYPE_NOREALM; break;
+ case KRB5_KDB_SALTTYPE_ONLYREALM:
+ retval = KRB5_ADM_SALTTYPE_ONLYREALM; break;
+ case KRB5_KDB_SALTTYPE_SPECIAL:
+ retval = KRB5_ADM_SALTTYPE_SPECIAL; break;
+ }
+ return(retval);
+}
+\f
+/*
+ * format_kw_string() - Format a keyword=<string> pair.
+ *
+ * Work routine for other string-based formatters also.
+ */
+static krb5_error_code
+format_kw_string(datap, kwordp, valp)
+ krb5_data *datap;
+ char *kwordp;
+ char *valp;
+{
+ krb5_error_code retval;
+ char fbuffer[BUFSIZ];
+
+ retval = ENOMEM;
+ sprintf(fbuffer,"%s=%s", kwordp, valp);
+ datap->data = (char *) malloc(strlen(fbuffer)+1);
+ if (datap->data) {
+ datap->length = strlen(fbuffer);
+ strcpy(datap->data, fbuffer);
+ retval = 0;
+ }
+ return(retval);
+}
+\f
+/*
+ * format_kw_integer() - Format a keyword=<integer> pair.
+ */
+static krb5_error_code
+format_kw_integer(datap, kwordp, val)
+ krb5_data *datap;
+ char *kwordp;
+ krb5_ui_4 val;
+{
+ krb5_error_code retval;
+ char fbuffer[BUFSIZ];
+
+ retval = ENOMEM;
+ sprintf(fbuffer,"%s=", kwordp);
+ datap->data = (char *) malloc(strlen(fbuffer)+sizeof(krb5_ui_4));
+ if (datap->data) {
+ datap->length = strlen(fbuffer);
+ strcpy(datap->data, fbuffer);
+ datap->data[datap->length] = (val >> 24) & 0xff;
+ datap->data[datap->length+1] = (val >> 16) & 0xff;
+ datap->data[datap->length+2] = (val >> 8) & 0xff;
+ datap->data[datap->length+3] = val & 0xff;
+ datap->length += sizeof(krb5_ui_4);
+ retval = 0;
+ }
+ return(retval);
+}
+\f
+/*
+ * format_kw_gentime() - Format a keyword=<general-time> pair.
+ *
+ * XXX - should this routine know so much about how generaltime is encoded?
+ */
+static krb5_error_code
+format_kw_gentime(datap, kwordp, timep)
+ krb5_data *datap;
+ char *kwordp;
+ krb5_timestamp *timep;
+{
+ krb5_error_code retval;
+ char fbuffer[BUFSIZ];
+ time_t tval;
+ struct tm *time_gmt;
+
+ retval = EINVAL;
+ tval = (time_t) *timep;
+ time_gmt = gmtime(&tval);
+ if (time_gmt) {
+ sprintf(fbuffer,"%04d%02d%02d%02d%02d%02dZ",
+ time_gmt->tm_year+1900,
+ time_gmt->tm_mon+1,
+ time_gmt->tm_mday,
+ time_gmt->tm_hour,
+ time_gmt->tm_min,
+ time_gmt->tm_sec);
+ retval = format_kw_string(datap, kwordp, fbuffer);
+ }
+ return(retval);
+}
+\f
+/*
+ * format_kw_salttype() - Format a keyword=<salttype> pair.
+ */
+static krb5_error_code
+format_kw_salttype(datap, kwordp, dbentp)
+ krb5_data *datap;
+ char *kwordp;
+ krb5_db_entry *dbentp;
+{
+ krb5_error_code retval;
+ char fbuffer[BUFSIZ];
+ char *sstring;
+
+ retval = EINVAL;
+ sstring = salt_type_to_string(dbentp->salt_type);
+ if (sstring) {
+ strcpy(fbuffer, sstring);
+ /* Only add secondary salt type if it's different and valid */
+ if ((dbentp->salt_type != dbentp->alt_salt_type) &&
+ (sstring = salt_type_to_string(dbentp->alt_salt_type))) {
+ strcat(fbuffer,",");
+ strcat(fbuffer,sstring);
+ }
+ retval = format_kw_string(datap, kwordp, fbuffer);
+ }
+ return(retval);
+}
+\f
+/*
+ * krb5_adm_dbent_to_proto() - Convert database a database entry into
+ * an external attribute list.
+ *
+ * "valid" controls the generation of "datap" and "nentp". For each
+ * corresponding bit in "valid" a keyword-value pair is generated from
+ * values in "dbentp" or "password" and put into "datap". The number of
+ * generated pairs is returned in "nentp". Additionally, the KRB5_ADM_M_SET
+ * and KRB5_ADM_M_GET bits control whether we are generating attribute lists
+ * for a "set" operation or a "get" operation. One of these bits must be
+ * specified.
+ *
+ * Successful callers must free the storage for datap and datap->data
+ * either manually or using krb5_free_adm_data().
+ */
+krb5_error_code
+krb5_adm_dbent_to_proto(kcontext, valid, dbentp, password, nentp, datap)
+ krb5_context kcontext; /* Kerberos context */ /* In */
+ krb5_ui_4 valid; /* Valid bitmask */ /* In */
+ krb5_db_entry *dbentp; /* Database entry */ /* In */
+ char *password; /* New password for set */ /* In */
+ krb5_int32 *nentp; /* Number of components */ /* Out */
+ krb5_data **datap; /* Output list */ /* Out */
+{
+ krb5_error_code kret;
+ krb5_data *outlist;
+ size_t n2alloc;
+ int outindex;
+ krb5_boolean is_set;
+
+ kret = 0;
+ /* First check out whether this is a set or get and the mask */
+ is_set = ((valid & KRB5_ADM_M_SET) == KRB5_ADM_M_SET);
+ if ((is_set && ((valid & ~KRB5_ADM_M_SET_VALID) != 0)) ||
+ (!is_set && ((valid & ~KRB5_ADM_M_GET_VALID) != 0)) ||
+ (!is_set && ((valid & KRB5_ADM_M_GET) == 0)))
+ return(EINVAL);
+
+ /* Allocate a new array of output data */
+ n2alloc = (is_set) ? KRB5_ADM_KW_MAX_SET : KRB5_ADM_KW_MAX_GET;
+ n2alloc *= sizeof(krb5_data);
+ outindex = 0;
+ outlist = (krb5_data *) malloc(n2alloc);
+ if (outlist) {
+ /* Clear out the output data list */
+ memset((char *) outlist, 0, n2alloc);
+
+ /* Handle password only for set request */
+ if (is_set &&
+ ((valid & KRB5_ADM_M_PASSWORD) != 0) &&
+ password) {
+ if (kret = format_kw_string(&outlist[outindex],
+ KRB5_ADM_KW_PASSWORD,
+ password))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle key version number */
+ if ((valid & KRB5_ADM_M_KVNO) != 0) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_KVNO,
+ (krb5_ui_4) dbentp->kvno))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle maximum ticket lifetime */
+ if ((valid & KRB5_ADM_M_MAXLIFE) != 0) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_MAXLIFE,
+ (krb5_ui_4) dbentp->max_life))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle maximum renewable ticket lifetime */
+ if ((valid & KRB5_ADM_M_MAXRENEWLIFE) != 0) {
+ if (kret =
+ format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_MAXRENEWLIFE,
+ (krb5_ui_4) dbentp->max_renewable_life))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle principal expiration */
+ if ((valid & KRB5_ADM_M_EXPIRATION) != 0) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_EXPIRATION,
+ &dbentp->expiration))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle password expiration */
+ if ((valid & KRB5_ADM_M_PWEXPIRATION) != 0) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_PWEXPIRATION,
+ &dbentp->pw_expiration))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Random key */
+ if ((valid & KRB5_ADM_M_RANDOMKEY) != 0) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_RANDOMKEY,
+ 1))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle flags */
+ if ((valid & KRB5_ADM_M_FLAGS) != 0) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_FLAGS,
+ (krb5_ui_4) dbentp->attributes))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle salt types */
+ if ((valid & KRB5_ADM_M_SALTTYPE) != 0) {
+ if (kret = format_kw_salttype(&outlist[outindex],
+ KRB5_ADM_KW_SALTTYPE,
+ dbentp))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle master key version number */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_MKVNO) != 0)) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_MKVNO,
+ (krb5_ui_4) dbentp->mkvno))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle last successful password change */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_LASTPWCHANGE) != 0)) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_LASTPWCHANGE,
+ &dbentp->last_pwd_change))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle last successful password entry */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_LASTSUCCESS) != 0)) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_LASTSUCCESS,
+ &dbentp->last_success))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle last failed password attempt */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_LASTFAILED) != 0)) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_LASTFAILED,
+ &dbentp->last_failed))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle number of failed password attempts */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_FAILCOUNT) != 0)) {
+ if (kret = format_kw_integer(&outlist[outindex],
+ KRB5_ADM_KW_FAILCOUNT,
+ (krb5_ui_4) dbentp->fail_auth_count))
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle last modification principal name */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_MODNAME) != 0)) {
+ char *modifier_name;
+
+ /* Flatten the name, format it then free it. */
+ if (kret = krb5_unparse_name(kcontext,
+ dbentp->mod_name,
+ &modifier_name))
+ goto choke;
+
+ kret = format_kw_string(&outlist[outindex],
+ KRB5_ADM_KW_MODNAME,
+ modifier_name);
+ krb5_xfree(modifier_name);
+ if (kret)
+ goto choke;
+ else
+ outindex++;
+ }
+ /* Handle last modification time */
+ if (!is_set &&
+ ((valid & KRB5_ADM_M_MODDATE) != 0)) {
+ if (kret = format_kw_gentime(&outlist[outindex],
+ KRB5_ADM_KW_MODDATE,
+ &dbentp->mod_date))
+ goto choke;
+ else
+ outindex++;
+ }
+ }
+ else
+ kret = ENOMEM;
+ choke:
+ if (kret) {
+ if (outlist) {
+ int i;
+ for (i=0; i<outindex; i++) {
+ if (outlist[i].data) {
+ memset(outlist[i].data, 0, (size_t) outlist[i].length);
+ free(outlist[i].data);
+ }
+ }
+ free(outlist);
+ }
+ outlist = (krb5_data *) NULL;
+ outindex = 0;
+ }
+ *datap = outlist;
+ *nentp = outindex;
+ return(kret);
+}
+