Skip to content

Commit 7e81124

Browse files
committed
The date command only works up to 2038 on 32bit machines
Use a "Julian day" calculation to fix this.
1 parent 4ac0c3b commit 7e81124

File tree

1 file changed

+152
-7
lines changed

1 file changed

+152
-7
lines changed

mk-cert

Lines changed: 152 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,24 @@ decode_args() {
493493

494494
-days[=:]* ) CERT_DAYS="${ar#*[=:]}" ;;
495495
-alldays )
496+
# Try to use faketime to set:
497+
# notBefore=Jan 1 12:00:00 1999 GMT
498+
# notAfter=Dec 31 12:00:00 9999 GMT
499+
CERT_DAYS=
496500
if faketime -h 2>/dev/null | grep -qi libfaketime
497-
then ft() { faketime -f '1999-01-01 12:00:00' "$@" ; }
501+
then
502+
ft() { TZ=UTC faketime -f '1999-01-01 12:00:00' "$@" ; }
503+
if [ "$(ft date +%Y-%m-%d 2>/dev/null)" = '1999-01-01' ]
504+
then CERT_DAYS=2922304
505+
else ft() { "$@"; }
506+
fi
498507
fi
499508

500-
CERT_DAYS=$((2932896 - $(ft date +%s)/86400))
509+
# Otherwise just try to hit the right day.
510+
[ "$CERT_DAYS" = '' ] && {
511+
END_OF_TIME=$(jdayjdat 31 12 9999)
512+
CERT_DAYS=$((END_OF_TIME - $(jdayjdat $(date '+%d %m %Y' ) ) ))
513+
}
501514
;;
502515

