diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-03-12 00:52:01 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-03-14 18:55:32 +1100 |
commit | bf0fbf2b11a44f06a64b620af7d01ff171c28e13 (patch) | |
tree | bebb13975a12e80a295cafeec72417a6911ea750 | |
parent | fbd733ab7adc907118a6cf56c08ed90c7000043f (diff) |
upstream: add valid-before="[time]" authorized_keys option. A
simple way of giving a key an expiry date. ok markus@
OpenBSD-Commit-ID: 1793b4dd5184fa87f42ed33c7b0f4f02bc877947
-rw-r--r-- | auth-options.c | 32 | ||||
-rw-r--r-- | auth-options.h | 5 | ||||
-rw-r--r-- | auth.c | 28 | ||||
-rw-r--r-- | misc.c | 55 | ||||
-rw-r--r-- | misc.h | 4 | ||||
-rw-r--r-- | ssh-keygen.1 | 8 | ||||
-rw-r--r-- | ssh-keygen.c | 44 | ||||
-rw-r--r-- | sshd.8 | 8 |
8 files changed, 128 insertions, 56 deletions
diff --git a/auth-options.c b/auth-options.c index 484e44b74..38211fa2a 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.c,v 1.76 2018/03/03 03:15:51 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.c,v 1.77 2018/03/12 00:52:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> |
4 | * | 4 | * |
@@ -311,6 +311,7 @@ sshauthopt_parse(const char *opts, const char **errstrp) | |||
311 | int r; | 311 | int r; |
312 | struct sshauthopt *ret = NULL; | 312 | struct sshauthopt *ret = NULL; |
313 | const char *errstr = "unknown error"; | 313 | const char *errstr = "unknown error"; |
314 | uint64_t valid_before; | ||
314 | 315 | ||
315 | if (errstrp != NULL) | 316 | if (errstrp != NULL) |
316 | *errstrp = NULL; | 317 | *errstrp = NULL; |
@@ -366,6 +367,19 @@ sshauthopt_parse(const char *opts, const char **errstrp) | |||
366 | &errstr); | 367 | &errstr); |
367 | if (ret->required_from_host_keys == NULL) | 368 | if (ret->required_from_host_keys == NULL) |
368 | goto fail; | 369 | goto fail; |
370 | } else if (opt_match(&opts, "valid-before")) { | ||
371 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) | ||
372 | goto fail; | ||
373 | if (parse_absolute_time(opt, &valid_before) != 0 || | ||
374 | valid_before == 0) { | ||
375 | free(opt); | ||
376 | errstr = "invalid expires time"; | ||
377 | goto fail; | ||
378 | } | ||
379 | free(opt); | ||
380 | if (ret->valid_before == 0 || | ||
381 | valid_before < ret->valid_before) | ||
382 | ret->valid_before = valid_before; | ||
369 | } else if (opt_match(&opts, "environment")) { | 383 | } else if (opt_match(&opts, "environment")) { |
370 | if (ret->nenv > INT_MAX) { | 384 | if (ret->nenv > INT_MAX) { |
371 | errstr = "too many environment strings"; | 385 | errstr = "too many environment strings"; |
@@ -572,6 +586,13 @@ sshauthopt_merge(const struct sshauthopt *primary, | |||
572 | OPTFLAG(permit_user_rc); | 586 | OPTFLAG(permit_user_rc); |
573 | #undef OPTFLAG | 587 | #undef OPTFLAG |
574 | 588 | ||
589 | /* Earliest expiry time should win */ | ||
590 | if (primary->valid_before != 0) | ||
591 | ret->valid_before = primary->valid_before; | ||
592 | if (additional->valid_before != 0 && | ||
593 | additional->valid_before < ret->valid_before) | ||
594 | ret->valid_before = additional->valid_before; | ||
595 | |||
575 | /* | 596 | /* |
576 | * When both multiple forced-command are specified, only | 597 | * When both multiple forced-command are specified, only |
577 | * proceed if they are identical, otherwise fail. | 598 | * proceed if they are identical, otherwise fail. |
@@ -631,6 +652,7 @@ sshauthopt_copy(const struct sshauthopt *orig) | |||
631 | OPTSCALAR(restricted); | 652 | OPTSCALAR(restricted); |
632 | OPTSCALAR(cert_authority); | 653 | OPTSCALAR(cert_authority); |
633 | OPTSCALAR(force_tun_device); | 654 | OPTSCALAR(force_tun_device); |
655 | OPTSCALAR(valid_before); | ||
634 | #undef OPTSCALAR | 656 | #undef OPTSCALAR |
635 | #define OPTSTRING(x) \ | 657 | #define OPTSTRING(x) \ |
636 | do { \ | 658 | do { \ |
@@ -751,14 +773,15 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, | |||
751 | { | 773 | { |
752 | int r = SSH_ERR_INTERNAL_ERROR; | 774 | int r = SSH_ERR_INTERNAL_ERROR; |
753 | 775 | ||
754 | /* Flag options */ | 776 | /* Flag and simple integer options */ |
755 | if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 || | 777 | if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 || |
756 | (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 || | 778 | (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 || |
757 | (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 || | 779 | (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 || |
758 | (r = sshbuf_put_u8(m, opts->permit_pty_flag)) != 0 || | 780 | (r = sshbuf_put_u8(m, opts->permit_pty_flag)) != 0 || |
759 | (r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 || | 781 | (r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 || |
760 | (r = sshbuf_put_u8(m, opts->restricted)) != 0 || | 782 | (r = sshbuf_put_u8(m, opts->restricted)) != 0 || |
761 | (r = sshbuf_put_u8(m, opts->cert_authority)) != 0) | 783 | (r = sshbuf_put_u8(m, opts->cert_authority)) != 0 || |
784 | (r = sshbuf_put_u64(m, opts->valid_before)) != 0) | ||
762 | return r; | 785 | return r; |
763 | 786 | ||
764 | /* tunnel number can be negative to indicate "unset" */ | 787 | /* tunnel number can be negative to indicate "unset" */ |
@@ -815,6 +838,9 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp) | |||
815 | OPT_FLAG(cert_authority); | 838 | OPT_FLAG(cert_authority); |
816 | #undef OPT_FLAG | 839 | #undef OPT_FLAG |
817 | 840 | ||
841 | if ((r = sshbuf_get_u64(m, &opts->valid_before)) != 0) | ||
842 | goto out; | ||
843 | |||
818 | /* tunnel number can be negative to indicate "unset" */ | 844 | /* tunnel number can be negative to indicate "unset" */ |
819 | if ((r = sshbuf_get_u8(m, &f)) != 0 || | 845 | if ((r = sshbuf_get_u8(m, &f)) != 0 || |
820 | (r = sshbuf_get_u32(m, &tmp)) != 0) | 846 | (r = sshbuf_get_u32(m, &tmp)) != 0) |
diff --git a/auth-options.h b/auth-options.h index 16871d754..bf59b30be 100644 --- a/auth-options.h +++ b/auth-options.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.h,v 1.25 2018/03/03 03:15:51 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.h,v 1.26 2018/03/12 00:52:01 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> | 4 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> |
@@ -37,6 +37,9 @@ struct sshauthopt { | |||
37 | /* "restrict" keyword was invoked */ | 37 | /* "restrict" keyword was invoked */ |
38 | int restricted; | 38 | int restricted; |
39 | 39 | ||
40 | /* key/principal expiry date */ | ||
41 | uint64_t valid_before; | ||
42 | |||
40 | /* Certificate-related options */ | 43 | /* Certificate-related options */ |
41 | int cert_authority; | 44 | int cert_authority; |
42 | char *cert_principals; | 45 | char *cert_principals; |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.126 2018/03/03 03:15:51 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.127 2018/03/12 00:52:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -1004,20 +1004,21 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) | |||
1004 | int do_permitopen = opts->npermitopen > 0 && | 1004 | int do_permitopen = opts->npermitopen > 0 && |
1005 | (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0; | 1005 | (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0; |
1006 | size_t i; | 1006 | size_t i; |
1007 | char msg[1024], tbuf[32]; | 1007 | char msg[1024], buf[64]; |
1008 | 1008 | ||
1009 | snprintf(tbuf, sizeof(tbuf), "%d", opts->force_tun_device); | 1009 | snprintf(buf, sizeof(buf), "%d", opts->force_tun_device); |
1010 | /* Try to keep this alphabetically sorted */ | 1010 | /* Try to keep this alphabetically sorted */ |
1011 | snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s", | 1011 | snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s", |
1012 | opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", | 1012 | opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", |
1013 | opts->force_command == NULL ? "" : " command", | 1013 | opts->force_command == NULL ? "" : " command", |
1014 | do_env ? " environment" : "", | 1014 | do_env ? " environment" : "", |
1015 | opts->valid_before == 0 ? "" : "expires", | ||
1015 | do_permitopen ? " permitopen" : "", | 1016 | do_permitopen ? " permitopen" : "", |
1016 | opts->permit_port_forwarding_flag ? " port-forwarding" : "", | 1017 | opts->permit_port_forwarding_flag ? " port-forwarding" : "", |
1017 | opts->cert_principals == NULL ? "" : " principals", | 1018 | opts->cert_principals == NULL ? "" : " principals", |
1018 | opts->permit_pty_flag ? " pty" : "", | 1019 | opts->permit_pty_flag ? " pty" : "", |
1019 | opts->force_tun_device == -1 ? "" : " tun=", | 1020 | opts->force_tun_device == -1 ? "" : " tun=", |
1020 | opts->force_tun_device == -1 ? "" : tbuf, | 1021 | opts->force_tun_device == -1 ? "" : buf, |
1021 | opts->permit_user_rc ? " user-rc" : "", | 1022 | opts->permit_user_rc ? " user-rc" : "", |
1022 | opts->permit_x11_forwarding_flag ? " x11-forwarding" : ""); | 1023 | opts->permit_x11_forwarding_flag ? " x11-forwarding" : ""); |
1023 | 1024 | ||
@@ -1036,6 +1037,10 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) | |||
1036 | } | 1037 | } |
1037 | 1038 | ||
1038 | /* Go into a little more details for the local logs. */ | 1039 | /* Go into a little more details for the local logs. */ |
1040 | if (opts->valid_before != 0) { | ||
1041 | format_absolute_time(opts->valid_before, buf, sizeof(buf)); | ||
1042 | debug("%s: expires at %s", loc, buf); | ||
1043 | } | ||
1039 | if (opts->cert_principals != NULL) { | 1044 | if (opts->cert_principals != NULL) { |
1040 | debug("%s: authorized principals: \"%s\"", | 1045 | debug("%s: authorized principals: \"%s\"", |
1041 | loc, opts->cert_principals); | 1046 | loc, opts->cert_principals); |
@@ -1089,7 +1094,20 @@ auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw, | |||
1089 | const char *remote_ip = ssh_remote_ipaddr(ssh); | 1094 | const char *remote_ip = ssh_remote_ipaddr(ssh); |
1090 | const char *remote_host = auth_get_canonical_hostname(ssh, | 1095 | const char *remote_host = auth_get_canonical_hostname(ssh, |
1091 | options.use_dns); | 1096 | options.use_dns); |
1097 | time_t now = time(NULL); | ||
1098 | char buf[64]; | ||
1092 | 1099 | ||
1100 | /* | ||
1101 | * Check keys/principals file expiry time. | ||
1102 | * NB. validity interval in certificate is handled elsewhere. | ||
1103 | */ | ||
1104 | if (opts->valid_before && now > 0 && | ||
1105 | opts->valid_before < (uint64_t)now) { | ||
1106 | format_absolute_time(opts->valid_before, buf, sizeof(buf)); | ||
1107 | debug("%s: entry expired at %s", loc, buf); | ||
1108 | auth_debug_add("%s: entry expired at %s", loc, buf); | ||
1109 | return -1; | ||
1110 | } | ||
1093 | /* Consistency checks */ | 1111 | /* Consistency checks */ |
1094 | if (opts->cert_principals != NULL && !opts->cert_authority) { | 1112 | if (opts->cert_principals != NULL && !opts->cert_authority) { |
1095 | debug("%s: principals on non-CA key", loc); | 1113 | debug("%s: principals on non-CA key", loc); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.c,v 1.126 2018/03/07 23:53:08 djm Exp $ */ | 1 | /* $OpenBSD: misc.c,v 1.127 2018/03/12 00:52:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2005,2006 Damien Miller. All rights reserved. |
@@ -1976,3 +1976,56 @@ atoi_err(const char *nptr, int *val) | |||
1976 | *val = (int)num; | 1976 | *val = (int)num; |
1977 | return errstr; | 1977 | return errstr; |
1978 | } | 1978 | } |
1979 | |||
1980 | int | ||
1981 | parse_absolute_time(const char *s, uint64_t *tp) | ||
1982 | { | ||
1983 | struct tm tm; | ||
1984 | time_t tt; | ||
1985 | char buf[32], *fmt; | ||
1986 | |||
1987 | *tp = 0; | ||
1988 | |||
1989 | /* | ||
1990 | * POSIX strptime says "The application shall ensure that there | ||
1991 | * is white-space or other non-alphanumeric characters between | ||
1992 | * any two conversion specifications" so arrange things this way. | ||
1993 | */ | ||
1994 | switch (strlen(s)) { | ||
1995 | case 8: /* YYYYMMDD */ | ||
1996 | fmt = "%Y-%m-%d"; | ||
1997 | snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); | ||
1998 | break; | ||
1999 | case 12: /* YYYYMMDDHHMM */ | ||
2000 | fmt = "%Y-%m-%dT%H:%M"; | ||
2001 | snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s", | ||
2002 | s, s + 4, s + 6, s + 8, s + 10); | ||
2003 | break; | ||
2004 | case 14: /* YYYYMMDDHHMMSS */ | ||
2005 | fmt = "%Y-%m-%dT%H:%M:%S"; | ||
2006 | snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", | ||
2007 | s, s + 4, s + 6, s + 8, s + 10, s + 12); | ||
2008 | break; | ||
2009 | default: | ||
2010 | return SSH_ERR_INVALID_FORMAT; | ||
2011 | } | ||
2012 | |||
2013 | memset(&tm, 0, sizeof(tm)); | ||
2014 | if (strptime(buf, fmt, &tm) == NULL) | ||
2015 | return SSH_ERR_INVALID_FORMAT; | ||
2016 | if ((tt = mktime(&tm)) < 0) | ||
2017 | return SSH_ERR_INVALID_FORMAT; | ||
2018 | /* success */ | ||
2019 | *tp = (uint64_t)tt; | ||
2020 | return 0; | ||
2021 | } | ||
2022 | |||
2023 | void | ||
2024 | format_absolute_time(uint64_t t, char *buf, size_t len) | ||
2025 | { | ||
2026 | time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */ | ||
2027 | struct tm tm; | ||
2028 | |||
2029 | localtime_r(&tt, &tm); | ||
2030 | strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); | ||
2031 | } | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: misc.h,v 1.70 2018/01/08 15:21:49 markus Exp $ */ | 1 | /* $OpenBSD: misc.h,v 1.71 2018/03/12 00:52:01 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -75,6 +75,8 @@ void lowercase(char *s); | |||
75 | int unix_listener(const char *, int, int); | 75 | int unix_listener(const char *, int, int); |
76 | int valid_domain(char *, int, const char **); | 76 | int valid_domain(char *, int, const char **); |
77 | const char *atoi_err(const char *, int *); | 77 | const char *atoi_err(const char *, int *); |
78 | int parse_absolute_time(const char *, uint64_t *); | ||
79 | void format_absolute_time(uint64_t, char *, size_t); | ||
78 | 80 | ||
79 | void sock_set_v6only(int); | 81 | void sock_set_v6only(int); |
80 | 82 | ||
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index f925eb2d7..3525d7d17 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.146 2018/01/25 03:34:43 djm Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.147 2018/03/12 00:52:01 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: January 25 2018 $ | 38 | .Dd $Mdocdate: March 12 2018 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -588,13 +588,13 @@ of two times separated by a colon to indicate an explicit time interval. | |||
588 | The start time may be specified as the string | 588 | The start time may be specified as the string |
589 | .Dq always | 589 | .Dq always |
590 | to indicate the certificate has no specified start time, | 590 | to indicate the certificate has no specified start time, |
591 | a date in YYYYMMDD format, a time in YYYYMMDDHHMMSS format, | 591 | a date in YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format, |
592 | a relative time (to the current time) consisting of a minus sign followed by | 592 | a relative time (to the current time) consisting of a minus sign followed by |
593 | an interval in the format described in the | 593 | an interval in the format described in the |
594 | TIME FORMATS section of | 594 | TIME FORMATS section of |
595 | .Xr sshd_config 5 . | 595 | .Xr sshd_config 5 . |
596 | .Pp | 596 | .Pp |
597 | The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time, | 597 | The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMM[SS] time, |
598 | a relative time starting with a plus character or the string | 598 | a relative time starting with a plus character or the string |
599 | .Dq forever | 599 | .Dq forever |
600 | to indicate that the certificate has no expirty date. | 600 | to indicate that the certificate has no expirty date. |
diff --git a/ssh-keygen.c b/ssh-keygen.c index d80930eeb..9aac64fc3 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.313 2018/02/23 15:58:38 markus Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.314 2018/03/12 00:52:01 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -1798,40 +1798,6 @@ parse_relative_time(const char *s, time_t now) | |||
1798 | return now + (u_int64_t)(secs * mul); | 1798 | return now + (u_int64_t)(secs * mul); |
1799 | } | 1799 | } |
1800 | 1800 | ||
1801 | static u_int64_t | ||
1802 | parse_absolute_time(const char *s) | ||
1803 | { | ||
1804 | struct tm tm; | ||
1805 | time_t tt; | ||
1806 | char buf[32], *fmt; | ||
1807 | |||
1808 | /* | ||
1809 | * POSIX strptime says "The application shall ensure that there | ||
1810 | * is white-space or other non-alphanumeric characters between | ||
1811 | * any two conversion specifications" so arrange things this way. | ||
1812 | */ | ||
1813 | switch (strlen(s)) { | ||
1814 | case 8: | ||
1815 | fmt = "%Y-%m-%d"; | ||
1816 | snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); | ||
1817 | break; | ||
1818 | case 14: | ||
1819 | fmt = "%Y-%m-%dT%H:%M:%S"; | ||
1820 | snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", | ||
1821 | s, s + 4, s + 6, s + 8, s + 10, s + 12); | ||
1822 | break; | ||
1823 | default: | ||
1824 | fatal("Invalid certificate time format \"%s\"", s); | ||
1825 | } | ||
1826 | |||
1827 | memset(&tm, 0, sizeof(tm)); | ||
1828 | if (strptime(buf, fmt, &tm) == NULL) | ||
1829 | fatal("Invalid certificate time %s", s); | ||
1830 | if ((tt = mktime(&tm)) < 0) | ||
1831 | fatal("Certificate time %s cannot be represented", s); | ||
1832 | return (u_int64_t)tt; | ||
1833 | } | ||
1834 | |||
1835 | static void | 1801 | static void |
1836 | parse_cert_times(char *timespec) | 1802 | parse_cert_times(char *timespec) |
1837 | { | 1803 | { |
@@ -1867,15 +1833,15 @@ parse_cert_times(char *timespec) | |||
1867 | cert_valid_from = parse_relative_time(from, now); | 1833 | cert_valid_from = parse_relative_time(from, now); |
1868 | else if (strcmp(from, "always") == 0) | 1834 | else if (strcmp(from, "always") == 0) |
1869 | cert_valid_from = 0; | 1835 | cert_valid_from = 0; |
1870 | else | 1836 | else if (parse_absolute_time(from, &cert_valid_from) != 0) |
1871 | cert_valid_from = parse_absolute_time(from); | 1837 | fatal("Invalid from time \"%s\"", from); |
1872 | 1838 | ||
1873 | if (*to == '-' || *to == '+') | 1839 | if (*to == '-' || *to == '+') |
1874 | cert_valid_to = parse_relative_time(to, now); | 1840 | cert_valid_to = parse_relative_time(to, now); |
1875 | else if (strcmp(to, "forever") == 0) | 1841 | else if (strcmp(to, "forever") == 0) |
1876 | cert_valid_to = ~(u_int64_t)0; | 1842 | cert_valid_to = ~(u_int64_t)0; |
1877 | else | 1843 | else if (parse_absolute_time(to, &cert_valid_to) != 0) |
1878 | cert_valid_to = parse_absolute_time(to); | 1844 | fatal("Invalid to time \"%s\"", to); |
1879 | 1845 | ||
1880 | if (cert_valid_to <= cert_valid_from) | 1846 | if (cert_valid_to <= cert_valid_from) |
1881 | fatal("Empty certificate validity interval"); | 1847 | fatal("Empty certificate validity interval"); |
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd.8,v 1.296 2018/03/03 06:37:53 dtucker Exp $ | 36 | .\" $OpenBSD: sshd.8,v 1.297 2018/03/12 00:52:01 djm Exp $ |
37 | .Dd $Mdocdate: March 3 2018 $ | 37 | .Dd $Mdocdate: March 12 2018 $ |
38 | .Dt SSHD 8 | 38 | .Dt SSHD 8 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -602,6 +602,10 @@ Enables execution of | |||
602 | previously disabled by the | 602 | previously disabled by the |
603 | .Cm restrict | 603 | .Cm restrict |
604 | option. | 604 | option. |
605 | .It Cm valid-before="timespec" | ||
606 | Specifies a time after which the key will not be accepted. | ||
607 | The time may be specified as a YYYYMMDD date or a YYYYMMDDHHMM[SS] time | ||
608 | in the system time-zone. | ||
605 | .It Cm X11-forwarding | 609 | .It Cm X11-forwarding |
606 | Permits X11 forwarding previously disabled by the | 610 | Permits X11 forwarding previously disabled by the |
607 | .Cm restrict | 611 | .Cm restrict |