17c478bdstevel@tonic-gate/*
2159d09aMark Phalan * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bdstevel@tonic-gate * Use is subject to license terms.
47c478bdstevel@tonic-gate */
57c478bdstevel@tonic-gate
67c478bdstevel@tonic-gate
77c478bdstevel@tonic-gate/*
87c478bdstevel@tonic-gate * lib/kadm/str_conv.c
97c478bdstevel@tonic-gate *
107c478bdstevel@tonic-gate * Copyright 1995, 1999 by the Massachusetts Institute of Technology.
117c478bdstevel@tonic-gate * All Rights Reserved.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * Export of this software from the United States of America may
147c478bdstevel@tonic-gate *   require a specific license from the United States Government.
157c478bdstevel@tonic-gate *   It is the responsibility of any person or organization contemplating
167c478bdstevel@tonic-gate *   export to obtain such a license before exporting.
177c478bdstevel@tonic-gate *
187c478bdstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bdstevel@tonic-gate * distribute this software and its documentation for any purpose and
207c478bdstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
217c478bdstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
227c478bdstevel@tonic-gate * this permission notice appear in supporting documentation, and that
237c478bdstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bdstevel@tonic-gate * to distribution of the software without specific, written prior
257c478bdstevel@tonic-gate * permission.  Furthermore if you modify this software you must label
267c478bdstevel@tonic-gate * your software as modified software and not distribute it in such a
277c478bdstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
287c478bdstevel@tonic-gate * M.I.T. makes no representations about the suitability of
297c478bdstevel@tonic-gate * this software for any purpose.  It is provided "as is" without express
307c478bdstevel@tonic-gate * or implied warranty.
317c478bdstevel@tonic-gate *
327c478bdstevel@tonic-gate */
337c478bdstevel@tonic-gate
347c478bdstevel@tonic-gate/*
357c478bdstevel@tonic-gate * str_conv.c - Convert between strings and Kerberos internal data.
367c478bdstevel@tonic-gate */
377c478bdstevel@tonic-gate
387c478bdstevel@tonic-gate/*
397c478bdstevel@tonic-gate * Table of contents:
407c478bdstevel@tonic-gate *
417c478bdstevel@tonic-gate * String decoding:
427c478bdstevel@tonic-gate * ----------------
437c478bdstevel@tonic-gate * krb5_string_to_salttype()	- Convert string to salttype (krb5_int32)
447c478bdstevel@tonic-gate * krb5_string_to_timestamp()	- Convert string to krb5_timestamp.
457c478bdstevel@tonic-gate * krb5_string_to_deltat()	- Convert string to krb5_deltat.
467c478bdstevel@tonic-gate *
477c478bdstevel@tonic-gate * String encoding:
487c478bdstevel@tonic-gate * ----------------
497c478bdstevel@tonic-gate * krb5_salttype_to_string()	- Convert salttype (krb5_int32) to string.
507c478bdstevel@tonic-gate * krb5_timestamp_to_string()	- Convert krb5_timestamp to string.
517c478bdstevel@tonic-gate * krb5_timestamp_to_sfstring()	- Convert krb5_timestamp to short filled string
527c478bdstevel@tonic-gate * krb5_deltat_to_string()	- Convert krb5_deltat to string.
537c478bdstevel@tonic-gate */
547c478bdstevel@tonic-gate
55505d05cgtb#include "k5-int.h"
56505d05cgtb#include <ctype.h>
577c478bdstevel@tonic-gate
587c478bdstevel@tonic-gate/* Salt type conversions */
597c478bdstevel@tonic-gate
607c478bdstevel@tonic-gate/*
617c478bdstevel@tonic-gate * Local data structures.
627c478bdstevel@tonic-gate */
637c478bdstevel@tonic-gatestruct salttype_lookup_entry {
647c478bdstevel@tonic-gate    krb5_int32		stt_enctype;		/* Salt type		*/
657c478bdstevel@tonic-gate    const char *	stt_specifier;		/* How to recognize it	*/
667c478bdstevel@tonic-gate    const char *	stt_output;		/* How to spit it out	*/
677c478bdstevel@tonic-gate};
687c478bdstevel@tonic-gate
697c478bdstevel@tonic-gate/*
707c478bdstevel@tonic-gate * Lookup tables.
717c478bdstevel@tonic-gate */
72159d09aMark Phalan
73159d09aMark Phalan#include "kdb.h"
747c478bdstevel@tonic-gatestatic const struct salttype_lookup_entry salttype_table[] = {
757c478bdstevel@tonic-gate/* salt type			input specifier	output string  */
767c478bdstevel@tonic-gate/*-----------------------------	--------------- ---------------*/
777c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_NORMAL,	"normal",	"Version 5"	  },
787c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_V4,		"v4",		"Version 4"	  },
797c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_NOREALM,	"norealm",	"Version 5 - No Realm" },
807c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_ONLYREALM,	"onlyrealm",	"Version 5 - Realm Only" },
817c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_SPECIAL,	"special",	"Special" },
827c478bdstevel@tonic-gate{ KRB5_KDB_SALTTYPE_AFS3,	"afs3",		"AFS version 3"    }
837c478bdstevel@tonic-gate};
847c478bdstevel@tonic-gatestatic const int salttype_table_nents = sizeof(salttype_table)/
857c478bdstevel@tonic-gate					sizeof(salttype_table[0]);
867c478bdstevel@tonic-gate
87505d05cgtbkrb5_error_code KRB5_CALLCONV
88505d05cgtbkrb5_string_to_salttype(char *string, krb5_int32 *salttypep)
897c478bdstevel@tonic-gate{
907c478bdstevel@tonic-gate    int i;
917c478bdstevel@tonic-gate    int found;
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gate    found = 0;
947c478bdstevel@tonic-gate    for (i=0; i<salttype_table_nents; i++) {
957c478bdstevel@tonic-gate	if (!strcasecmp(string, salttype_table[i].stt_specifier)) {
967c478bdstevel@tonic-gate	    found = 1;
977c478bdstevel@tonic-gate	    *salttypep = salttype_table[i].stt_enctype;
987c478bdstevel@tonic-gate	    break;
997c478bdstevel@tonic-gate	}
1007c478bdstevel@tonic-gate    }
1017c478bdstevel@tonic-gate    return((found) ? 0 : EINVAL);
1027c478bdstevel@tonic-gate}
1037c478bdstevel@tonic-gate
1047c478bdstevel@tonic-gate/*
1057c478bdstevel@tonic-gate * Internal datatype to string routines.
1067c478bdstevel@tonic-gate *
1077c478bdstevel@tonic-gate * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
1087c478bdstevel@tonic-gate * if the supplied buffer/length will not contain the output.
1097c478bdstevel@tonic-gate */
110505d05cgtbkrb5_error_code KRB5_CALLCONV
111505d05cgtbkrb5_salttype_to_string(krb5_int32 salttype, char *buffer, size_t buflen)
1127c478bdstevel@tonic-gate{
1137c478bdstevel@tonic-gate    int i;
1147c478bdstevel@tonic-gate    const char *out;
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate    out = (char *) NULL;
1177c478bdstevel@tonic-gate    for (i=0; i<salttype_table_nents; i++) {
1187c478bdstevel@tonic-gate	if (salttype ==  salttype_table[i].stt_enctype) {
1197c478bdstevel@tonic-gate	    out = salttype_table[i].stt_output;
1207c478bdstevel@tonic-gate	    break;
1217c478bdstevel@tonic-gate	}
1227c478bdstevel@tonic-gate    }
1237c478bdstevel@tonic-gate    if (out) {
1247c478bdstevel@tonic-gate	if (buflen > strlen(out))
1257c478bdstevel@tonic-gate	    strcpy(buffer, out);
1267c478bdstevel@tonic-gate	else
1277c478bdstevel@tonic-gate	    out = (char *) NULL;
1287c478bdstevel@tonic-gate	return((out) ? 0 : ENOMEM);
1297c478bdstevel@tonic-gate    }
1307c478bdstevel@tonic-gate    else
1317c478bdstevel@tonic-gate	return(EINVAL);
1327c478bdstevel@tonic-gate}
1337c478bdstevel@tonic-gate
1347c478bdstevel@tonic-gate/* (absolute) time conversions */
1357c478bdstevel@tonic-gate
1367c478bdstevel@tonic-gate#ifndef HAVE_STRFTIME
1377c478bdstevel@tonic-gate#undef strftime
1387c478bdstevel@tonic-gate#define strftime my_strftime
1397c478bdstevel@tonic-gatestatic size_t strftime (char *, size_t, const char *, const struct tm *);
1407c478bdstevel@tonic-gate#endif
1417c478bdstevel@tonic-gate
142505d05cgtb#ifdef HAVE_STRPTIME
143505d05cgtb#ifdef NEED_STRPTIME_PROTO
144505d05cgtbextern char *strptime (const char *, const char *,
145505d05cgtb			    struct tm *)
146505d05cgtb#ifdef __cplusplus
147505d05cgtb    throw()
148505d05cgtb#endif
149505d05cgtb    ;
150505d05cgtb#endif
151505d05cgtb#else /* HAVE_STRPTIME */
1527c478bdstevel@tonic-gate#undef strptime
1537c478bdstevel@tonic-gate#define strptime my_strptime
1547c478bdstevel@tonic-gatestatic char *strptime (const char *, const char *, struct tm *);
1557c478bdstevel@tonic-gate#endif
1567c478bdstevel@tonic-gate
157505d05cgtbkrb5_error_code KRB5_CALLCONV
158505d05cgtbkrb5_string_to_timestamp(char *string, krb5_timestamp *timestampp)
1597c478bdstevel@tonic-gate{
160505d05cgtb    int i;
161505d05cgtb    struct tm timebuf;
162505d05cgtb    time_t now, ret_time;
1637c478bdstevel@tonic-gate    char *s;
1647c478bdstevel@tonic-gate    static const char * const atime_format_table[] = {
165159d09aMark Phalan	"%Y%m%d%H%M%S",		/* yyyymmddhhmmss		*/
1667c478bdstevel@tonic-gate	"%Y.%m.%d.%H.%M.%S",	/* yyyy.mm.dd.hh.mm.ss		*/
167159d09aMark Phalan	"%y%m%d%H%M%S",		/* yymmddhhmmss			*/
1687c478bdstevel@tonic-gate	"%y.%m.%d.%H.%M.%S",	/* yy.mm.dd.hh.mm.ss		*/
169159d09aMark Phalan	"%y%m%d%H%M",		/* yymmddhhmm			*/
170159d09aMark Phalan	"%H%M%S",		/* hhmmss			*/
171159d09aMark Phalan	"%H%M",			/* hhmm				*/
1727c478bdstevel@tonic-gate	"%T",			/* hh:mm:ss			*/
1737c478bdstevel@tonic-gate	"%R",			/* hh:mm			*/
1747c478bdstevel@tonic-gate	/* The following not really supported unless native strptime present */
1757c478bdstevel@tonic-gate	"%x:%X",		/* locale-dependent short format */
1767c478bdstevel@tonic-gate	"%d-%b-%Y:%T",		/* dd-month-yyyy:hh:mm:ss	*/
1777c478bdstevel@tonic-gate	"%d-%b-%Y:%R"		/* dd-month-yyyy:hh:mm		*/
1787c478bdstevel@tonic-gate    };
1797c478bdstevel@tonic-gate    static const int atime_format_table_nents =
1807c478bdstevel@tonic-gate	sizeof(atime_format_table)/sizeof(atime_format_table[0]);
1817c478bdstevel@tonic-gate
182505d05cgtb
183505d05cgtb    now = time((time_t *) NULL);
1847c478bdstevel@tonic-gate    for (i=0; i<atime_format_table_nents; i++) {
185505d05cgtb        /* We reset every time throughout the loop as the manual page
186505d05cgtb	 * indicated that no guarantees are made as to preserving timebuf
187505d05cgtb	 * when parsing fails
188505d05cgtb	 */
189505d05cgtb#ifdef HAVE_LOCALTIME_R
190505d05cgtb	(void) localtime_r(&now, &timebuf);
191505d05cgtb#else
192505d05cgtb	memcpy(&timebuf, localtime(&now), sizeof(timebuf));
193505d05cgtb#endif
19454925bfwillf	/*LINTED*/
195505d05cgtb	if ((s = strptime(string, atime_format_table[i], &timebuf))
196505d05cgtb	    && (s != string)) {
197505d05cgtb 	    /* See if at end of buffer - otherwise partial processing */
198505d05cgtb	    while(*s != 0 && isspace((int) *s)) s++;
199505d05cgtb	    if (*s != 0)
200505d05cgtb	        continue;
201505d05cgtb	    if (timebuf.tm_year <= 0)
202505d05cgtb		continue;	/* clearly confused */
203505d05cgtb	    ret_time = mktime(&timebuf);
204505d05cgtb	    if (ret_time == (time_t) -1)
205505d05cgtb		continue;	/* clearly confused */
206505d05cgtb	    *timestampp = (krb5_timestamp) ret_time;
207505d05cgtb	    return 0;
2087c478bdstevel@tonic-gate	}
2097c478bdstevel@tonic-gate    }
210505d05cgtb    return(EINVAL);
2117c478bdstevel@tonic-gate}
2127c478bdstevel@tonic-gate
213505d05cgtbkrb5_error_code KRB5_CALLCONV
214505d05cgtbkrb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
2157c478bdstevel@tonic-gate{
2167c478bdstevel@tonic-gate    int ret;
2177c478bdstevel@tonic-gate    time_t timestamp2 = timestamp;
218505d05cgtb    struct tm tmbuf;
219505d05cgtb    const char *fmt = "%c"; /* This is to get around gcc -Wall warning that
220505d05cgtb			       the year returned might be two digits */
2217c478bdstevel@tonic-gate
222505d05cgtb#ifdef HAVE_LOCALTIME_R
223505d05cgtb    (void) localtime_r(&timestamp2, &tmbuf);
224505d05cgtb#else
225505d05cgtb    memcpy(&tmbuf, localtime(&timestamp2), sizeof(tmbuf));
226505d05cgtb#endif
227505d05cgtb    ret = strftime(buffer, buflen, fmt, &tmbuf);
2287c478bdstevel@tonic-gate    if (ret == 0 || ret == buflen)
2297c478bdstevel@tonic-gate	return(ENOMEM);
2307c478bdstevel@tonic-gate    return(0);
2317c478bdstevel@tonic-gate}
2327c478bdstevel@tonic-gate
233505d05cgtbkrb5_error_code KRB5_CALLCONV
234505d05cgtbkrb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen, char *pad)
2357c478bdstevel@tonic-gate{
2367c478bdstevel@tonic-gate    struct tm	*tmp;
2377c478bdstevel@tonic-gate    size_t i;
2387c478bdstevel@tonic-gate    size_t	ndone;
2397c478bdstevel@tonic-gate    time_t timestamp2 = timestamp;
240