Add new string conversion routines
authorPaul Park <pjpark@mit.edu>
Mon, 31 Jul 1995 20:00:32 +0000 (20:00 +0000)
committerPaul Park <pjpark@mit.edu>
Mon, 31 Jul 1995 20:00:32 +0000 (20:00 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6360 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kadm/Makefile.in
src/lib/kadm/configure.in
src/lib/kadm/str_conv.c [new file with mode: 0644]

index 626f3e189d57b2e59f068e27b564070ab571f87b..c3bac9144e544faec076da9db0df5dc74bcebba9 100644 (file)
@@ -8,7 +8,8 @@ BASE_OBJS= adm_conn.$(OBJEXT)   \
        adm_kt_dec.$(OBJEXT)    \
        adm_kt_enc.$(OBJEXT)    \
        adm_rw.$(OBJEXT)        \
-       alt_prof.$(OBJEXT)
+       alt_prof.$(OBJEXT)      \
+       str_conv.$(OBJEXT)
 
 UNIX_OBJS = logger.$(OBJEXT)
 
@@ -24,7 +25,8 @@ SRCS= $(srcdir)/adm_conn.c    \
        $(srcdir)/adm_kw_dec.c  \
        $(srcdir)/adm_kw_enc.c  \
        $(srcdir)/logger.c      \
-       $(srcdir)/alt_prof.c
+       $(srcdir)/alt_prof.c    \
+       $(srcdir)/str_conv.c
 
 all:: all-$(WHAT) $(BASE_OBJS) 
 
@@ -54,8 +56,9 @@ clean-windows::
 # t_dbentry
 #
 T_DBENTRY_OBJS =  t_dbentry.$(OBJEXT) \
-               $(TOPLIBD)/libkadm.a $(TOPLIBD)/libkrb5.a       \
-               $(TOPLIBD)/libcrypto.a $(TOPLIBD)/libcom_err.a
+               $(TOPLIBD)/libkadm.a $(TOPLIBD)/libkdb5.a \
+               $(TOPLIBD)/libkrb5.a $(TOPLIBD)/libcrypto.a \
+               $(TOPLIBD)/libcom_err.a
 
 t_dbentry:     $(T_DBENTRY_OBJS)
        $(LD) -o t_dbentry $(T_DBENTRY_OBJS) $(LIBS)
index b5e674b7a6bf8272afcbcb881604b184badcc1a1..d89fb3e9d1a3803562dcbefec731adc1dfbc84c7 100644 (file)
@@ -5,7 +5,7 @@ AC_PROG_ARCHIVE_ADD
 AC_PROG_RANLIB
 AC_PROG_INSTALL
 AC_HAVE_HEADERS(pwd.h stdarg.h syslog.h)
-AC_HAVE_FUNCS(srand48 srand srandom syslog openlog closelog strftime)
+AC_HAVE_FUNCS(srand48 srand srandom syslog openlog closelog strftime strptime)
 AC_FUNC_CHECK(vsprintf,AC_DEFINE(HAVE_VSPRINTF))
 ET_RULES
 LinkFileDir(../libkadm.a, libkadm.a, ./kadm)
diff --git a/src/lib/kadm/str_conv.c b/src/lib/kadm/str_conv.c
new file mode 100644 (file)
index 0000000..b925f78
--- /dev/null
@@ -0,0 +1,824 @@
+/*
+ * lib/kadm/str_conv.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.
+ *
+ */
+
+/*
+ * str_conv.c - Convert between strings and Kerberos internal data.
+ */
+
+/*
+ * Table of contents:
+ *
+ * String decoding:
+ * ----------------
+ * krb5_string_to_keytype()    - Convert string to krb5_keytype.
+ * krb5_string_to_salttype()   - Convert string to salttype (krb5_int32)
+ * krb5_string_to_enctype()    - Convert string to krb5_enctype.
+ * krb5_string_to_cksumtype()  - Convert string to krb5_cksumtype;
+ * krb5_string_to_flags()      - Convert string to krb5_flags.
+ * krb5_string_to_timestamp()  - Convert string to krb5_timestamp.
+ * krb5_string_to_deltat()     - Convert string to krb5_deltat.
+ *
+ * String encoding:
+ * ----------------
+ * krb5_keytype_to_string()    - Convert krb5_keytype to string.
+ * krb5_salttype_to_string()   - Convert salttype (krb5_int32) to string.
+ * krb5_enctype_to_string()    - Convert krb5_enctype to string.
+ * krb5_cksumtype_to_string()  - Convert krb5_cksumtype to string.
+ * krb5_flags_to_string()      - Convert krb5_flags to string.
+ * krb5_timestamp_to_string()  - Convert krb5_timestamp to string.
+ * krb5_deltat_to_string()     - Convert krb5_deltat to string.
+ */
+
+#include "k5-int.h"
+#include "adm.h"
+#include "adm_proto.h"
+
+/*
+ * Local data structures.
+ */
+struct keytype_lookup_entry {
+    krb5_keytype       ktt_keytype;            /* Keytype              */
+    const char *       ktt_specifier;          /* How to recognize it  */
+    const char *       ktt_output;             /* How to spit it out   */
+};
+
+struct salttype_lookup_entry {
+    krb5_int32         stt_keytype;            /* Salt type            */
+    const char *       stt_specifier;          /* How to recognize it  */
+    const char *       stt_output;             /* How to spit it out   */
+};
+
+struct enctype_lookup_entry {
+    krb5_enctype       ett_enctype;            /* Encryption type      */
+    const char *       ett_specifier;          /* How to recognize it  */
+    const char *       ett_output;             /* How to spit it out   */
+};
+
+struct cksumtype_lookup_entry {
+    krb5_cksumtype     cst_cksumtype;          /* Checksum type        */
+    const char *       cst_specifier;          /* How to recognize it  */
+    const char *       cst_output;             /* How to spit it out   */
+};
+
+struct flags_lookup_entry {
+    krb5_flags         fl_flags;               /* Flag                 */
+    krb5_boolean       fl_sense;               /* Sense of the flag    */
+    const char *       fl_specifier;           /* How to recognize it  */
+    const char *       fl_output;              /* How to spit it out   */
+};
+
+struct deltat_match_entry {
+    const char *       dt_scan_format;         /* sscanf format        */
+    int                        dt_nmatch;              /* Number to match      */
+    int                        dt_dindex;              /* Day index            */
+    int                        dt_hindex;              /* Hour index           */
+    int                        dt_mindex;              /* Minute index         */
+    int                        dt_sindex;              /* Second index         */
+};
+
+/*
+ * Local strings
+ */
+/* Keytype strings */
+static const char keytype_null_in[]    = "null";
+static const char keytype_des_in[]     = "des";
+static const char keytype_null_out[]   = "Null";
+static const char keytype_des_out[]    = "DES";
+
+/* Salttype strings */
+static const char stype_v5_in[]                = "normal";
+static const char stype_v4_in[]                = "v4";
+static const char stype_norealm_in[]   = "norealm";
+static const char stype_olrealm_in[]   = "onlyrealm";
+static const char stype_special_in[]   = "special";
+static const char stype_v5_out[]       = "Version 5";
+static const char stype_v4_out[]       = "Version 4";
+static const char stype_norealm_out[]  = "Version 5 - No Realm";
+static const char stype_olrealm_out[]  = "Version 5 - Realm Only";
+static const char stype_special_out[]  = "Special";
+
+/* Encryption type strings */
+static const char etype_null_in[]      = "null";
+static const char etype_descbccrc_in[] = "des-cbc-crc";
+static const char etype_descbcmd4_in[] = "des-cbc-md4";
+static const char etype_descbcmd5_in[] = "des-cbc-md5";
+static const char etype_rawdescbc_in[] = "raw-des-cbc";
+static const char etype_null_out[]     = "Null";
+static const char etype_descbccrc_out[]        = "DES cbc mode with CRC-32";
+static const char etype_descbcmd4_out[]        = "DES cbc mode with RSA-MD4";
+static const char etype_descbcmd5_out[]        = "DES cbc mode with RSA-MD5";
+static const char etype_rawdescbc_out[]        = "DES cbc mode";
+
+/* Checksum type strings */
+static const char cstype_crc32_in[]    = "crc32";
+static const char cstype_md4_in[]      = "md4";
+static const char cstype_md4des_in[]   = "md4-des";
+static const char cstype_descbc_in[]   = "des-cbc";
+static const char cstype_md5_in[]      = "md5";
+static const char cstype_md5des_in[]   = "md5-des";
+static const char cstype_crc32_out[]   = "CRC-32";
+static const char cstype_md4_out[]     = "RSA-MD4";
+static const char cstype_md4des_out[]  = "RSA-MD4 with DES cbc mode";
+static const char cstype_descbc_out[]  = "DES cbc mode";
+static const char cstype_md5_out[]     = "RSA-MD5";
+static const char cstype_md5des_out[]  = "RSA-MD5 with DES cbc mode";
+
+/* Flags strings */
+static const char flags_pdate_in[]     = "postdateable";
+static const char flags_fwd_in[]       = "forwardable";
+static const char flags_tgtbased_in[]  = "tgt-based";
+static const char flags_renew_in[]     = "renewable";
+static const char flags_proxy_in[]     = "proxiable";
+static const char flags_dup_skey_in[]  = "dup-skey";
+static const char flags_tickets_in[]   = "allow-tickets";
+static const char flags_preauth_in[]   = "preauth";
+static const char flags_hwauth_in[]    = "hwauth";
+static const char flags_pwchange_in[]  = "pwchange";
+static const char flags_service_in[]   = "service";
+static const char flags_pwsvc_in[]     = "pwservice";
+static const char flags_md5_in[]       = "md5";
+static const char flags_pdate_out[]    = "Not Postdateable";
+static const char flags_fwd_out[]      = "Not Forwardable";
+static const char flags_tgtbased_out[] = "No TGT-based requests";
+static const char flags_renew_out[]    = "Not renewable";
+static const char flags_proxy_out[]    = "Not proxiable";
+static const char flags_dup_skey_out[] = "No DUP_SKEY requests";
+static const char flags_tickets_out[]  = "All Tickets Disallowed";
+static const char flags_preauth_out[]  = "Preauthorization required";
+static const char flags_hwauth_out[]   = "HW Authorization required";
+static const char flags_pwchange_out[] = "Password Change required";
+static const char flags_service_out[]  = "Service Disabled";
+static const char flags_pwsvc_out[]    = "Password Changing Service";
+static const char flags_md5_out[]      = "RSA-MD5 supported";
+static const char flags_default_neg[]  = "-";
+static const char flags_default_sep[]  = " ";
+
+/* Absolute time strings */
+static const char atime_full_digits[]  = "%y%m%d%H%M%S";
+static const char atime_full_digits_d[]        = "%y.%m.%d.%H.%M.%S";
+static const char atime_nsec_digits[]  = "%y%m%d%H%M";
+static const char atime_rel_hms[]      = "%H%M%S";
+static const char atime_rel_hm[]       = "%H%M";
+static const char atime_rel_col_hms[]  = "%T";
+static const char atime_rel_col_hm[]   = "%R";
+static const char atime_ldep_sfmt[]    = "%x:%X";
+static const char atime_full_text[]    = "%d-%b-%Y:%T";
+static const char atime_full_text_nos[]        = "%d-%b-%Y:%R";
+#if    !HAVE_STRPTIME
+static const char ascan_full_digits[]  = "%02d%02d%02d%02d%02d%02d";
+static const char ascan_full_digits_d[]        = "%02d.%02d.%02d.%02d.%02d.%02d";
+static const char ascan_nsec_digits[]  = "%02d%02d%02d%02d%02d";
+static const char ascan_rel_hms[]      = "%02d%02d%02d";
+static const char ascan_rel_hm[]       = "%02d%02d";
+static const char ascan_rel_col_hms[]  = "%02d:%02d:%02d";
+static const char ascan_rel_col_hm[]   = "%02d:%02d";
+#endif /* !HAVE_STRPTIME */
+
+/* Delta time strings */
+static const char dtscan_dhms_notext[] = "%d-%02d:%02d:%02d";
+static const char dtscan_dhms_stext[]  = "%dd%dh%dm%ds";
+static const char dtscan_hms_notext[]  = "%d:%02d:%02d";
+static const char dtscan_hms_stext[]   = "%dh%dm%ds";
+static const char dtscan_hm_notext[]   = "%d:%02d";
+static const char dtscan_hm_stext[]    = "%dh%dm";
+static const char dtscan_days[]                = "%d%[d]";
+static const char dtscan_hours[]       = "%d%[h]";
+static const char dtscan_minutes[]     = "%d%[m]";
+static const char dtscan_seconds[]     = "%d%[s]";
+static const char dt_day_singular[]    = "day";
+static const char dt_day_plural[]      = "days";
+static const char dt_output_donly[]    = "%d %s";
+static const char dt_output_dhms[]     = "%d %s %02d:%02d:%02d";
+static const char dt_output_hms[]      = "%d:%02d:%02d";
+
+/*
+ * Lookup tables.
+ */
+static const struct keytype_lookup_entry keytype_table[] = {
+/* krb5_keytype        input specifier         output string           */
+/*-------------        ----------------------- ------------------------*/
+{ KEYTYPE_NULL,        keytype_null_in,        keytype_null_out        },
+{ KEYTYPE_DES, keytype_des_in,         keytype_des_out         }
+};
+static const int keytype_table_nents = sizeof(keytype_table)/
+                                      sizeof(keytype_table[0]);
+
+static const struct salttype_lookup_entry salttype_table[] = {
+/* salt type                   input specifier         output string     */
+/*-----------------------------        ----------------------- ------------------*/
+{ KRB5_KDB_SALTTYPE_NORMAL,    stype_v5_in,            stype_v5_out      },
+{ KRB5_KDB_SALTTYPE_V4,                stype_v4_in,            stype_v4_out      },
+{ KRB5_KDB_SALTTYPE_NOREALM,   stype_norealm_in,       stype_norealm_out },
+{ KRB5_KDB_SALTTYPE_ONLYREALM, stype_olrealm_in,       stype_olrealm_out },
+{ KRB5_KDB_SALTTYPE_SPECIAL,   stype_special_in,       stype_special_out }
+};
+static const int salttype_table_nents = sizeof(salttype_table)/
+                                       sizeof(salttype_table[0]);
+
+static const struct enctype_lookup_entry enctype_table[] = {
+/* krb5_enctype             input specifier            output string           */
+/*------------------ ---------------------     ------------------------*/
+{ ETYPE_NULL,       etype_null_in,             etype_null_out          },
+{ ETYPE_DES_CBC_CRC, etype_descbccrc_in,       etype_descbccrc_out     },
+{ ETYPE_DES_CBC_MD4, etype_descbcmd4_in,       etype_descbcmd4_out     },
+{ ETYPE_DES_CBC_MD5, etype_descbcmd5_in,       etype_descbcmd5_out     },
+{ ETYPE_RAW_DES_CBC, etype_rawdescbc_in,       etype_rawdescbc_out     }
+};
+static const int enctype_table_nents = sizeof(enctype_table)/
+                                      sizeof(enctype_table[0]);
+
+static const struct cksumtype_lookup_entry cksumtype_table[] = {
+/* krb5_cksumtype         input specifier      output string           */
+/*----------------------- ---------------------        ------------------------*/
+{ CKSUMTYPE_CRC32,        cstype_crc32_in,     cstype_crc32_out        },
+{ CKSUMTYPE_RSA_MD4,      cstype_md4_in,       cstype_md4_out          },
+{ CKSUMTYPE_RSA_MD4_DES,  cstype_md4des_in,    cstype_md4des_out       },
+{ CKSUMTYPE_DESCBC,       cstype_descbc_in,    cstype_descbc_out       },
+{ CKSUMTYPE_RSA_MD5,      cstype_md5_in,       cstype_md5_out          },
+{ CKSUMTYPE_RSA_MD5_DES,  cstype_md5des_in,    cstype_md5des_out       }
+};
+static const int cksumtype_table_nents = sizeof(cksumtype_table)/
+                                        sizeof(cksumtype_table[0]);
+
+static const struct flags_lookup_entry flags_table[] = {
+/* flag                                sense   input specifier    output string     */
+/*----------------------------- -------        ------------------ ------------------*/
+{ KRB5_KDB_DISALLOW_POSTDATED, 0,      flags_pdate_in,    flags_pdate_out   },
+{ KRB5_KDB_DISALLOW_FORWARDABLE,0,     flags_fwd_in,      flags_fwd_out     },
+{ KRB5_KDB_DISALLOW_TGT_BASED, 0,      flags_tgtbased_in, flags_tgtbased_out},
+{ KRB5_KDB_DISALLOW_RENEWABLE, 0,      flags_renew_in,    flags_renew_out   },
+{ KRB5_KDB_DISALLOW_PROXIABLE, 0,      flags_proxy_in,    flags_proxy_out   },
+{ KRB5_KDB_DISALLOW_DUP_SKEY,  0,      flags_dup_skey_in, flags_dup_skey_out},
+{ KRB5_KDB_DISALLOW_ALL_TIX,   0,      flags_tickets_in,  flags_tickets_out },
+{ KRB5_KDB_REQUIRES_PRE_AUTH,  1,      flags_preauth_in,  flags_preauth_out },
+{ KRB5_KDB_REQUIRES_HW_AUTH,   1,      flags_hwauth_in,   flags_hwauth_out  },
+{ KRB5_KDB_REQUIRES_PWCHANGE,  1,      flags_pwchange_in, flags_pwchange_out},
+{ KRB5_KDB_DISALLOW_SVR,       0,      flags_service_in,  flags_service_out },
+{ KRB5_KDB_PWCHANGE_SERVICE,   1,      flags_pwsvc_in,    flags_pwsvc_out   },
+{ KRB5_KDB_SUPPORT_DESMD5,     1,      flags_md5_in,      flags_md5_out     }
+};
+static const int flags_table_nents = sizeof(flags_table)/
+                                    sizeof(flags_table[0]);
+
+static const char * const atime_format_table[] = {
+atime_full_digits,     /* yymmddhhmmss                 */
+atime_full_digits_d,   /* yy.mm.dd.hh.mm.ss            */
+atime_nsec_digits,     /* yymmddhhmm                   */
+atime_rel_hms,         /* hhmmss                       */
+atime_rel_hm,          /* hhmm                         */
+atime_rel_col_hms,     /* hh:mm:ss                     */
+atime_rel_col_hm,      /* hh:mm                        */
+/* The following not really supported unless native strptime present */
+atime_ldep_sfmt,       /*locale-dependent short format */
+atime_full_text,       /* dd-month-yyyy:hh:mm:ss       */
+atime_full_text_nos    /* dd-month-yyyy:hh:mm          */
+};
+static const int atime_format_table_nents = sizeof(atime_format_table)/
+                                           sizeof(atime_format_table[0]);
+
+static const struct deltat_match_entry deltat_table[] = {
+/* scan format         nmatch  daypos  hourpos minpos  secpos  */
+/*---------------------        ------- ------- ------- ------- --------*/
+{ dtscan_dhms_notext,  4,      0,      1,      2,      3       },
+{ dtscan_dhms_stext,   4,      0,      1,      2,      3       },
+{ dtscan_hms_notext,   3,      -1,     0,      1,      2       },
+{ dtscan_hms_stext,    3,      -1,     0,      1,      2       },
+{ dtscan_hm_notext,    2,      -1,     -1,     0,      1       },
+{ dtscan_hm_stext,     2,      -1,     -1,     0,      1       },
+{ dtscan_days,         2,      0,      -1,     -1,     -1      },
+{ dtscan_hours,                2,      -1,     0,      -1,     -1      },
+{ dtscan_minutes,      2,      -1,     -1,     0,      -1      },
+{ dtscan_seconds,      2,      -1,     -1,     -1,     0       }
+};
+static const int deltat_table_nents = sizeof(deltat_table)/
+                                     sizeof(deltat_table[0]);
+\f
+#if    !HAVE_STRPTIME
+/*
+ * Rudimentary version of strptime for systems which don't have it.
+ */
+static char *
+strptime(buf, format, tm)
+    char *buf;
+    const char *format;
+    struct tm *tm;
+{
+    int year, month, day, hour, minute, second;
+    char *bp;
+    time_t now;
+    
+    /*
+     * We only understand the following fixed formats:
+     *    %y%m%d%H%M%S
+     *    %y.%m.%d.%H.%M.%S
+     *    %y%m%d%H%M
+     *    %H%M%S
+     *    %H%M
+     *    %T
+     *    %R
+     */
+    bp = (char *) NULL;
+    if (!strcmp(format, atime_full_digits) &&
+       (sscanf(buf, ascan_full_digits,
+               &year, &month, &day, &hour, &minute, &second) == 6)) {
+       tm->tm_year = year;
+       tm->tm_mon = month - 1;
+       tm->tm_mday = day;
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       tm->tm_sec = second;
+       bp = &buf[strlen(atime_full_digits)];
+    }
+    else if (!strcmp(format,atime_full_digits_d) &&
+            (sscanf(buf, ascan_full_digits_d,
+                    &year, &month, &day, &hour, &minute, &second) == 6)) {
+       tm->tm_year = year;
+       tm->tm_mon = month - 1;
+       tm->tm_mday = day;
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       tm->tm_sec = second;
+       bp = &buf[strlen(atime_full_digits_d)];
+    }
+    else if (!strcmp(format, atime_nsec_digits) &&
+            (sscanf(buf, ascan_nsec_digits,
+               &year, &month, &day, &hour, &minute) == 5)) {
+       tm->tm_year = year;
+       tm->tm_mon = month - 1;
+       tm->tm_mday = day;
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       tm->tm_sec = 0;
+       bp = &buf[strlen(atime_nsec_digits)];
+    }
+    else if (!strcmp(format, atime_rel_hms) &&
+            (sscanf(buf, ascan_rel_hms, &hour, &minute, &second) == 3)) {
+       now = time((time_t *) NULL);
+       memcpy(tm, localtime(&now), sizeof(struct tm));
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       tm->tm_sec = second;
+       bp = &buf[strlen(atime_rel_hms)];
+    }
+    else if (!strcmp(format, atime_rel_hm) &&
+            (sscanf(buf, ascan_rel_hm, &hour, &minute) == 2)) {
+       now = time((time_t *) NULL);
+       memcpy(tm, localtime(&now), sizeof(struct tm));
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       bp = &buf[strlen(atime_rel_hm)];
+    }
+    else if (!strcmp(format, atime_rel_col_hms) &&
+            (sscanf(buf, ascan_rel_col_hms, &hour, &minute, &second) == 3)) {
+       now = time((time_t *) NULL);
+       memcpy(tm, localtime(&now), sizeof(struct tm));
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       tm->tm_sec = second;
+       bp = &buf[strlen(atime_rel_col_hms)];
+    }
+    else if (!strcmp(format, atime_rel_col_hm) &&
+            (sscanf(buf, ascan_rel_col_hm, &hour, &minute) == 2)) {
+       now = time((time_t *) NULL);
+       memcpy(tm, localtime(&now), sizeof(struct tm));
+       tm->tm_hour = hour;
+       tm->tm_min = minute;
+       bp = &buf[strlen(atime_rel_col_hm)];
+    }
+    return(bp);
+}
+#endif /* HAVE_STRPTIME */
+\f
+/*
+ * String to internal datatype routines.
+ *
+ * These routines return 0 for success, EINVAL for invalid entry.
+ */
+krb5_error_code
+krb5_string_to_keytype(string, keytypep)
+    char               * string;
+    krb5_keytype       * keytypep;
+{
+    int i;
+    int found;
+
+    found = 0;
+    for (i=0; i<keytype_table_nents; i++) {
+       if (!strcasecmp(string, keytype_table[i].ktt_specifier)) {
+           found = 1;
+           *keytypep = keytype_table[i].ktt_keytype;
+           break;
+       }
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_salttype(string, salttypep)
+    char       * string;
+    krb5_int32 * salttypep;
+{
+    int i;
+    int found;
+
+    found = 0;
+    for (i=0; i<salttype_table_nents; i++) {
+       if (!strcasecmp(string, salttype_table[i].stt_specifier)) {
+           found = 1;
+           *salttypep = salttype_table[i].stt_keytype;
+           break;
+       }
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_enctype(string, enctypep)
+    char               * string;
+    krb5_enctype       * enctypep;
+{
+    int i;
+    int found;
+
+    found = 0;
+    for (i=0; i<enctype_table_nents; i++) {
+       if (!strcasecmp(string, enctype_table[i].ett_specifier)) {
+           found = 1;
+           *enctypep = enctype_table[i].ett_enctype;
+           break;
+       }
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_cksumtype(string, cksumtypep)
+    char               * string;
+    krb5_cksumtype     * cksumtypep;
+{
+    int i;
+    int found;
+
+    found = 0;
+    for (i=0; i<cksumtype_table_nents; i++) {
+       if (!strcasecmp(string, cksumtype_table[i].cst_specifier)) {
+           found = 1;
+           *cksumtypep = cksumtype_table[i].cst_cksumtype;
+           break;
+       }
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_flags(string, positive, negative, flagsp)
+    char       * string;
+    const char * positive;
+    const char * negative;
+    krb5_flags * flagsp;
+{
+    int        i;
+    int        found;
+    const char *neg;
+    size_t     nsize, psize;
+    int                cpos;
+    int                sense;
+
+    found = 0;
+    /* We need to have a way to negate it. */
+    neg = (negative) ? negative : flags_default_neg;
+    nsize = strlen(neg);
+    psize = (positive) ? strlen(positive) : 0;
+
+    cpos = 0;
+    sense = 1;
+    /* First check for positive or negative sense */
+    if (!strncasecmp(neg, string, nsize)) {
+       sense = 0;
+       cpos += (int) nsize;
+    }
+    else if (psize && !strncasecmp(positive, string, psize)) {
+       cpos += (int) psize;
+    }
+
+    for (i=0; i<flags_table_nents; i++) {
+       if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) {
+           found = 1;
+           if (sense == flags_table[i].fl_sense)
+               *flagsp |= flags_table[i].fl_flags;
+           else
+               *flagsp &= ~flags_table[i].fl_flags;
+
+           break;
+       }
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_timestamp(string, timestampp)
+    char               * string;
+    krb5_timestamp     * timestampp;
+{
+    int i;
+    int found;
+    struct tm timebuf;
+
+    found = 0;
+    for (i=0; i<atime_format_table_nents; i++) {
+       if (strptime(string, atime_format_table[i], &timebuf)) {
+           found = 1;
+           break;
+       }
+    }
+    if (found)
+       *timestampp = (krb5_timestamp) mktime(&timebuf);
+    return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_string_to_deltat(string, deltatp)
+    char       * string;
+    krb5_deltat        * deltatp;
+{
+    int i;
+    int found;
+    int svalues[4];
+    int days, hours, minutes, seconds;
+    krb5_deltat        dt;
+
+    found = 0;
+    days = hours = minutes = seconds = 0;
+    for (i=0; i<deltat_table_nents; i++) {
+       if (sscanf(string, deltat_table[i].dt_scan_format,
+                  &svalues[0], &svalues[1], &svalues[2], &svalues[3]) ==
+           deltat_table[i].dt_nmatch) {
+           if (deltat_table[i].dt_dindex >= 0)
+               days = svalues[deltat_table[i].dt_dindex];
+           if (deltat_table[i].dt_hindex >= 0)
+               hours = svalues[deltat_table[i].dt_hindex];
+           if (deltat_table[i].dt_mindex >= 0)
+               minutes = svalues[deltat_table[i].dt_mindex];
+           if (deltat_table[i].dt_sindex >= 0)
+               seconds = svalues[deltat_table[i].dt_sindex];
+           found = 1;
+           break;
+       }
+    }
+    if (found) {
+       dt = days;
+       dt *= 24;
+       dt += hours;
+       dt *= 60;
+       dt += minutes;
+       dt *= 60;
+       dt += seconds;
+       *deltatp = dt;
+    }
+    return((found) ? 0 : EINVAL);
+}
+
+/*
+ * Internal datatype to string routines.
+ *
+ * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
+ * if the supplied buffer/length will not contain the output.
+ */
+krb5_error_code
+krb5_keytype_to_string(keytype, buffer, buflen)
+    krb5_keytype       keytype;
+    char               * buffer;
+    size_t             buflen;
+{
+    int i;
+    const char *out;
+
+    out = (char *) NULL;
+    for (i=0; i<keytype_table_nents; i++) {
+       if (keytype ==  keytype_table[i].ktt_keytype) {
+           out = keytype_table[i].ktt_output;
+           break;
+       }
+    }
+    if (out) {
+       if (buflen > strlen(out))
+           strcpy(buffer, out);
+       else
+           out = (char *) NULL;
+       return((out) ? 0 : ENOMEM);
+    }
+    else
+       return(EINVAL);
+}
+
+krb5_error_code
+krb5_salttype_to_string(salttype, buffer, buflen)
+    krb5_int32 salttype;
+    char       * buffer;
+    size_t     buflen;
+{
+    int i;
+    const char *out;
+
+    out = (char *) NULL;
+    for (i=0; i<salttype_table_nents; i++) {
+       if (salttype ==  salttype_table[i].stt_keytype) {
+           out = salttype_table[i].stt_output;
+           break;
+       }
+    }
+    if (out) {
+       if (buflen > strlen(out))
+           strcpy(buffer, out);
+       else
+           out = (char *) NULL;
+       return((out) ? 0 : ENOMEM);
+    }
+    else
+       return(EINVAL);
+}
+
+krb5_error_code
+krb5_enctype_to_string(enctype, buffer, buflen)
+    krb5_enctype       enctype;
+    char               * buffer;
+    size_t             buflen;
+{
+    int i;
+    const char *out;
+
+    out = (char *) NULL;
+    for (i=0; i<enctype_table_nents; i++) {
+       if (enctype ==  enctype_table[i].ett_enctype) {
+           out = enctype_table[i].ett_output;
+           break;
+       }
+    }
+    if (out) {
+       if (buflen > strlen(out))
+           strcpy(buffer, out);
+       else
+           out = (char *) NULL;
+       return((out) ? 0 : ENOMEM);
+    }
+    else
+       return(EINVAL);
+}
+
+krb5_error_code
+krb5_cksumtype_to_string(cksumtype, buffer, buflen)
+    krb5_cksumtype     cksumtype;
+    char               * buffer;
+    size_t             buflen;
+{
+    int i;
+    const char *out;
+
+    out = (char *) NULL;
+    for (i=0; i<cksumtype_table_nents; i++) {
+       if (cksumtype ==  cksumtype_table[i].cst_cksumtype) {
+           out = cksumtype_table[i].cst_output;
+           break;
+       }
+    }
+    if (out) {
+       if (buflen > strlen(out))
+           strcpy(buffer, out);
+       else
+           out = (char *) NULL;
+       return((out) ? 0 : ENOMEM);
+    }
+    else
+       return(EINVAL);
+}
+
+krb5_error_code
+krb5_flags_to_string(flags, sep, buffer, buflen)
+    krb5_flags flags;
+    const char * sep;
+    char       * buffer;
+    size_t     buflen;
+{
+    int                        i;
+    krb5_flags         pflags;
+    const char         *sepstring;
+    char               *op;
+    int                        initial;
+    krb5_error_code    retval;
+
+    retval = 0;
+    op = buffer;
+    pflags = 0;
+    initial = 1;
+    sepstring = (sep) ? sep : flags_default_sep;
+    /* Blast through the table matching all we can */
+    for (i=0; i<flags_table_nents; i++) {
+       if (flags & flags_table[i].fl_flags) {
+           /* Found a match, see if it'll fit into the output buffer */
+           if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) <
+               (buffer + buflen)) {
+               if (!initial) {
+                   strcpy(op, sep);
+                   op += strlen(sep);
+               }
+               initial = 0;
+               strcpy(op, flags_table[i].fl_output);
+               op += strlen(flags_table[i].fl_output);
+           }
+           else {
+               retval = ENOMEM;
+               break;
+           }
+           /* Keep track of what we matched */
+           pflags |= flags_table[i].fl_flags;
+       }
+    }
+    if (!retval) {
+       /* See if there's any leftovers */
+       if (flags & ~pflags)
+           retval = EINVAL;
+       else if (initial)
+           *buffer = '\0';
+    }
+    return(retval);
+}
+
+krb5_error_code
+krb5_timestamp_to_string(timestamp, buffer, buflen)
+    krb5_timestamp     timestamp;
+    char               * buffer;
+    size_t             buflen;
+{
+    if (strlen(ctime((time_t *) &timestamp)) <= buflen) {
+       strcpy(buffer, ctime((time_t *) &timestamp));
+       /* ctime returns <datestring>\n\0 */
+       buffer[strlen(buffer)-1] = '\0';
+       return(0);
+    }
+    return(ENOMEM);
+}
+
+krb5_error_code
+krb5_deltat_to_string(deltat, buffer, buflen)
+    krb5_deltat        deltat;
+    char       * buffer;
+    size_t     buflen;
+{
+    int                        days, hours, minutes, seconds;
+    krb5_deltat                dt;
+    krb5_error_code    retval;
+
+    days = deltat / (24*3600);
+    dt = deltat % (24*3600);
+    hours = dt / 3600;
+    dt %= 3600;
+    minutes = dt / 60;
+    seconds = dt % 60;
+
+    retval = 0;
+    if (days) {
+       if (hours || minutes || seconds) {
+           if (buflen < (strlen(dt_output_dhms)+strlen(dt_day_plural)))
+               retval = ENOMEM;
+           else
+               sprintf(buffer, dt_output_dhms, days,
+                       (days > 1) ? dt_day_plural : dt_day_singular,
+                       hours, minutes, seconds);
+       }
+       else {
+           if (buflen < (strlen(dt_output_donly)+strlen(dt_day_plural)))
+               retval = ENOMEM;
+           else
+               sprintf(buffer, dt_output_donly, days,
+                       (days > 1) ? dt_day_plural : dt_day_singular);
+       }
+    }
+    else {
+       if (buflen < strlen(dt_output_hms))
+           retval = ENOMEM;
+       else
+           sprintf(buffer, dt_output_hms, hours, minutes, seconds);
+    }
+    return(retval);
+}