summaryrefslogtreecommitdiffstats
path: root/src/lib/kadm/t_dbentry.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/kadm/t_dbentry.c')
-rw-r--r--src/lib/kadm/t_dbentry.c965
1 files changed, 965 insertions, 0 deletions
diff --git a/src/lib/kadm/t_dbentry.c b/src/lib/kadm/t_dbentry.c
new file mode 100644
index 000000000..6c71234b3
--- /dev/null
+++ b/src/lib/kadm/t_dbentry.c
@@ -0,0 +1,965 @@
+/*
+ * lib/kadm/t_dbentry.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.
+ *
+ */
+
+/*
+ * t_dbentry.c - Test function of krb5_adm_{proto_to_dbent,dbent_to_proto}.
+ */
+
+#include "k5-int.h"
+#include "adm.h"
+#include "adm_proto.h"
+
+#if HAVE_SRAND48
+#define SRAND srand48
+#define RAND lrand48
+#define RAND_TYPE long
+#endif /* HAVE_SRAND48 */
+
+#if !defined(RAND_TYPE) && defined(HAVE_SRAND)
+#define SRAND srand
+#define RAND rand
+#define RAND_TYPE int
+#endif /* !defined(RAND_TYPE) && defined(HAVE_SRAND) */
+
+#if !defined(RAND_TYPE) && defined(HAVE_SRANDOM)
+#define SRAND srandom
+#define RAND random
+#define RAND_TYPE long
+#endif /* !defined(RAND_TYPE) && defined(HAVE_SRANDOM) */
+
+#if !defined(RAND_TYPE)
+There is no random number generator.
+#endif /* !defined(RAND_TYPE) */
+
+/*
+ * Generate a random event that has an a/b chance of succeeding
+ */
+#define RANDOM_EVENT(a,b) ((RAND() % b) < a)
+/* Define probabilities of generating each attribute type */
+#define PASSWORD_EVENT RANDOM_EVENT(3,5)
+#define KVNO_EVENT RANDOM_EVENT(2,5)
+#define MAXLIFE_EVENT RANDOM_EVENT(1,4)
+#define MAXRENEWLIFE_EVENT RANDOM_EVENT(1,4)
+#define EXPIRATION_EVENT RANDOM_EVENT(1,3)
+#define PWEXPIRATION_EVENT RANDOM_EVENT(1,3)
+#define RANDOMKEY_EVENT RANDOM_EVENT(1,8)
+#define FLAGS_EVENT RANDOM_EVENT(9,10)
+#define SALT_EVENT RANDOM_EVENT(7,16)
+#define MKVNO_EVENT RANDOM_EVENT(2,5)
+#define LASTPWCHANGE_EVENT RANDOM_EVENT(2,5)
+#define LASTSUCCESS_EVENT RANDOM_EVENT(2,5)
+#define LASTFAILED_EVENT RANDOM_EVENT(2,5)
+#define FAILCOUNT_EVENT RANDOM_EVENT(2,5)
+#define MODNAME_EVENT RANDOM_EVENT(2,5)
+#define MODDATE_EVENT RANDOM_EVENT(2,5)
+#define EXTRA_EVENT RANDOM_EVENT(1,5)
+#define SET_EVENT RANDOM_EVENT(1,4)
+
+/*
+ * Convert a time value to a string for output messages.
+ */
+static char *
+time2string(ts)
+ krb5_timestamp ts;
+{
+ static char buf[1024];
+
+ strcpy(buf, ctime((time_t *) &ts));
+ /* Remove trailing \n */
+ buf[strlen(buf)-1] = '\0';
+ return(buf);
+}
+
+static krb5_boolean
+aux_data_inequal(in, out)
+ krb5_db_entry *in, *out;
+{
+ krb5_tl_data *intl, *outtl;
+ krb5_boolean found;
+
+ if (in->n_tl_data != out->n_tl_data)
+ return(1);
+ found = 1;
+ for (intl = in->tl_data; intl; intl = intl->tl_data_next) {
+ found = 0;
+ for (outtl = out->tl_data; outtl; outtl = outtl->tl_data_next) {
+ if ((intl->tl_data_type == outtl->tl_data_type) &&
+ (intl->tl_data_length == outtl->tl_data_length) &&
+ !memcmp(intl->tl_data_contents,
+ outtl->tl_data_contents,
+ intl->tl_data_length)) {
+ outtl->tl_data_length = -outtl->tl_data_length;
+ found = 1;
+ }
+ }
+ if (!found)
+ break;
+ }
+ for (outtl = out->tl_data; outtl; outtl = outtl->tl_data_next) {
+ if (outtl->tl_data_length < 0)
+ outtl->tl_data_length = -outtl->tl_data_length;
+ }
+ return(!found);
+}
+
+static void
+print_auxdata(entp)
+ krb5_db_entry *entp;
+{
+ krb5_tl_data *tl;
+ int i;
+
+ for (tl = entp->tl_data; tl; tl = tl->tl_data_next) {
+ printf("tl_data(%d)[len=%d] ", tl->tl_data_type, tl->tl_data_length);
+ for (i=0; i<tl->tl_data_length; i++)
+ printf("%02x ", tl->tl_data_contents[i]);
+ printf("\n");
+ }
+}
+
+static krb5_boolean
+key_data_inequal(in, out)
+ krb5_db_entry *in, *out;
+{
+ krb5_boolean found;
+ int i, j;
+
+ if (in->n_key_data != out->n_key_data)
+ return(1);
+ found = 1;
+ for (i=0; i<in->n_key_data; i++) {
+ found = 0;
+ for (j=0; j<out->n_key_data; j++) {
+ if ((in->key_data[i].key_data_kvno ==
+ out->key_data[j].key_data_kvno) &&
+ (in->key_data[i].key_data_type[0] ==
+ out->key_data[j].key_data_type[0]) &&
+ (in->key_data[i].key_data_type[1] ==
+ out->key_data[j].key_data_type[1]) &&
+ (in->key_data[i].key_data_length[0] ==
+ out->key_data[j].key_data_length[0]) &&
+ (in->key_data[i].key_data_length[1] ==
+ out->key_data[j].key_data_length[1]) &&
+ !memcmp(in->key_data[i].key_data_contents[0],
+ out->key_data[j].key_data_contents[0],
+ in->key_data[i].key_data_length[0]) &&
+ (!in->key_data[i].key_data_length[1] ||
+ !memcmp(in->key_data[i].key_data_contents[1],
+ out->key_data[j].key_data_contents[1],
+ in->key_data[i].key_data_length[1]))) {
+ out->key_data[j].key_data_length[0] =
+ -out->key_data[j].key_data_length[0];
+ found = 1;
+ }
+ }
+ if (!found)
+ break;
+ }
+ for (j=0; j<out->n_key_data; j++) {
+ if (out->key_data[j].key_data_length[0] < 0)
+ out->key_data[j].key_data_length[0] =
+ -out->key_data[j].key_data_length[0];
+ }
+ return(!found);
+}
+
+static void
+print_keydata(entp)
+ krb5_db_entry *entp;
+{
+ int i, j;
+
+ for (j=0; j<entp->n_key_data; j++) {
+ printf("key(vno=%d):key(type=%d)[contents= ",
+ entp->key_data[j].key_data_kvno,
+ entp->key_data[j].key_data_type[0]);
+ for (i=0; i<entp->key_data[j].key_data_length[0]; i++)
+ printf("%02x ", entp->key_data[j].key_data_contents[0][i]);
+ printf("] salt(type=%d)", entp->key_data[j].key_data_type[1]);
+ if (entp->key_data[j].key_data_length[1]) {
+ printf("[contents= ");
+ for (i=0; i<entp->key_data[j].key_data_length[1]; i++)
+ printf("%02x ", entp->key_data[j].key_data_contents[1][i]);
+ printf("]");
+ }
+ printf("\n");
+ }
+}
+
+static krb5_boolean
+extra_data_inequal(in, out)
+ krb5_db_entry *in, *out;
+{
+ if (in->e_length != out->e_length)
+ return(1);
+ if (in->e_length && memcmp(in->e_data, out->e_data, (size_t) in->e_length))
+ return(1);
+ return(0);
+}
+
+static void
+print_extradata(entp)
+ krb5_db_entry *entp;
+{
+ int i;
+
+ printf("extra:");
+ for (i=0; i<entp->e_length; i++)
+ printf("%02x ", entp->e_data[i]);
+ printf("\n");
+}
+
+/*
+ * Generate a database entry, either randomly, or using well known values.
+ */
+static void
+gen_dbent(kcontext, dbentp, isrand, validp, pwdp, expectp)
+ krb5_context kcontext;
+ krb5_db_entry *dbentp;
+ krb5_boolean isrand;
+ krb5_ui_4 *validp;
+ char **pwdp;
+ krb5_boolean *expectp;
+{
+ time_t now;
+ krb5_boolean is_set;
+ size_t pwlen;
+ int i;
+ static char *defpass = "testpassword";
+ static char *defprinc = "testprinc/instance@realm";
+
+ now = time((time_t *) NULL);
+ is_set = ((*validp & KRB5_ADM_M_SET) != 0);
+
+ /* Do password on set */
+ if (isrand) {
+ if (PASSWORD_EVENT) {
+ pwlen = 9 + (RAND() % 56);
+ *pwdp = (char *) malloc(pwlen);
+ for (i=0; i<pwlen-1; i++) {
+ (*pwdp)[i] = RAND() % 128;
+ while (!isalnum((int) (*pwdp)[i]))
+ (*pwdp)[i] = RAND() % 128;
+ }
+ (*pwdp)[pwlen-1] = '\0';
+ *validp |= KRB5_ADM_M_PASSWORD;
+ }
+ }
+ else {
+ if (is_set) {
+ *pwdp = (char *) malloc(strlen(defpass)+1);
+ strcpy(*pwdp, defpass);
+ *validp |= KRB5_ADM_M_PASSWORD;
+ }
+ }
+
+ /* Do maxlife */
+ if (isrand) {
+ if (MAXLIFE_EVENT) {
+ dbentp->max_life = RAND();
+ *validp |= KRB5_ADM_M_MAXLIFE;
+ }
+ }
+ else {
+ dbentp->max_life = KRB5_KDB_MAX_LIFE;
+ *validp |= KRB5_ADM_M_MAXLIFE;
+ }
+
+ /* Do maxrenewlife */
+ if (isrand) {
+ if (MAXRENEWLIFE_EVENT) {
+ dbentp->max_renewable_life = RAND();
+ *validp |= KRB5_ADM_M_MAXRENEWLIFE;
+ }
+ }
+ else {
+ dbentp->max_renewable_life = KRB5_KDB_MAX_RLIFE;
+ *validp |= KRB5_ADM_M_MAXRENEWLIFE;
+ }
+
+ /* Do expiration */
+ if (isrand) {
+ if (EXPIRATION_EVENT) {
+ dbentp->expiration = RAND();
+ *validp |= KRB5_ADM_M_EXPIRATION;
+ }
+ }
+ else {
+ dbentp->expiration = KRB5_KDB_EXPIRATION;
+ *validp |= KRB5_ADM_M_EXPIRATION;
+ }
+
+ /* Do pw_expiration */
+ if (isrand) {
+ if (PWEXPIRATION_EVENT) {
+ dbentp->pw_expiration = RAND();
+ *validp |= KRB5_ADM_M_PWEXPIRATION;
+ }
+ }
+ else {
+ dbentp->pw_expiration = (krb5_timestamp) now + 3600;
+ *validp |= KRB5_ADM_M_PWEXPIRATION;
+ }
+
+ /* Do randomkey - 1/8 probability of doing randomkey */
+ if (isrand && (RANDOMKEY_EVENT)) {
+ *validp |= KRB5_ADM_M_RANDOMKEY;
+ }
+
+ /* Do flags */
+ if (isrand) {
+ if (FLAGS_EVENT) {
+ dbentp->attributes = RAND();
+ *validp |= KRB5_ADM_M_FLAGS;
+ }
+ }
+ else {
+ dbentp->attributes = KRB5_KDB_DEF_FLAGS;
+ *validp |= KRB5_ADM_M_FLAGS;
+ }
+
+ /* Do lastsuccess */
+ if (isrand) {
+ if (LASTSUCCESS_EVENT) {
+ dbentp->last_success = RAND();
+ *validp |= KRB5_ADM_M_LASTSUCCESS;
+ }
+ }
+ else {
+ if (!is_set) {
+ dbentp->last_success = (krb5_timestamp) now - 3600;
+ *validp |= KRB5_ADM_M_LASTSUCCESS;
+ }
+ }
+
+ /* Do lastfailed */
+ if (isrand) {
+ if (LASTFAILED_EVENT) {
+ dbentp->last_failed = RAND();
+ *validp |= KRB5_ADM_M_LASTFAILED;
+ }
+ }
+ else {
+ if (!is_set) {
+ dbentp->last_failed = (krb5_timestamp) now - 3600;
+ *validp |= KRB5_ADM_M_LASTFAILED;
+ }
+ }
+
+ /* Do failcount */
+ if (isrand) {
+ if (FAILCOUNT_EVENT) {
+ dbentp->fail_auth_count = RAND();
+ *validp |= KRB5_ADM_M_FAILCOUNT;
+ }
+ }
+ else {
+ if (!is_set) {
+ dbentp->fail_auth_count = 0;
+ *validp |= KRB5_ADM_M_FAILCOUNT;
+ }
+ }
+
+ /*
+ * Generate auxiliary data.
+ */
+ if (isrand) {
+ krb5_octet *lpw_change;
+ krb5_tl_data *tldata;
+ krb5_timestamp lpw;
+ krb5_tl_mod_princ mprinc;
+ int didone;
+
+ didone = 0;
+ if (LASTPWCHANGE_EVENT) {
+ if ((tldata = (krb5_tl_data *) malloc(sizeof(krb5_tl_data))) &&
+ (lpw_change = (krb5_octet *) malloc(sizeof(krb5_timestamp)))) {
+ lpw = (krb5_timestamp) RAND();
+ lpw_change[0] = (unsigned char) ((lpw >> 24) & 0xff);
+ lpw_change[1] = (unsigned char) ((lpw >> 16) & 0xff);
+ lpw_change[2] = (unsigned char) ((lpw >> 8) & 0xff);
+ lpw_change[3] = (unsigned char) (lpw & 0xff);
+ tldata->tl_data_next = (krb5_tl_data *) NULL;
+ tldata->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+ tldata->tl_data_length = sizeof(krb5_timestamp);
+ tldata->tl_data_contents = lpw_change;
+ dbentp->n_tl_data = 1;
+ dbentp->tl_data = tldata;
+ didone++;
+ }
+ }
+ if (MODNAME_EVENT || MODDATE_EVENT) {
+ mprinc.mod_date = (krb5_timestamp) RAND();
+ if (!krb5_parse_name(kcontext, defprinc, &mprinc.mod_princ)) {
+ if (!krb5_dbe_encode_mod_princ_data(kcontext, &mprinc, dbentp))
+ didone++;
+ }
+ }
+ if (didone)
+ *validp |= KRB5_ADM_M_AUXDATA;
+ }
+ else {
+ krb5_octet *lpw_change;
+ krb5_tl_data *tldata;
+ krb5_timestamp lpw;
+ krb5_tl_mod_princ mprinc;
+
+ if ((tldata = (krb5_tl_data *) malloc(sizeof(krb5_tl_data))) &&
+ (lpw_change = (krb5_octet *) malloc(sizeof(krb5_timestamp)))) {
+ lpw = (krb5_timestamp) now - 3600;
+ lpw_change[0] = (unsigned char) ((lpw >> 24) & 0xff);
+ lpw_change[1] = (unsigned char) ((lpw >> 16) & 0xff);
+ lpw_change[2] = (unsigned char) ((lpw >> 8) & 0xff);
+ lpw_change[3] = (unsigned char) (lpw & 0xff);
+ tldata->tl_data_next = (krb5_tl_data *) NULL;
+ tldata->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+ tldata->tl_data_length = sizeof(krb5_timestamp);
+ tldata->tl_data_contents = lpw_change;
+ dbentp->n_tl_data = 1;
+ dbentp->tl_data = tldata;
+ }
+ mprinc.mod_date = (krb5_timestamp) now;
+ if (!krb5_parse_name(kcontext, defprinc, &mprinc.mod_princ))
+ krb5_dbe_encode_mod_princ_data(kcontext, &mprinc, dbentp);
+ *validp |= KRB5_ADM_M_AUXDATA;
+ }
+
+ /* Make key data */
+ if (isrand) {
+ int i, j, kl, sl;
+
+ if (!is_set) {
+ for (i=0; i<(1+(RAND()%8)); i++) {
+ if (!krb5_dbe_create_key_data(kcontext, dbentp)) {
+ dbentp->key_data[i].key_data_kvno = RAND() % 32768;
+ dbentp->key_data[i].key_data_type[0] = RAND() % 32768;
+ dbentp->key_data[i].key_data_type[1] = RAND() % 32768;
+ kl = dbentp->key_data[i].key_data_length[0] =
+ 8 + (RAND() % 128);
+ sl = dbentp->key_data[i].key_data_length[1] =
+ 0 + (RAND() % 128);
+ if (dbentp->key_data[i].key_data_contents[0] =
+ (krb5_octet *) malloc(kl)) {
+ for (j=0; j<kl; j++) {
+ dbentp->key_data[i].key_data_contents[0][j] =
+ RAND() % 256;
+ }
+ }
+ if (dbentp->key_data[i].key_data_contents[1] =
+ (krb5_octet *) malloc(sl)) {
+ for (j=0; j<sl; j++) {
+ dbentp->key_data[i].key_data_contents[1][j] =
+ RAND() % 256;
+ }
+ }
+ *validp |= KRB5_ADM_M_KEYDATA;
+ }
+ }
+ }
+ }
+ else {
+ if (!is_set) {
+ if (!krb5_dbe_create_key_data(kcontext, dbentp)) {
+ int i;
+
+ dbentp->key_data[0].key_data_kvno = 1;
+ dbentp->key_data[0].key_data_type[0] = 1;
+ dbentp->key_data[0].key_data_type[1] = 0;
+ dbentp->key_data[0].key_data_length[0] = 24;
+ dbentp->key_data[0].key_data_length[1] = 0;
+ if (dbentp->key_data[0].key_data_contents[0] =
+ (krb5_octet *) malloc(24)) {
+ for (i=0; i<24; i++)
+ dbentp->key_data[0].key_data_contents[0][i] = RAND() % 256;
+ }
+ dbentp->key_data[0].key_data_contents[1] = (krb5_octet *) NULL;
+ *validp |= KRB5_ADM_M_KEYDATA;
+ }
+ }
+ }
+
+ /* Make extra data */
+ if (isrand && EXTRA_EVENT) {
+ dbentp->e_length = 8 + (RAND() % 504);
+ if (dbentp->e_data = (krb5_octet *)
+ malloc((size_t) dbentp->e_length)) {
+ int j;
+ for (j=0; j<dbentp->e_length; j++) {
+ dbentp->e_data[j] = RAND() % 256;
+ }
+ *validp |= KRB5_ADM_M_EXTRADATA;
+ }
+ else
+ dbentp->e_length = 0;
+ }
+
+ if (is_set) {
+ /* Only 25% may fail at most */
+ if (isrand && ((RAND() % 100) < 75)) {
+ *validp &= KRB5_ADM_M_SET_VALID;
+ }
+#ifdef notdef
+ if ((*validp & KRB5_ADM_M_PASSWORD) != 0)
+ *validp &= ~KRB5_ADM_M_RANDOMKEY;
+#endif /* notdef */
+ *expectp = ((*validp & ~KRB5_ADM_M_SET_VALID) != 0) ? 1 : 0;
+ }
+ else {
+ /* Only 25% may fail at most */
+ if (isrand && ((RAND() % 100) < 75))
+ *validp &= KRB5_ADM_M_GET_VALID;
+ *expectp = ((*validp & ~KRB5_ADM_M_GET_VALID) != 0) ? 1 : 0;
+ }
+}
+
+/*
+ * Compare two entries.
+ */
+static krb5_boolean
+compare_entries(kcontext, ivalid, ientp, ipwd, ovalid, oentp, opwd)
+ krb5_context kcontext;
+ krb5_ui_4 ivalid;
+ krb5_db_entry *ientp;
+ char *ipwd;
+ krb5_ui_4 ovalid;
+ krb5_db_entry *oentp;
+ char *opwd;
+{
+ /* Handle/compare password */
+ if (((ivalid & KRB5_ADM_M_PASSWORD) != 0) &&
+ (((ovalid & KRB5_ADM_M_PASSWORD) == 0) ||
+ strcmp(ipwd, opwd)))
+ return(0);
+
+ /* Handle/compare maxlife */
+ if (((ivalid & KRB5_ADM_M_MAXLIFE) != 0) &&
+ (((ovalid & KRB5_ADM_M_MAXLIFE) == 0) ||
+ (ientp->max_life != oentp->max_life)))
+ return(0);
+
+ /* Handle/compare maxrenewlife */
+ if (((ivalid & KRB5_ADM_M_MAXRENEWLIFE) != 0) &&
+ (((ovalid & KRB5_ADM_M_MAXRENEWLIFE) == 0) ||
+ (ientp->max_renewable_life != oentp->max_renewable_life)))
+ return(0);
+
+ /* Handle/compare expiration */
+ if (((ivalid & KRB5_ADM_M_EXPIRATION) != 0) &&
+ (((ovalid & KRB5_ADM_M_EXPIRATION) == 0) ||
+ (ientp->expiration != oentp->expiration)))
+ return(0);
+
+ /* Handle/compare pwexpiration */
+ if (((ivalid & KRB5_ADM_M_PWEXPIRATION) != 0) &&
+ (((ovalid & KRB5_ADM_M_PWEXPIRATION) == 0) ||
+ (ientp->pw_expiration != oentp->pw_expiration)))
+ return(0);
+
+#ifdef notdef
+ /* Handle/compare random key */
+ if (((ivalid & KRB5_ADM_M_RANDOMKEY) != 0) &&
+ ((ovalid & KRB5_ADM_M_PASSWORD) != 0))
+ return(0);
+#endif /* notdef */
+
+ /* Handle/compare flags */
+ if (((ivalid & KRB5_ADM_M_FLAGS) != 0) &&
+ (((ovalid & KRB5_ADM_M_FLAGS) == 0) ||
+ (ientp->attributes != oentp->attributes)))
+ return(0);
+
+ /* Handle/compare lastsuccess */
+ if (((ivalid & KRB5_ADM_M_LASTSUCCESS) != 0) &&
+ (((ovalid & KRB5_ADM_M_LASTSUCCESS) == 0) ||
+ (ientp->last_success != oentp->last_success)))
+ return(0);
+
+ /* Handle/compare lastfailed */
+ if (((ivalid & KRB5_ADM_M_LASTFAILED) != 0) &&
+ (((ovalid & KRB5_ADM_M_LASTFAILED) == 0) ||
+ (ientp->last_failed != oentp->last_failed)))
+ return(0);
+
+ /* Handle/compare failcount */
+ if (((ivalid & KRB5_ADM_M_FAILCOUNT) != 0) &&
+ (((ovalid & KRB5_ADM_M_FAILCOUNT) == 0) ||
+ (ientp->fail_auth_count != oentp->fail_auth_count)))
+ return(0);
+
+ /* Handle/compare auxiliary data */
+ if (((ivalid & KRB5_ADM_M_AUXDATA) != 0) &&
+ (((ovalid & KRB5_ADM_M_AUXDATA) == 0) ||
+ aux_data_inequal(ientp, oentp)))
+ return(0);
+
+ /* Handle/compare key data */
+ if (((ivalid & KRB5_ADM_M_KEYDATA) != 0) &&
+ (((ovalid & KRB5_ADM_M_KEYDATA) == 0) ||
+ key_data_inequal(ientp, oentp)))
+ return(0);
+
+ /* Handle/compare extra data */
+ if (((ivalid & KRB5_ADM_M_EXTRADATA) != 0) &&
+ (((ovalid & KRB5_ADM_M_EXTRADATA) == 0) ||
+ extra_data_inequal(ientp, oentp)))
+ return(0);
+
+ return(1);
+}
+
+/*
+ * Print out an entry.
+ */
+static void
+print_dbent(kcontext, ivalid, ientp, ipwd)
+ krb5_context kcontext;
+ krb5_ui_4 ivalid;
+ krb5_db_entry *ientp;
+ char *ipwd;
+{
+ printf("Valid mask:\t%08x\n", ivalid);
+
+ /* Print password */
+ if ((ivalid & KRB5_ADM_M_PASSWORD) != 0)
+ printf("Password:\t%s\n", ipwd);
+
+ /* Print maxlife */
+ if ((ivalid & KRB5_ADM_M_MAXLIFE) != 0)
+ printf("max_life:\t%8d\t%08x\n", ientp->max_life, ientp->max_life);
+
+ /* Print maxrenewlife */
+ if ((ivalid & KRB5_ADM_M_MAXRENEWLIFE) != 0)
+ printf("max_rlife:\t%8d\t%08x\n", ientp->max_renewable_life,
+ ientp->max_renewable_life);
+
+ /* Print expiration */
+ if ((ivalid & KRB5_ADM_M_EXPIRATION) != 0)
+ printf("expires:\t%8d\t%08x\t%s\n", ientp->expiration,
+ ientp->expiration, time2string(ientp->expiration));
+
+ /* Print pwexpiration */
+ if ((ivalid & KRB5_ADM_M_PWEXPIRATION) != 0)
+ printf("pw expires:\t%8d\t%08x\t%s\n", ientp->pw_expiration,
+ ientp->pw_expiration, time2string(ientp->pw_expiration));
+
+ /* Print random key */
+ if ((ivalid & KRB5_ADM_M_RANDOMKEY) != 0)
+ printf("random key\n");
+
+ /* Print flags */
+ if ((ivalid & KRB5_ADM_M_FLAGS) != 0)
+ printf("flags:\t\t%8d\t%08x\n", ientp->attributes, ientp->attributes);
+
+ /* Print lastsuccess */
+ if ((ivalid & KRB5_ADM_M_LASTSUCCESS) != 0)
+ printf("lastsucc:\t%8d\t%08x\t%s\n", ientp->last_success,
+ ientp->last_success, time2string(ientp->last_success));
+
+ /* Print lastfailed */
+ if ((ivalid & KRB5_ADM_M_LASTFAILED) != 0)
+ printf("lastfail:\t%8d\t%08x\t%s\n", ientp->last_failed,
+ ientp->last_failed, time2string(ientp->last_failed));
+
+ /* Print failcount */
+ if ((ivalid & KRB5_ADM_M_FAILCOUNT) != 0)
+ printf("failcount:\t%8d\t%08x\n", ientp->fail_auth_count,
+ ientp->fail_auth_count);
+
+ /* Print auxiliary data */
+ if ((ivalid & KRB5_ADM_M_AUXDATA) != 0)
+ print_auxdata(ientp);
+
+ /* Print key data */
+ if ((ivalid & KRB5_ADM_M_KEYDATA) != 0)
+ print_keydata(ientp);
+
+ /* Print extra data */
+ if ((ivalid & KRB5_ADM_M_EXTRADATA) != 0)
+ print_extradata(ientp);
+}
+
+/*
+ * Do a test case.
+ *
+ * Strategy: Generate the desired database entry type, then convert it using
+ * krb5_adm_dbent_to_proto, then convert it back to a database entry
+ * using krb5_adm_proto_to_dbent. Then verify the match.
+ */
+static krb5_int32
+do_test(pname, verbose, isrand, is_a_set, title, passno)
+ char *pname;
+ krb5_boolean verbose;
+ krb5_boolean isrand;
+ krb5_boolean is_a_set;
+ char *title;
+ krb5_int32 passno;
+{
+ krb5_context kcontext;
+ krb5_db_entry *in_dbent;
+ krb5_db_entry *out_dbent;
+ krb5_error_code kret;
+ krb5_int32 ncomps;
+ krb5_data *complist;
+ krb5_ui_4 in_validmask;
+ krb5_ui_4 out_validmask;
+ char *in_password;
+ char *out_password;
+ krb5_boolean should_fail;
+
+ if (verbose) {
+ printf("* Begin %s", title);
+ if (isrand)
+ printf(" pass %d", passno);
+ printf("\n");
+ }
+
+ kret = 0;
+ krb5_init_context(&kcontext);
+ krb5_init_ets(kcontext);
+ in_dbent = (krb5_db_entry *) malloc(sizeof(krb5_db_entry));
+ out_dbent = (krb5_db_entry *) malloc(sizeof(krb5_db_entry));
+ if (in_dbent && out_dbent) {
+ /* Initialize our data */
+ memset((char *) in_dbent, 0, sizeof(krb5_db_entry));
+ memset((char *) out_dbent, 0, sizeof(krb5_db_entry));
+ in_password = out_password = (char *) NULL;
+ out_validmask = 0;
+ ncomps = 0;
+ complist = (krb5_data *) NULL;
+ should_fail = 0;
+ if (!isrand) {
+ if (is_a_set)
+ in_validmask = KRB5_ADM_M_SET;
+ else
+ in_validmask = KRB5_ADM_M_GET;
+ }
+ else {
+ if (SET_EVENT)
+ in_validmask = KRB5_ADM_M_SET;
+ else
+ in_validmask = KRB5_ADM_M_GET;
+ }
+
+ /* Generate the database entry. */
+ gen_dbent(kcontext,
+ in_dbent, isrand, &in_validmask, &in_password, &should_fail);
+
+ /* Convert it to the o-t-w protocol */
+ if (!(kret = krb5_adm_dbent_to_proto(kcontext,
+ in_validmask,
+ in_dbent,
+ in_password,
+ &ncomps,
+ &complist))) {
+ /* If this should fail, then we've got a problem here */
+ if (!should_fail) {
+
+ /* Otherwise, convert it back to a database entry */
+ if (!(kret = krb5_adm_proto_to_dbent(kcontext,
+ ncomps,
+ complist,
+ &out_validmask,
+ out_dbent,
+ &out_password))) {
+ /* Compare the entries */
+ if (compare_entries(kcontext,
+ in_validmask,
+ in_dbent,
+ in_password,
+ out_validmask,
+ out_dbent,
+ out_password)) {
+ /* Success */
+ if (verbose) {
+ printf("Successful translation");
+ printf(" during %s", title);
+ if (isrand)
+ printf(" pass %d", passno);
+ printf(" of:\n");
+ print_dbent(kcontext,
+ in_validmask, in_dbent, in_password);
+ }
+ }
+ else {
+ /* Failed */
+ fprintf(stderr, "%s: comparison mismatch", pname);
+ fprintf(stderr, " during %s", title);
+ if (isrand)
+ fprintf(stderr, " pass %d", passno);
+ fprintf(stderr, "\n");
+ if (verbose) {
+ printf("Input entry is as follows:\n");
+ print_dbent(kcontext,
+ in_validmask, in_dbent, in_password);
+ printf("Output entry is as follows:\n");
+ print_dbent(kcontext,
+ out_validmask,
+ out_dbent,
+ out_password);
+ }
+ kret = KRB5KRB_ERR_GENERIC;
+ }
+ if (out_password)
+ krb5_xfree(out_password);
+ }
+ else {
+ /* Conversion to database entry failed */
+ fprintf(stderr, "%s: protocol decode failed with %d",
+ pname, kret);
+ fprintf(stderr, " during %s", title);
+ if (isrand)
+ fprintf(stderr, " pass %d", passno);
+ fprintf(stderr, "\n");
+ }
+ }
+ else {
+ /* Should have failed */
+ fprintf(stderr, "%s: protocol encode unexpectedly succeeded",
+ pname);
+ kret = KRB5KRB_ERR_GENERIC;
+ fprintf(stderr, " during %s", title);
+ if (isrand)
+ fprintf(stderr, " pass %d", passno);
+ fprintf(stderr, "\n");
+ }
+ krb5_free_adm_data(kcontext, ncomps, complist);
+ }
+ else {
+ /* Convert to protocol failed */
+ if (!should_fail) {
+ /* Unexpected failure */
+ fprintf(stderr, "%s: protocol encode failed with %d",
+ pname, kret);
+ fprintf(stderr, " during %s", title);
+ if (isrand)
+ fprintf(stderr, " pass %d", passno);
+ fprintf(stderr, "\n");
+ }
+ else {
+ /* Success */
+ if (verbose)
+ printf("- Expected failure OK\n");
+ kret = 0;
+ }
+ }
+ /* Cleanup */
+ if (in_password)
+ free(in_password);
+ if (in_dbent->tl_data) {
+ krb5_tl_data *xxx, *xxx1;
+
+ for (xxx=in_dbent->tl_data; xxx; ) {
+ xxx1 = xxx;
+ xxx = xxx->tl_data_next;
+ free(xxx1);
+ }
+ }
+ free(in_dbent);
+ if (out_dbent->tl_data) {
+ krb5_tl_data *xxx, *xxx1;
+
+ for (xxx=out_dbent->tl_data; xxx; ) {
+ xxx1 = xxx;
+ xxx = xxx->tl_data_next;
+ free(xxx1);
+ }
+ }
+ free(out_dbent);
+ }
+ else {
+ fprintf(stderr, "%s: no memory\n", pname);
+ kret = ENOMEM;
+ }
+
+ krb5_free_context(kcontext);
+ if (verbose) {
+ printf("* End %s ", title);
+ if (isrand)
+ printf(" pass %d ", passno);
+ printf("%s", (kret) ? "FAILURE" : "SUCCESS");
+ if (kret)
+ printf("%d - %s", kret, error_message(kret));
+ printf("\n");
+ }
+ return((kret) ? 1 : 0);
+}
+
+/*
+ * usage is: t_dbentry [-r <nnn>] [-v]
+ */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_boolean verbose;
+ krb5_int32 randompasses;
+ krb5_int32 error;
+ int option;
+ extern char *optarg;
+ char *programname;
+ int i;
+ time_t now;
+
+ randompasses = 0;
+ verbose = 0;
+ error = 0;
+ programname = argv[0];
+
+ now = time((time_t *) NULL);
+ SRAND((RAND_TYPE) now);
+ while ((option = getopt(argc, argv, "r:v")) != EOF) {
+ switch (option) {
+ case 'r':
+ if (sscanf(optarg, "%d", &randompasses) != 1) {
+ fprintf(stderr, "%s: %s is not a number\n", argv[0], optarg);
+ error++;
+ }
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ fprintf(stderr, "%s: usage is %s [-r number] [-v]\n",
+ argv[0], argv[0]);
+ error++;
+ break;
+ }
+ }
+ if (error)
+ return(error);
+
+ error += do_test(programname, verbose, 0, 1, "Standard set test", 0);
+ error += do_test(programname, verbose, 0, 0, "Standard get test", 0);
+ for (i=0; i<randompasses; i++)
+ error += do_test(programname, verbose, 1, 0, "Random test", i+1);
+ if (verbose) {
+ if (error)
+ printf("%s: %d errors in %d tests (%5.2f%%)\n", argv[0], error,
+ randompasses+2,
+ (float) (error*100) / (float) (randompasses+2));
+ }
+ return(error);
+}
+