From 1f47ff15b3673e6bd9d2148c155d20a718e84d3f Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Sun, 12 Oct 2008 21:51:51 +0000 Subject: [PATCH] validate strftime format string input (when necessary) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9985 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_apr.h | 10 ++++ .../applications/mod_dptools/mod_dptools.c | 6 ++- src/mod/applications/mod_fifo/mod_fifo.c | 10 ++-- src/mod/applications/mod_rss/mod_rss.c | 2 +- .../mod_voicemail/mod_voicemail.c | 14 ++--- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 +- .../event_handlers/mod_cdr_csv/mod_cdr_csv.c | 2 +- src/mod/loggers/mod_logfile/mod_logfile.c | 2 +- src/switch_apr.c | 51 +++++++++++++++++++ src/switch_channel.c | 13 +++-- src/switch_console.c | 2 +- src/switch_event.c | 2 +- src/switch_log.c | 2 +- src/switch_time.c | 2 +- 14 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index 26d8a9c13e..be15ba8d95 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -270,6 +270,16 @@ SWITCH_DECLARE(switch_status_t) switch_time_exp_gmt_get(switch_time_t *result, s */ SWITCH_DECLARE(switch_status_t) switch_strftime(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm); +/** + * formats the exploded time according to the format specified (does not validate format string) + * @param s string to write to + * @param retsize The length of the returned string + * @param max The maximum length of the string + * @param format The format for the time string + * @param tm The time to convert + */ +SWITCH_DECLARE(switch_status_t) switch_strftime_nocheck(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm); + /** * switch_rfc822_date formats dates in the RFC822 * format in an efficient manner. It is a fixed length diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index de6d66f2d1..e3309955c3 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1022,7 +1022,11 @@ SWITCH_STANDARD_API(strftime_api_function) thetime = switch_timestamp_now(); } switch_time_exp_lt(&tm, thetime); - switch_strftime(date, &retsize, sizeof(date), switch_strlen_zero(cmd) ? "%Y-%m-%d %T" : cmd, &tm); + if (switch_strlen_zero(cmd)) { + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + } else { + switch_strftime(date, &retsize, sizeof(date), cmd, &tm); + } stream->write_function(stream, "%s", date); return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index f81b10692c..ad8d936976 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -520,7 +520,7 @@ SWITCH_STANDARD_APP(fifo_function) ts = switch_timestamp_now(); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "fifo_status", "WAITING"); switch_channel_set_variable(channel, "fifo_timestamp", date); @@ -613,7 +613,7 @@ SWITCH_STANDARD_APP(fifo_function) } else { ts = switch_timestamp_now(); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "fifo_status", cd.do_orbit ? "TIMEOUT" : "ABORTED"); switch_channel_set_variable(channel, "fifo_timestamp", date); @@ -709,7 +709,7 @@ SWITCH_STANDARD_APP(fifo_function) ts = switch_timestamp_now(); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "fifo_status", "WAITING"); switch_channel_set_variable(channel, "fifo_timestamp", date); @@ -883,7 +883,7 @@ SWITCH_STANDARD_APP(fifo_function) ts = switch_timestamp_now(); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "fifo_status", "TALKING"); switch_channel_set_variable(channel, "fifo_target", uuid); switch_channel_set_variable(channel, "fifo_timestamp", date); @@ -910,7 +910,7 @@ SWITCH_STANDARD_APP(fifo_function) ts = switch_timestamp_now(); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "fifo_status", "WAITING"); switch_channel_set_variable(channel, "fifo_timestamp", date); diff --git a/src/mod/applications/mod_rss/mod_rss.c b/src/mod/applications/mod_rss/mod_rss.c index c3043c01a0..a57b95ea4d 100644 --- a/src/mod/applications/mod_rss/mod_rss.c +++ b/src/mod/applications/mod_rss/mod_rss.c @@ -480,7 +480,7 @@ SWITCH_STANDARD_APP(rss_function) char dtmf[5] = ""; switch_time_exp_lt(&tm, switch_timestamp_now()); - switch_strftime(date, &retsize, sizeof(date), "%I:%M %p", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%I:%M %p", &tm); switch_snprintf(buf, sizeof(buf), diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index a1a796428e..1d8c772a90 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -2728,7 +2728,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, cons free(dbuf); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_channel_set_variable(channel, "RECORD_DATE", date); switch_channel_set_variable(channel, "RECORD_SOFTWARE", "FreeSWITCH"); switch_channel_set_variable(channel, "RECORD_TITLE", profile->record_title); @@ -3176,13 +3176,13 @@ static int web_callback(void *pArg, int argc, char **argv, char **columnNames) if (l_created) { switch_time_exp_lt(&tm, l_created); - switch_strftime(create_date, &retsize, sizeof(create_date), fmt, &tm); - switch_strftime(rss_date, &retsize, sizeof(create_date), "%D %T", &tm); + switch_strftime_nocheck(create_date, &retsize, sizeof(create_date), fmt, &tm); + switch_strftime_nocheck(rss_date, &retsize, sizeof(create_date), "%D %T", &tm); } if (l_read) { switch_time_exp_lt(&tm, l_read); - switch_strftime(read_date, &retsize, sizeof(read_date), fmt, &tm); + switch_strftime_nocheck(read_date, &retsize, sizeof(read_date), fmt, &tm); } switch_snprintf(heard, sizeof(heard), *read_date == '\0' ? "never" : read_date); @@ -3256,13 +3256,13 @@ static int rss_callback(void *pArg, int argc, char **argv, char **columnNames) if (l_created) { switch_time_exp_lt(&tm, l_created); - switch_strftime(create_date, &retsize, sizeof(create_date), fmt, &tm); - switch_strftime(rss_date, &retsize, sizeof(create_date), fmt, &tm); + switch_strftime_nocheck(create_date, &retsize, sizeof(create_date), fmt, &tm); + switch_strftime_nocheck(rss_date, &retsize, sizeof(create_date), fmt, &tm); } if (l_read) { switch_time_exp_lt(&tm, l_read); - switch_strftime(read_date, &retsize, sizeof(read_date), fmt, &tm); + switch_strftime_nocheck(read_date, &retsize, sizeof(read_date), fmt, &tm); } holder->x_item = switch_xml_add_child_d(holder->x_channel, "item", holder->items++); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 2023910e20..d633ea3e19 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1251,7 +1251,7 @@ static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNam switch_size_t retsize; switch_time_exp_lt(&tm, switch_time_from_sec(etime)); - switch_strftime(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm); } cb->stream->write_function(cb->stream, diff --git a/src/mod/event_handlers/mod_cdr_csv/mod_cdr_csv.c b/src/mod/event_handlers/mod_cdr_csv/mod_cdr_csv.c index ba492ed4ce..1abfb09f48 100644 --- a/src/mod/event_handlers/mod_cdr_csv/mod_cdr_csv.c +++ b/src/mod/event_handlers/mod_cdr_csv/mod_cdr_csv.c @@ -100,7 +100,7 @@ static void do_rotate(cdr_fd_t *fd) if (globals.rotate) { switch_time_exp_lt(&tm, switch_timestamp_now()); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm); len = strlen(fd->path) + strlen(date) + 2; p = switch_mprintf("%s.%s", fd->path, date); diff --git a/src/mod/loggers/mod_logfile/mod_logfile.c b/src/mod/loggers/mod_logfile/mod_logfile.c index 1b5fc5191b..2de93808d1 100644 --- a/src/mod/loggers/mod_logfile/mod_logfile.c +++ b/src/mod/loggers/mod_logfile/mod_logfile.c @@ -125,7 +125,7 @@ static switch_status_t mod_logfile_rotate(logfile_profile_t *profile) switch_mutex_lock(globals.mutex); switch_time_exp_lt(&tm, switch_timestamp_now()); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d-%H-%M-%S", &tm); profile->log_size = 0; diff --git a/src/switch_apr.c b/src/switch_apr.c index a936b780a0..0fb9e89a97 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -103,6 +103,57 @@ SWITCH_DECLARE(const char *) switch_dso_error(switch_dso_handle_t *dso, char *bu /* string functions */ SWITCH_DECLARE(switch_status_t) switch_strftime(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm) +{ + const char *p = format; + + if (!p) return SWITCH_STATUS_FALSE; + + while (*p) { + if (*p == '%') { + switch (*(++p)) { + case 'C': + case 'D': + case 'r': + case 'R': + case 'T': + case 'e': + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'd': + case 'H': + case 'I': + case 'j': + case 'm': + case 'M': + case 'p': + case 'S': + case 'U': + case 'w': + case 'W': + case 'x': + case 'X': + case 'y': + case 'Y': + case 'z': + case 'Z': + case '%': + p++; + continue; + case '\0': + default: + return SWITCH_STATUS_FALSE; + } + } + p++; + } + + return apr_strftime(s, retsize, max, format, (apr_time_exp_t *) tm); +} + +SWITCH_DECLARE(switch_status_t) switch_strftime_nocheck(char *s, switch_size_t *retsize, switch_size_t max, const char *format, switch_time_exp_t *tm) { return apr_strftime(s, retsize, max, format, (apr_time_exp_t *) tm); } diff --git a/src/switch_channel.c b/src/switch_channel.c index 003685d6f8..2933f2a250 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2105,40 +2105,39 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t * cid_buf = caller_profile->caller_id_number; } - if (caller_profile->times) { switch_time_exp_t tm; switch_size_t retsize; const char *fmt = "%Y-%m-%d %T"; switch_time_exp_lt(&tm, caller_profile->times->created); - switch_strftime(start, &retsize, sizeof(start), fmt, &tm); + switch_strftime_nocheck(start, &retsize, sizeof(start), fmt, &tm); switch_channel_set_variable(channel, "start_stamp", start); switch_time_exp_lt(&tm, caller_profile->times->profile_created); - switch_strftime(profile_start, &retsize, sizeof(profile_start), fmt, &tm); + switch_strftime_nocheck(profile_start, &retsize, sizeof(profile_start), fmt, &tm); switch_channel_set_variable(channel, "profile_start_stamp", profile_start); if (caller_profile->times->answered) { switch_time_exp_lt(&tm, caller_profile->times->answered); - switch_strftime(answer, &retsize, sizeof(answer), fmt, &tm); + switch_strftime_nocheck(answer, &retsize, sizeof(answer), fmt, &tm); switch_channel_set_variable(channel, "answer_stamp", answer); } if (caller_profile->times->progress) { switch_time_exp_lt(&tm, caller_profile->times->progress); - switch_strftime(progress, &retsize, sizeof(progress), fmt, &tm); + switch_strftime_nocheck(progress, &retsize, sizeof(progress), fmt, &tm); switch_channel_set_variable(channel, "progress_stamp", progress); } if (caller_profile->times->progress_media) { switch_time_exp_lt(&tm, caller_profile->times->progress_media); - switch_strftime(progress_media, &retsize, sizeof(progress_media), fmt, &tm); + switch_strftime_nocheck(progress_media, &retsize, sizeof(progress_media), fmt, &tm); switch_channel_set_variable(channel, "progress_media_stamp", progress_media); } switch_time_exp_lt(&tm, caller_profile->times->hungup); - switch_strftime(end, &retsize, sizeof(end), fmt, &tm); + switch_strftime_nocheck(end, &retsize, sizeof(end), fmt, &tm); switch_channel_set_variable(channel, "end_stamp", end); tt_created = (time_t) (caller_profile->times->created / 1000000); diff --git a/src/switch_console.c b/src/switch_console.c index ca26ff52a9..6c36730112 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -289,7 +289,7 @@ SWITCH_DECLARE(void) switch_console_printf(switch_text_channel_t channel, const } switch_time_exp_lt(&tm, switch_timestamp_now()); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); if (channel == SWITCH_CHANNEL_ID_LOG) { fprintf(handle, "[%d] %s %s:%d %s() %s", (int) getpid(), date, filep, line, func, data); diff --git a/src/switch_event.c b/src/switch_event.c index 88666a94f0..7de730e232 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -1008,7 +1008,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_fire_detailed(const char *file, con switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "FreeSWITCH-IPv6", guess_ip_v6); switch_time_exp_lt(&tm, ts); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Date-Local", date); switch_rfc822_date(date, ts); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Date-GMT", date); diff --git a/src/switch_log.c b/src/switch_log.c index 084c7c8eac..bbfd1f21a1 100644 --- a/src/switch_log.c +++ b/src/switch_log.c @@ -265,7 +265,7 @@ SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, const char switch_time_exp_t tm; switch_time_exp_lt(&tm, now); - switch_strftime(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(funcp) + strlen(fmt)); new_fmt = malloc(len + 1); diff --git a/src/switch_time.c b/src/switch_time.c index a2bf2379a1..97ff8e810f 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -571,7 +571,7 @@ SWITCH_DECLARE(switch_status_t) switch_strftime_tz(const char *tz, const char *f if (tzdef) { /* The lookup of the zone may fail. */ tztime( &timep, tzdef, &tm ); tm2switchtime( &tm, &stm ); - switch_strftime(date, &retsize, len, switch_strlen_zero(format) ? "%Y-%m-%d %T" : format, &stm); + switch_strftime_nocheck(date, &retsize, len, switch_strlen_zero(format) ? "%Y-%m-%d %T" : format, &stm); if (!switch_strlen_zero_buf(date)) { return SWITCH_STATUS_SUCCESS; }