четверг, 20 ноября 2008 г.

Отгадки времени

Забавная проблема возникла на работе. Разрабатываем мы Континент, в нем есть компонент - сервер доступа. Он позволяет пользователям подключаться к VPN извне. Авторизация осуществляется на сертификатах, технология открытых ключей, как там ее.

Появился баг - Невозможно создать сертификат с датами начала/окончания срока действия меньше/больше соответственно 1950/2049гг. Причем интерфейс позволяет ввести в качестве года значение от 1753 до 4111. И откуда взялись эти странные цифры?

Приоритет у запроса естественно был ниже плинтуса, но руки до него всетаки дошли и выяснилось следующее... Время в сертификате может храниться в двух форматах: UTCTime и generalizedTime. Отличаются они собственно одним - UTCTime ограничивает значение года только двумя значащими цифрами, а generalizedTime - позволяет указывать четыре.

Понятно уже, что сервером обрабатывался только первый вариант. Там правда были прикручены какие-то костыли на тему трех и четырехзначного значения года, но никаких попыток обработать поля типа generalizedTime не производилось.

Дело не сложное, переписал функцию, и появилась возможность анализировать и тот и другой, но не все так гладко. (Иначе и не стал бы растекаться тут мысью по дереву). Сравнивается то все это дело с текущим временем, для того, чтобы определить действует ли сейтификат в данный момент.

Но текйщий момент времени мы можем получить только в time_t, диапазон которого ограничен датами от 1970 до 2037 года.

Но и generalizedTime сконвертировать в time_t сразу не получится. Можно воспользоваться структурой tm, диапазон которой снизу ограничен 1900 годом.

Сплошные ограничения. Могли бы создать проблемы, если бы текущее время системы можно было задвинуть за пределы 1970 года. Думаю что ни одна система этого сейчас не потерпит, а нам нужно только убедиться, что сертификат действует сейчас. Поэтому время сертификата можно смело обрубить до диапазона time_t, и сравнивать с текущим.

Хотя сам сертификат может иметь даты в значительно более широких пределах. Вопрос в том, кому это надо? По хорошему, выписывать сетификаты задним числом вообще не правильно.

Ссылки по теме: RFC2459, RFC3161.

4 коммент.:

Unknown комментирует...

Не знаю, дружишь ли ты с .Net, но там встроенный тип DateTime без ограничений.

Андрей Валяев комментирует...

Тут дело не в Net, с которым я не дружу, всмысле никогда дела не имел.

И даже не в C++...

Это проблема ASN1. Видимо первоначально они ввели тип UTCTime, но очень ограниченный. Очень часто такое ограниченное мышление встречается...

Unknown комментирует...

Тоесть не удаётся получить 64-битное значение даты? Если как-то получится, то интерпретировать просто: 62 бита это количество 100нс тиков начиная с 01.01.0001

Unknown комментирует...

Старшие 2 бита это флаги: Локальное время, Глобальное время.