1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/str_conv.c - Convert between strings and krb5 data types */
3 /*
4 * Copyright 1995, 1999, 2007 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26
27 /*
28 * Table of contents:
29 *
30 * String decoding:
31 * ----------------
32 * krb5_string_to_salttype() - Convert string to salttype (krb5_int32)
33 * krb5_string_to_timestamp() - Convert string to krb5_timestamp.
34 * krb5_string_to_deltat() - Convert string to krb5_deltat.
35 *
36 * String encoding:
37 * ----------------
38 * krb5_salttype_to_string() - Convert salttype (krb5_int32) to string.
39 * krb5_timestamp_to_string() - Convert krb5_timestamp to string.
40 * krb5_timestamp_to_sfstring() - Convert krb5_timestamp to short filled string
41 * krb5_deltat_to_string() - Convert krb5_deltat to string.
42 */
43
44 #include "k5-int.h"
45 #include <ctype.h>
46
47 /* Salt type conversions */
48
49 /*
50 * Local data structures.
51 */
52 struct salttype_lookup_entry {
53 krb5_int32 stt_enctype; /* Salt type number */
54 const char * stt_name; /* Salt type name */
55 };
56
57 /*
58 * Lookup tables.
59 */
60
61 #include "kdb.h"
62 static const struct salttype_lookup_entry salttype_table[] = {
63 { KRB5_KDB_SALTTYPE_NORMAL, "normal" },
64 { KRB5_KDB_SALTTYPE_NOREALM, "norealm", },
65 { KRB5_KDB_SALTTYPE_ONLYREALM, "onlyrealm", },
66 { KRB5_KDB_SALTTYPE_SPECIAL, "special", },
67 };
68 static const int salttype_table_nents = sizeof(salttype_table)/
69 sizeof(salttype_table[0]);
70
71 krb5_error_code KRB5_CALLCONV
krb5_string_to_salttype(char * string,krb5_int32 * salttypep)72 krb5_string_to_salttype(char *string, krb5_int32 *salttypep)
73 {
74 int i;
75 int found;
76
77 found = 0;
78 for (i=0; i<salttype_table_nents; i++) {
79 if (!strcasecmp(string, salttype_table[i].stt_name)) {
80 found = 1;
81 *salttypep = salttype_table[i].stt_enctype;
82 break;
83 }
84 }
85 return((found) ? 0 : EINVAL);
86 }
87
88 /*
89 * Internal datatype to string routines.
90 *
91 * These routines return 0 for success, EINVAL for invalid parameter, ENOMEM
92 * if the supplied buffer/length will not contain the output.
93 */
94 krb5_error_code KRB5_CALLCONV
krb5_salttype_to_string(krb5_int32 salttype,char * buffer,size_t buflen)95 krb5_salttype_to_string(krb5_int32 salttype, char *buffer, size_t buflen)
96 {
97 int i;
98 const char *out;
99
100 out = (char *) NULL;
101 for (i=0; i<salttype_table_nents; i++) {
102 if (salttype == salttype_table[i].stt_enctype) {
103 out = salttype_table[i].stt_name;
104 break;
105 }
106 }
107 if (out) {
108 if (strlcpy(buffer, out, buflen) >= buflen)
109 return(ENOMEM);
110 return(0);
111 }
112 else
113 return(EINVAL);
114 }
115
116 /* (absolute) time conversions */
117
118 #ifdef HAVE_STRPTIME
119 #ifdef NEED_STRPTIME_PROTO
120 extern char *strptime (const char *, const char *,
121 struct tm *)
122 #ifdef __cplusplus
123 throw()
124 #endif
125 ;
126 #endif
127 #else /* HAVE_STRPTIME */
128 #undef strptime
129 #define strptime my_strptime
130 static char *strptime (const char *, const char *, struct tm *);
131 #endif
132
133 #ifndef HAVE_LOCALTIME_R
134 static inline struct tm *
localtime_r(const time_t * t,struct tm * buf)135 localtime_r(const time_t *t, struct tm *buf)
136 {
137 struct tm *tm = localtime(t);
138 if (tm == NULL)
139 return NULL;
140 *buf = *tm;
141 return buf;
142 }
143 #endif
144
145 krb5_error_code KRB5_CALLCONV
krb5_string_to_timestamp(char * string,krb5_timestamp * timestampp)146 krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp)
147 {
148 int i;
149 struct tm timebuf, timebuf2;
150 time_t now, ret_time;
151 char *s;
152 static const char * const atime_format_table[] = {
153 "%Y%m%d%H%M%S", /* yyyymmddhhmmss */
154 "%Y.%m.%d.%H.%M.%S", /* yyyy.mm.dd.hh.mm.ss */
155 "%y%m%d%H%M%S", /* yymmddhhmmss */
156 "%y.%m.%d.%H.%M.%S", /* yy.mm.dd.hh.mm.ss */
157 "%y%m%d%H%M", /* yymmddhhmm */
158 "%H%M%S", /* hhmmss */
159 "%H%M", /* hhmm */
160 "%T", /* hh:mm:ss */
161 "%R", /* hh:mm */
162 /* The following not really supported unless native strptime present */
163 "%x:%X", /* locale-dependent short format */
164 "%d-%b-%Y:%T", /* dd-month-yyyy:hh:mm:ss */
165 "%d-%b-%Y:%R" /* dd-month-yyyy:hh:mm */
166 };
167 static const int atime_format_table_nents =
168 sizeof(atime_format_table)/sizeof(atime_format_table[0]);
169
170
171 now = time((time_t *) NULL);
172 if (localtime_r(&now, &timebuf2) == NULL)
173 return EINVAL;
174 for (i=0; i<atime_format_table_nents; i++) {
175 /* We reset every time throughout the loop as the manual page
176 * indicated that no guarantees are made as to preserving timebuf
177 * when parsing fails
178 */
179 timebuf = timebuf2;
180 if ((s = strptime(string, atime_format_table[i], &timebuf))
181 && (s != string)) {
182 /* See if at end of buffer - otherwise partial processing */
183 while(*s != 0 && isspace((int) *s)) s++;
184 if (*s != 0)
185 continue;
186 if (timebuf.tm_year <= 0)
187 continue; /* clearly confused */
188 ret_time = mktime(&timebuf);
189 if (ret_time == (time_t) -1)
190 continue; /* clearly confused */
191 *timestampp = (krb5_timestamp) ret_time;
192 return 0;
193 }
194 }
195 return(EINVAL);
196 }
197
198 krb5_error_code KRB5_CALLCONV
krb5_timestamp_to_string(krb5_timestamp timestamp,char * buffer,size_t buflen)199 krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
200 {
201 size_t ret;
202 time_t timestamp2 = ts2tt(timestamp);
203 struct tm tmbuf;
204 const char *fmt = "%c"; /* This is to get around gcc -Wall warning that
205 the year returned might be two digits */
206
207 if (localtime_r(×tamp2, &tmbuf) == NULL)
208 return(ENOMEM);
209 ret = strftime(buffer, buflen, fmt, &tmbuf);
210 if (ret == 0 || ret == buflen)
211 return(ENOMEM);
212 return(0);
213 }
214
215 krb5_error_code KRB5_CALLCONV
krb5_timestamp_to_sfstring(krb5_timestamp timestamp,char * buffer,size_t buflen,char * pad)216 krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen, char *pad)
217 {
218 struct tm *tmp;
219 size_t i;
220 size_t ndone;
221 time_t timestamp2 = ts2tt(timestamp);
222 struct tm tmbuf;
223
224 static const char * const sftime_format_table[] = {
225 "%c", /* Default locale-dependent date and time */
226 "%d %b %Y %T", /* dd mon yyyy hh:mm:ss */
227 "%x %X", /* locale-dependent short format */
228 "%x %T", /* locale-dependent date + hh:mm:ss */
229 "%x %R", /* locale-dependent date + hh:mm */
230 "%Y-%m-%dT%H:%M:%S", /* ISO 8601 date + time */
231 "%Y-%m-%dT%H:%M", /* ISO 8601 date + hh:mm */
232 "%Y%m%d%H%M%S", /* ISO 8601 date + time, basic */
233 "%Y%m%d%H%M" /* ISO 8601 date + hh:mm, basic */
234 };
235 static const unsigned int sftime_format_table_nents =
236 sizeof(sftime_format_table)/sizeof(sftime_format_table[0]);
237
238 tmp = localtime_r(×tamp2, &tmbuf);
239 if (tmp == NULL)
240 return errno;
241 ndone = 0;
242 for (i=0; i<sftime_format_table_nents; i++) {
243 if ((ndone = strftime(buffer, buflen, sftime_format_table[i], tmp)))
244 break;
245 }
246 if (ndone && pad) {
247 for (i=ndone; i<buflen-1; i++)
248 buffer[i] = *pad;
249 buffer[buflen-1] = '\0';
250 }
251 return((ndone) ? 0 : ENOMEM);
252 }
253
254 /* relative time (delta-t) conversions */
255
256 /* string->deltat is in deltat.y */
257
258 krb5_error_code KRB5_CALLCONV
krb5_deltat_to_string(krb5_deltat deltat,char * buffer,size_t buflen)259 krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
260 {
261 int days, hours, minutes, seconds;
262 krb5_deltat dt;
263
264 days = (int) (deltat / (24*3600L));
265 dt = deltat % (24*3600L);
266 hours = (int) (dt / 3600);
267 dt %= 3600;
268 minutes = (int) (dt / 60);
269 seconds = (int) (dt % 60);
270
271 if (days == 0)
272 snprintf(buffer, buflen, "%d:%02d:%02d", hours, minutes, seconds);
273 else if (hours || minutes || seconds)
274 snprintf(buffer, buflen, "%d %s %02d:%02d:%02d", days,
275 (days > 1) ? "days" : "day",
276 hours, minutes, seconds);
277 else
278 snprintf(buffer, buflen, "%d %s", days,
279 (days > 1) ? "days" : "day");
280 return 0;
281 }
282
283 #undef __P
284 #define __P(X) X
285
286 #ifndef HAVE_STRPTIME
287 #undef _CurrentTimeLocale
288 #define _CurrentTimeLocale (&dummy_locale_info)
289
290 struct dummy_locale_info_t {
291 char d_t_fmt[15];
292 char t_fmt_ampm[12];
293 char t_fmt[9];
294 char d_fmt[9];
295 char day[7][10];
296 char abday[7][4];
297 char mon[12][10];
298 char abmon[12][4];
299 char am_pm[2][3];
300 };
301 static const struct dummy_locale_info_t dummy_locale_info = {
302 "%a %b %d %X %Y", /* %c */
303 "%I:%M:%S %p", /* %r */
304 "%H:%M:%S", /* %X */
305 "%m/%d/%y", /* %x */
306 { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
307 "Saturday" },
308 { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
309 { "January", "February", "March", "April", "May", "June",
310 "July", "August", "September", "October", "November", "December" },
311 { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
312 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
313 { "AM", "PM" },
314 };
315 #undef TM_YEAR_BASE
316 #define TM_YEAR_BASE 1900
317
318 #include "strptime.c"
319 #endif
320