Skip to content
Snippets Groups Projects
Commit 84fdb756 authored by Jan Včelák's avatar Jan Včelák :rocket:
Browse files

dnssec, ISO time stamps writing and parsing

parent 5719692d
No related branches found
No related tags found
1 merge request!421DNSSEC, key time stamps parsing
......@@ -38,6 +38,8 @@ libshared_la_SOURCES = \
shared/pem.h \
shared/shared.h \
shared/strtonum.h \
shared/timestamp.c \
shared/timestamp.h \
shared/wire.h
libdnssec_la_CPPFLAGS = \
......
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include <stdbool.h>
#include <time.h>
#include "shared.h"
/*
* POSIX strftime supports '%z', strptime doesn't.
*/
#define TIME_FORMAT_BASE "%Y-%m-%dT%H:%M:%S"
#define TIME_FORMAT_WRITE TIME_FORMAT_BASE "%z"
#define TIME_FORMAT_READ TIME_FORMAT_BASE
/*!
* Read time zone offset in +hhmm or -hhmm format.
*
* Format written by '%z' specifier in \ref strftime.
*/
static bool read_timezone(const char *buffer, int *offset)
{
assert(buffer);
if (strlen(buffer) != 5) {
return false;
}
char sign;
unsigned hours, mins;
if (sscanf(buffer, "%c%2u%2u", &sign, &hours, &mins) != 3) {
return false;
}
if (sign != '+' && sign != '-') {
return false;
}
if (hours > 23 || mins > 59) {
return false;
}
*offset = (sign == '+' ? 1 : -1) * (hours * 3600 + mins * 60);
return true;
}
_public_
bool timestamp_write(char *buffer, size_t size, time_t timestamp)
{
if (!buffer) {
return false;
}
struct tm tm = { 0 };
if (!gmtime_r(&timestamp, &tm)) {
return false;
}
return strftime(buffer, size, TIME_FORMAT_WRITE, &tm) != 0;
}
_public_
bool timestamp_read(const char *buffer, time_t *timestamp_ptr)
{
if (!buffer || !timestamp_ptr) {
return false;
}
struct tm tm = { 0 };
const char *timezone = strptime(buffer, TIME_FORMAT_READ, &tm);
if (timezone == NULL) {
return false;
}
int gmtoff = 0;
if (!read_timezone(timezone, &gmtoff)) {
return false;
}
*timestamp_ptr = timegm(&tm) - gmtoff;
return true;
}
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
#include <time.h>
/*
* The ISO 8610 'YYYY-MM-DDThh:mm:ss+zzzz' format is used.
*/
/*!
* Write time stamp into a string buffer.
*
* \param buffer Buffer to write time stamp into.
* \param size Size of the output buffer.
* \param timestamp Time stamp value to be written.
*
* \return Time stamp was written successfully.
*
*/
bool timestamp_write(char *buffer, size_t size, time_t timestamp);
/*!
* Read a time stamp from a string buffer.
*
* \param[in] buffer Buffer to read time stamp from.
* \param[out] timestamp Read time stamp value.
*
* \return Time stamp was read successfully.
*/
bool timestamp_read(const char *buffer, time_t *timestamp);
......@@ -24,6 +24,7 @@
/shared_bignum
/shared_dname
/shared_strtonum
/shared_timestamp
/shared_wire
/sign
/sign_der
......
......@@ -43,6 +43,7 @@ check_PROGRAMS = \
shared_bignum \
shared_dname \
shared_strtonum \
shared_timestamp \
shared_wire \
tsig
......
/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <tap/basic.h>
#include "timestamp.h"
int main(int argc, char *argv[])
{
plan_lazy();
char buffer[128] = { 0 };
ok(timestamp_write(NULL, 0, 0) == false,
"timestamp_write: no buffer");
ok(timestamp_write(buffer, 10, 0) == false,
"timestamp_write: small buffer");
ok(timestamp_write(buffer, sizeof(buffer), 0) &&
strcmp(buffer, "1970-01-01T00:00:00+0000") == 0,
"timestamp_write: epoch begin");
ok(timestamp_write(buffer, sizeof(buffer), 1439554225) &&
strcmp(buffer, "2015-08-14T12:10:25+0000") == 0,
"timestamp_write: date in past");
ok(timestamp_write(buffer, sizeof(buffer), 2147483646) &&
strcmp(buffer, "2038-01-19T03:14:06+0000") == 0,
"timestamp_write: date in future (likely)");
time_t ts = 0;
ok(timestamp_read(NULL, &ts) == false,
"timestamp_read: no buffer");
ok(timestamp_read("", NULL) == false,
"timestamp_read: no output");
ok(timestamp_read("", &ts) == false,
"timestamp_read: empty input");
ok(timestamp_read("1970-01-01T00:00:00", &ts) == false,
"timestamp_read: missing time zone");
ok(timestamp_read("1970-01-01T00:00:00+000", &ts) == false,
"timestamp_read: malformed time zone");
ok(timestamp_read("1970-01-01T00:00:00+2400", &ts) == false,
"timestamp_read: malformed time zone hours");
ok(timestamp_read("1970-01-01T00:00:00+0090", &ts) == false,
"timestamp_read: malformed time zone minuts");
ok(timestamp_read("1970-01-01T00:00:01+0000", &ts) && ts == 1,
"timestamp_read: first second since epoch");
ok(timestamp_read("2009-02-13T23:31:31+0000", &ts) && ts == 1234567891,
"timestamp_read: date in past");
ok(timestamp_read("2034-05-05T01:24:20+0000", &ts) && ts == 2030405060,
"timestamp_read: date in future (likely)");
ok(timestamp_read("2015-08-14T14:25:46+0200", &ts) &&
timestamp_write(buffer, sizeof(buffer), ts) &&
strcmp(buffer, "2015-08-14T12:25:46+0000") == 0,
"timestamp convert time zone (east)");
ok(timestamp_read("2015-08-14T10:19:17-0230", &ts) &&
timestamp_write(buffer, sizeof(buffer), ts) &&
strcmp(buffer, "2015-08-14T12:49:17+0000") == 0,
"timestamp convert time zone (west)");
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment