Call for testing: OpenSSH-5.6

Damien Miller djm at mindrot.org
Sun Aug 15 14:11:01 EST 2010


On Sun, 15 Aug 2010, Darren Tucker wrote:

> On Sun, Aug 15, 2010 at 12:14:28PM +1000, Damien Miller wrote:
> > On Sun, 15 Aug 2010, Darren Tucker wrote:
> [...]
> > > It's only used when generating time-based certificates, so the quick and
> > > dirty hack is to just disable that on platforms that don't have
> > > strptime.  (I looked at pulling in support from openbsd but it's a
> > > tangled web of locale stuff).
> > > 
> > > Please try this patch (you will need to run "autoreconf" to rebuild
> > > configure).
> > 
> > I think this is a reasonable thingto do for release. Note that you
> > will still be able to use time-based certificates if you want to use
> > them, but you will need to specify the start and end times using the
> > relative time format.
> 
> I think a better way of doing this longer term is to have a dummy
> strptime implementation in the compat library, but that can wait until
> after the release since it risks linking problems elsewhere.

Actually, OpenBSD's strptime isn't too tangled if you chop out the
locale stuff. We don't actually use any of that anyway, just the numeric
converters. Here is a stab at a port, but it is late here and I'm
too tired to test it (it assumes you have the configure bits done already).

diff -u -r1.44 Makefile.in
--- openbsd-compat/Makefile.in	15 Jan 2010 01:38:30 -0000	1.44
+++ openbsd-compat/Makefile.in	15 Aug 2010 04:09:37 -0000
@@ -16,7 +16,7 @@
 INSTALL=@INSTALL@
 LDFLAGS=-L. @LDFLAGS@
 
-OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
+OPENBSD=base64.o basename.o bindresvport.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o vis.o
 
 COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
 
Index: openbsd-compat/openbsd-compat.h
===================================================================
RCS file: /var/cvs/openssh/openbsd-compat/openbsd-compat.h,v
retrieving revision 1.49
diff -u -r1.49 openbsd-compat.h
--- openbsd-compat/openbsd-compat.h	16 Jan 2010 12:58:37 -0000	1.49
+++ openbsd-compat/openbsd-compat.h	15 Aug 2010 04:09:37 -0000
@@ -87,6 +87,10 @@
 void strmode(int mode, char *p);
 #endif
 
+#ifndef HAVE_STRPTIME
+char *strptime(const char *buf, const char *fmt, struct tm *tm);
+#endif
+
 #if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
 int mkstemps(char *path, int slen);
 int mkstemp(char *path);