503516
-out[=:]* ) FN="${ar#*[=:]}" ;;
@@ -985,6 +998,13 @@ check_args() {
985998
fi
986999

9871000
# Problems?
1001+
if ! openssl no-req 2>&1 | grep -qie ^req
1002+
then
1003+
echo >&2 'No suitable OpenSSL command found.'
1004+
echo >&2 'The -openssl=/path/exe can be used to choose one.'
1005+
exit 1
1006+
fi
1007+
9881008
if ! openssl x509 -help 2>&1 | grep -qie -set_serial
9891009
then NOSETSERIAL=yes
9901010
fi
@@ -1402,10 +1422,10 @@ sign_created_csr() {
14021422
# Default to days left on CA certificate
14031423
[[ "$CERT_DAYS" = "" && "$SINGLEUSECA" != yes ]] && {
14041424
ENDDAY="$(openssl x509 -noout -enddate -in <(echo "$SIGNPEM") )"
1405-
ENDDAY="$(date +%s --date="$(sed 's/^[^=]*=//' <<< "$ENDDAY")" ||:)"
1406-
TODAY="$(ft date +%s)"
1407-
[[ "$ENDDAY" = "" ]] && ENDDAY=2932896 || ENDDAY=$((ENDDAY/86400))
1408-
CERT_DAYS=$((ENDDAY - TODAY/86400))
1425+
ENDDAY="$(sed 's/^[^=]*=//' <<< "$ENDDAY")"
1426+
ENDDAY=$(jdayjdat $(awk '{print $2,$1,$4;}' <<< "$ENDDAY") )
1427+
TODAY=$(jdayjdat $(date '+%d %m %Y' ) )
1428+
CERT_DAYS=$((ENDDAY - TODAY))
14091429
}
14101430

14111431
# Do we have to override the CSR's common name?
@@ -1621,14 +1641,139 @@ extract_pubkey() {
16211641
echo "$PUBKEY"
16221642
}
16231643

1644+
jdayjdat() {
1645+
awk '#!/usr/bin/awk -f
1646+
1647+
BEGIN{
1648+
days[0] = "Sunday";
1649+
days[1] = "Monday";
1650+
days[2] = "Tuesday";
1651+
days[3] = "Wednesday";
1652+
days[4] = "Thursday";
1653+
days[5] = "Friday";
1654+
days[6] = "Saturday";
1655+
1656+
months["jan"] = 1;
1657+
months["feb"] = 2;
1658+
months["mar"] = 3;
1659+
months["apr"] = 4;
1660+
months["may"] = 5;
1661+
months["jun"] = 6;
1662+
months["jul"] = 7;
1663+
months["aug"] = 8;
1664+
months["sep"] = 9;
1665+
months["oct"] = 10;
1666+
months["nov"] = 11;
1667+
months["dec"] = 12;
1668+
1669+
if(ARGC == 2) {
1670+
j = ARGV[1]+0;
1671+
if (j>0 && j<65536) j += 2400000
1672+
split(jdate(j),A);
1673+
print A[1];
1674+
} else if(ARGC >= 4) {
1675+
d = ARGV[1]; m = ARGV[2]; y = ARGV[3];
1676+
1677+
if (d+0 > 999 && y < 100) { ms = d; d = y; y = ms; }
1678+
ms = tolower(substr(m, 1, 3));
1679+
if (ms in months) m = months[ms];
1680+
else {
1681+
ms = tolower(substr(d, 1, 3));
1682+
if (ms in months) {
1683+
d = m;
1684+
m = months[ms];
1685+
}
1686+
}
1687+
1688+
if( y>31 && y<70 ) y+=2000;
1689+
if( y>31 && y<100) y+=1900;
1690+
if( m<1) {m+=12; y--;}
1691+
if( m>12) {m-=12; y++;}
1692+
1693+
jd = jday(d,m,y);
1694+
if (ARGC > 4) {
1695+
printf("Input: %04d-%02d-%02d\n", y, m, d);
1696+
print jd
1697+
js = jdate(jd);
1698+
split(js,A,/[- ]/);
1699+
print js;
1700+
print A[1], A[2], A[3], days[A[4]];
1701+
} else
1702+
print jd
1703+
} else
1704+
if(ARGC == 1) {
1705+
"date +%s" | getline t
1706+
t += 43200;
1707+
j = int(t / 86400); t -= j * 86400;
1708+
j = int(j + 2440587);
1709+
print jdate(j), t "s";
1710+
} else
1711+
print "Incorrect arguments"
1712+
}
1713+
1714+
function jdate(j, y,m,d,dow)
1715+
{
1716+
# Julian date converter. Takes a julian date (the number of days since
1717+
# some distant epoch or other) and returns the broken out date.
1718+
# d = day of month;
1719+
# m = month;
1720+
# y = year (actual year, like 1977, not 77 unless it was 77 a.d.);
1721+
# dow = day of week (0->Sunday to 6->Saturday)
1722+
# These are Gregorian.
1723+
# Copied from Algorithm 199 in Collected algorithms of the CACM
1724+
# Author: Robert G. Tantzen, Translators: Nat Howard, Robert de Bath
1725+
1726+
j = j + 1
1727+
dow = (j + 1)%7;
1728+
j -= 1721119;
1729+
# This should be a Euclidean division. But dates before 0001-01-01 dont
1730+
# make much sense anyway. Or even Friday, 15 October 1582 when the
1731+
# Gregorian calendar started.
1732+
y = int((4 * j - 1)/146097);
1733+
j = 4 * j - 1 - 146097 * y;
1734+
d = int(j/4);
1735+
j = int((4 * d + 3)/1461);
1736+
d = 4 * d + 3 - 1461 * j;
1737+
d = int((d + 4)/4);
1738+
m = int((5 * d - 3)/153);
1739+
d = 5 * d - 3 - 153 * m;
1740+
d = int((d + 5) / 5);
1741+
y = 100 * y + j;
1742+
if(m < 10) m += 3; else { m -= 9; ++y; }
1743+
1744+
return sprintf("%04d-%02d-%02d %d", y, m, d, dow);
1745+
}
1746+
1747+
function jday(d,m,y, c,ya,j)
1748+
{
1749+
# Takes a date, and returns a Julian day. A Julian day is the number of
1750+
# days since some base date (in the very distant past).
1751+
# Handy for getting date of x number of days after a given Julian date
1752+
# (use jdate to get that from the Gregorian date).
1753+
# Author: Robert G. Tantzen, translators: Nat Howard, Robert de Bath
1754+
# Translated from the algol original in Collected Algorithms of CACM
1755+
# (This and jdate are algorithm 199).
1756+
1757+
if(m>2) m -=3; else { m +=9; --y; }
1758+
c = int(y/100);
1759+
ya = y - (100*c);
1760+
j = int(146097*c/4) + int(1461*ya/4) + int((153*m+2)/5) + d + 1721119;
1761+
1762+
return j - 1;
1763+
}
1764+
' "$@"
1765+
}
1766+
16241767
test_for_windows() {
16251768
# MINGW has two copies of openssl, one compiled for Windows and one
16261769
# compiled for Unix. The Windows version cannot be used with process
16271770
# substitution ( the <(...) stuff ). Check to see if the default is
16281771
# working, if not try to find the other one.
16291772
local pgm
16301773

1631-
if [ "$(openssl enc -a -in <(echo ok) 2>/dev/null )" != b2sK ]
1774+
if ! openssl no-req 2>&1 | grep -qie ^req
1775+
then openssl() { echo 2>&1 OpenSSL failed. ; return 1; }
1776+
elif [ "$(openssl enc -a -in <(echo ok) 2>/dev/null )" != b2sK ]
16321777
then
16331778
for pgm in $(which -a openssl)
16341779
do

0 commit comments

Comments
 (0)