Index: openbsd-compat/strptime.c
===================================================================
RCS file: openbsd-compat/strptime.c
diff -N openbsd-compat/strptime.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openbsd-compat/strptime.c	15 Aug 2010 04:09:38 -0000
@@ -0,0 +1,400 @@
+/*	$OpenBSD: strptime.c,v 1.12 2008/06/26 05:42:05 ray Exp $ */
+/*	$NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $	*/
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* OPENBSD ORIGINAL: lib/libc/time/strptime.c */
+
+#include "includes.h"
+
+#ifndef HAVE_STRPTIME
+
+#include <ctype.h>
+#include <locale.h>
+#include <string.h>
+#include <time.h>
+#include <tzfile.h>
+
+/* #define	_ctloc(x)		(_CurrentTimeLocale->x) */
+
+/*
+ * We do not implement alternate representations. However, we always
+ * check whether a given modifier is allowed for a certain conversion.
+ */
+#define _ALT_E			0x01
+#define _ALT_O			0x02
+#define	_LEGAL_ALT(x)		{ if (alt_format & ~(x)) return (0); }
+
+
+static	int _conv_num(const unsigned char **, int *, int, int);
+static	char *_strptime(const char *, const char *, struct tm *, int);
+
+
+char *
+strptime(const char *buf, const char *fmt, struct tm *tm)
+{
+	return(_strptime(buf, fmt, tm, 1));
+}
+
+static char *
+_strptime(const char *buf, const char *fmt, struct tm *tm, int initialize)
+{
+	unsigned char c;
+	const unsigned char *bp;
+	size_t len;
+	int alt_format, i;
+	static int century, relyear;
+
+	if (initialize) {
+		century = TM_YEAR_BASE;
+		relyear = -1;
+	}
+
+	bp = (unsigned char *)buf;
+	while ((c = *fmt) != '\0') {
+		/* Clear `alternate' modifier prior to new conversion. */
+		alt_format = 0;
+
+		/* Eat up white-space. */
+		if (isspace(c)) {
+			while (isspace(*bp))
+				bp++;
+
+			fmt++;
+			continue;
+		}
+				
+		if ((c = *fmt++) != '%')
+			goto literal;
+
+
+again:		switch (c = *fmt++) {
+		case '%':	/* "%%" is converted to "%". */
+literal:
+		if (c != *bp++)
+			return (NULL);
+
+		break;
+
+		/*
+		 * "Alternative" modifiers. Just set the appropriate flag
+		 * and start over again.
+		 */
+		case 'E':	/* "%E?" alternative conversion modifier. */
+			_LEGAL_ALT(0);
+			alt_format |= _ALT_E;
+			goto again;
+
+		case 'O':	/* "%O?" alternative conversion modifier. */
+			_LEGAL_ALT(0);
+			alt_format |= _ALT_O;
+			goto again;
+			
+		/*
+		 * "Complex" conversion rules, implemented through recursion.
+		 */
+#if 0
+		case 'c':	/* Date and time, using the locale's format. */
+			_LEGAL_ALT(_ALT_E);
+			if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
+				return (NULL);
+			break;
+#endif
+		case 'D':	/* The date as "%m/%d/%y". */
+			_LEGAL_ALT(0);
+			if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
+				return (NULL);
+			break;
+	
+		case 'R':	/* The time as "%H:%M". */
+			_LEGAL_ALT(0);
+			if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
+				return (NULL);
+			break;
+
+		case 'r':	/* The time as "%I:%M:%S %p". */
+			_LEGAL_ALT(0);
+			if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
+				return (NULL);
+			break;
+
+		case 'T':	/* The time as "%H:%M:%S". */
+			_LEGAL_ALT(0);
+			if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
+				return (NULL);
+			break;
+#if 0
+		case 'X':	/* The time, using the locale's format. */
+			_LEGAL_ALT(_ALT_E);
+			if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
+				return (NULL);
+			break;
+
+		case 'x':	/* The date, using the locale's format. */
+			_LEGAL_ALT(_ALT_E);
+			if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
+				return (NULL);
+			break;
+#endif
+		/*
+		 * "Elementary" conversion rules.
+		 */
+#if 0
+		case 'A':	/* The day of week, using the locale's form. */
+		case 'a':
+			_LEGAL_ALT(0);
+			for (i = 0; i < 7; i++) {
+				/* Full name. */
+				len = strlen(_ctloc(day[i]));
+				if (strncasecmp(_ctloc(day[i]), bp, len) == 0)
+					break;
+
+				/* Abbreviated name. */
+				len = strlen(_ctloc(abday[i]));
+				if (strncasecmp(_ctloc(abday[i]), bp, len) == 0)
+					break;
+			}
+
+			/* Nothing matched. */
+			if (i == 7)
+				return (NULL);
+
+			tm->tm_wday = i;
+			bp += len;
+			break;
+
+		case 'B':	/* The month, using the locale's form. */
+		case 'b':
+		case 'h':
+			_LEGAL_ALT(0);
+			for (i = 0; i < 12; i++) {
+				/* Full name. */
+				len = strlen(_ctloc(mon[i]));
+				if (strncasecmp(_ctloc(mon[i]), bp, len) == 0)
+					break;
+
+				/* Abbreviated name. */
+				len = strlen(_ctloc(abmon[i]));
+				if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0)
+					break;
+			}
+
+			/* Nothing matched. */
+			if (i == 12)
+				return (NULL);
+
+			tm->tm_mon = i;
+			bp += len;
+			break;
+#endif
+
+		case 'C':	/* The century number. */
+			_LEGAL_ALT(_ALT_E);
+			if (!(_conv_num(&bp, &i, 0, 99)))
+				return (NULL);
+
+			century = i * 100;
+			break;
+
+		case 'd':	/* The day of month. */
+		case 'e':
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
+				return (NULL);
+			break;
+
+		case 'k':	/* The hour (24-hour clock representation). */
+			_LEGAL_ALT(0);
+			/* FALLTHROUGH */
+		case 'H':
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
+				return (NULL);
+			break;
+
+		case 'l':	/* The hour (12-hour clock representation). */
+			_LEGAL_ALT(0);
+			/* FALLTHROUGH */
+		case 'I':
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
+				return (NULL);
+			break;
+
+		case 'j':	/* The day of year. */
+			_LEGAL_ALT(0);
+			if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
+				return (NULL);
+			tm->tm_yday--;
+			break;
+
+		case 'M':	/* The minute. */
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
+				return (NULL);
+			break;
+
+		case 'm':	/* The month. */
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
+				return (NULL);
+			tm->tm_mon--;
+			break;
+
+#if 0
+		case 'p':	/* The locale's equivalent of AM/PM. */
+			_LEGAL_ALT(0);
+			/* AM? */
+			len = strlen(_ctloc(am_pm[0]));
+			if (strncasecmp(_ctloc(am_pm[0]), bp, len) == 0) {
+				if (tm->tm_hour > 12)	/* i.e., 13:00 AM ?! */
+					return (NULL);
+				else if (tm->tm_hour == 12)
+					tm->tm_hour = 0;
+
+				bp += len;
+				break;
+			}
+			/* PM? */
+			len = strlen(_ctloc(am_pm[1]));
+			if (strncasecmp(_ctloc(am_pm[1]), bp, len) == 0) {
+				if (tm->tm_hour > 12)	/* i.e., 13:00 PM ?! */
+					return (NULL);
+				else if (tm->tm_hour < 12)
+					tm->tm_hour += 12;
+
+				bp += len;
+				break;
+			}
+
+			/* Nothing matched. */
+			return (NULL);
+#endif
+		case 'S':	/* The seconds. */
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_sec, 0, 61)))
+				return (NULL);
+			break;
+
+		case 'U':	/* The week of year, beginning on sunday. */
+		case 'W':	/* The week of year, beginning on monday. */
+			_LEGAL_ALT(_ALT_O);
+			/*
+			 * XXX This is bogus, as we can not assume any valid
+			 * information present in the tm structure at this
+			 * point to calculate a real value, so just check the
+			 * range for now.
+			 */
+			 if (!(_conv_num(&bp, &i, 0, 53)))
+				return (NULL);
+			 break;
+
+		case 'w':	/* The day of week, beginning on sunday. */
+			_LEGAL_ALT(_ALT_O);
+			if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
+				return (NULL);
+			break;
+
+		case 'Y':	/* The year. */
+			_LEGAL_ALT(_ALT_E);
+			if (!(_conv_num(&bp, &i, 0, 9999)))
+				return (NULL);
+
+			relyear = -1;
+			tm->tm_year = i - TM_YEAR_BASE;
+			break;
+
+		case 'y':	/* The year within the century (2 digits). */
+			_LEGAL_ALT(_ALT_E | _ALT_O);
+			if (!(_conv_num(&bp, &relyear, 0, 99)))
+				return (NULL);
+			break;
+
+		/*
+		 * Miscellaneous conversions.
+		 */
+		case 'n':	/* Any kind of white-space. */
+		case 't':
+			_LEGAL_ALT(0);
+			while (isspace(*bp))
+				bp++;
+			break;
+
+
+		default:	/* Unknown/unsupported conversion. */
+			return (NULL);
+		}
+
+
+	}
+
+	/*
+	 * We need to evaluate the two digit year spec (%y)
+	 * last as we can get a century spec (%C) at any time.
+	 */
+	if (relyear != -1) {
+		if (century == TM_YEAR_BASE) {
+			if (relyear <= 68)
+				tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
+			else
+				tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
+		} else {
+			tm->tm_year = relyear + century - TM_YEAR_BASE;
+		}
+	}
+
+	return ((char *)bp);
+}
+
+
+static int
+_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
+{
+	int result = 0;
+	int rulim = ulim;
+
+	if (**buf < '0' || **buf > '9')
+		return (0);
+
+	/* we use rulim to break out of the loop when we run out of digits */
+	do {
+		result *= 10;
+		result += *(*buf)++ - '0';
+		rulim /= 10;
+	} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+
+	if (result < llim || result > ulim)
+		return (0);
+
+	*dest = result;
+	return (1);
+}
+
+#endif /* HAVE_STRPTIME */
+


More information about the openssh-unix-dev mailing list