ietf-nntp Millenium Bug in Stan Barber's NNTP Reference server

Charles Lindsey chl at clw.cs.man.ac.uk
Sun Jan 2 14:43:37 PST 2000


This will probably affect a lot of CNEWS sites that have clients using
the NEWNEWS command.

The fix below is not thoroughly tested, but is the best that can be
managed on January 2nd.

It would also seem that INN (at least version 1.7.2) does not understand
dates of the form YYYYMMDD, though it seems at first sight to do the
right thing with 000101.

*** date.c.orig	Tue Nov  1 06:08:41 1994
--- date.c	Sun Jan  2 21:26:58 2000
***************
*** 58,75 ****
      { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  
  long
! dtol(date_ascii)
  	char	*date_ascii;
  {
  	char	date[32], *date_str;
  	char	*lhs, *rhs;
  	char	temp;
  	long	seconds;
! 	int	year, month, day, hour, mins, secs;
  	int	len, i;
  
  	len = strlen(date_ascii);
! 	if (len != sizeof("yymmddhhmmss")-1)
  		return (-1);
  
  	(void) strcpy(date, date_ascii);
--- 58,77 ----
      { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  
  long
! dtol(date_ascii, local)
  	char	*date_ascii;
+ 	int	local;
  {
  	char	date[32], *date_str;
  	char	*lhs, *rhs;
  	char	temp;
  	long	seconds;
! 	int	century, year, month, day, hour, mins, secs;
  	int	len, i;
  
  	len = strlen(date_ascii);
! 	if (len != sizeof("yymmddhhmmss")-1 
! 	    && len != sizeof("yyyymmddhhmmss")-1)
  		return (-1);
  
  	(void) strcpy(date, date_ascii);
***************
*** 107,113 ****
--- 109,138 ----
  	month = twodigtoi(lhs);
  	lhs += 2;
  	year = twodigtoi(lhs);
+ 	lhs += 2;
+ 	if (*lhs != NULL)
+ 	    century = twodigtoi(lhs) * 100;
+ 	else {
+ 	    struct tm	*gmt;
+ #ifdef USG
+ 	    time_t		now;
  
+ 	    (void) time(&now);
+ 	    gmt = local ? localtime(&now) : gmtime(&now);
+ #else /* not USG */
+ 	    struct timeval	now;
+ 
+ 	    (void) gettimeofday(&now, (struct timezone *)NULL);
+ 	    gmt = local ? localtime(&now.tv_sec) : gmtime(&now.tv_sec);
+ #endif /* not USG */
+ 	    if (gmt->tm_year % 100 >= year)
+ 		century = (gmt->tm_year / 100 +19) * 100;
+ 	    else
+ 		century = (gmt->tm_year / 100 +18) * 100;
+ 	/* all of which is quite correct, but a waste of time,
+ 	   because it will break again in 2038 :-( */
+ 	}
+ 
  	if (month < 1 || month > 12 ||
  	    day < 1 || day > 31 ||
  	    mins < 0 || mins > 59 ||
***************
*** 120,126 ****
  	if (hour < 0 || hour > 23)
  		return (-1);
  	seconds = 0;
! 	year += 1900;
  	for (i = 1970; i < year; i++)
  		seconds += dysize(i);
  	/* Leap year */
--- 145,151 ----
  	if (hour < 0 || hour > 23)
  		return (-1);
  	seconds = 0;
! 	year += century;
  	for (i = 1970; i < year; i++)
  		seconds += dysize(i);
  	/* Leap year */
***************
*** 144,150 ****
   *				since the epoch.
   *
   *	Returns:		Pointer to static data in the form
!  *				yymmddhhmmss\0.
   *
   *	Side effects:		None.
   */
--- 169,175 ----
   *				since the epoch.
   *
   *	Returns:		Pointer to static data in the form
!  *				yyyymmddhhmmss\0.
   *
   *	Side effects:		None.
   */
***************
*** 158,165 ****
  
  	tp = gmtime(&date);
  
! 	(void) sprintf(timebuf, "%02d%02d%02d%02d%02d%02d",
! 		tp->tm_year,
  		tp->tm_mon + 1,		/* 0 to 11??? How silly. */
  		tp->tm_mday,
  		tp->tm_hour,
--- 183,190 ----
  
  	tp = gmtime(&date);
  
! 	(void) sprintf(timebuf, "%04d%02d%02d%02d%02d%02d",
! 		tp->tm_year + 1900,
  		tp->tm_mon + 1,		/* 0 to 11??? How silly. */
  		tp->tm_mday,
  		tp->tm_hour,
*** newgroups.c.orig	Sun Jan  2 16:58:08 2000
--- newgroups.c	Sun Jan  2 20:55:19 2000
***************
*** 27,33 ****
  	char		*reqlist[2];
  
  	if (argc < 3) {
! printf("%d Usage: NEWGROUPS yymmdd hhmmss [\"GMT\"] [<distributions>].\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
--- 27,33 ----
  	char		*reqlist[2];
  
  	if (argc < 3) {
! printf("%d Usage: NEWGROUPS [yy]yymmdd hhmmss [\"GMT\"] 
[<distributions>].\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
***************
*** 43,51 ****
  		return;
  	}
  
! 	/*	    YYMMDD		    HHMMSS	*/
! 	if (strlen(argv[1]) != 6 || strlen(argv[2]) != 6) {
! 		printf("%d Date/time must be in form YYMMDD HHMMSS.\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		(void) fclose(date_fp);
--- 43,52 ----
  		return;
  	}
  
! 	/*	    [YY]YYMMDD		    HHMMSS	*/
! 	if ((strlen(argv[1]) != 6 && strlen(argv[1]) != 8)
! 	    || strlen(argv[2]) != 6) {
! 		printf("%d Date/time must be in form [YY]YYMMDD HHMMSS.\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		(void) fclose(date_fp);
***************
*** 52,76 ****
  		return;
  	}
  
! 	(void) strcpy(line, argv[1]);			/* yymmdd */
  	(void) strcat(line, argv[2]);			/* hhmmss */
  
- 	date = dtol(line);
- 	if (date < 0) {
- 		printf("%d Invalid date specification.\r\n", ERR_CMDSYN);
- 		(void) fflush(stdout);
- 		(void) fclose(date_fp);
- 		return;
- 	}
- 
  	argc -= 3;
  	argv += 3;
  
  	if (argc > 0 && !strcasecmp(*argv, "GMT")) { /* We store stuff in GMT */
  		++argv;				/* anyway, so this is */
  		--argc;				/* a "noop" */
! 	} else 					/* But that means not GMT */
  		date = local_to_gmt(date);	/* is a definite "op" */
  
  	if (argc > 0) {
  		distcount = get_distlist(&dist_list, *argv);
--- 53,78 ----
  		return;
  	}
  
! 	(void) strcpy(line, argv[1]);			/* [yy]yymmdd */
  	(void) strcat(line, argv[2]);			/* hhmmss */
  
  	argc -= 3;
  	argv += 3;
  
  	if (argc > 0 && !strcasecmp(*argv, "GMT")) { /* We store stuff in GMT */
+ 		date = dtol(line, 0);
  		++argv;				/* anyway, so this is */
  		--argc;				/* a "noop" */
! 	} else {				/* But that means not GMT */
! 		date = dtol(line, 1);
  		date = local_to_gmt(date);	/* is a definite "op" */
+ 	}
+ 	if (date < 0) {
+ 		printf("%d Invalid date specification.\r\n", ERR_CMDSYN);
+ 		(void) fflush(stdout);
+ 		(void) fclose(date_fp);
+ 		return;
+ 	}
  
  	if (argc > 0) {
  		distcount = get_distlist(&dist_list, *argv);
*** newnews.c.orig	Sun Jan  2 16:58:37 2000
--- newnews.c	Sun Jan  2 17:00:12 2000
***************
*** 43,49 ****
  #endif
  
  	if (argc < 4) {
! 		printf("%d Usage: NEWNEWS newsgroups yymmdd hhmmss [\"GMT\"] 
[<distributions>].\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
--- 43,49 ----
  #endif
  
  	if (argc < 4) {
! 		printf("%d Usage: NEWNEWS newsgroups [yy]yymmdd hhmmss [\"GMT\"] 
[<distributions>].\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
***************
*** 78,86 ****
  		}
  	}
  
! 	/*	    YYMMDD		    HHMMSS	*/
! 	if (strlen(argv[2]) != 6 || strlen(argv[3]) != 6) {
! 		printf("%d Date/time must be in form YYMMDD HHMMSS.\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
--- 78,87 ----
  		}
  	}
  
! 	/*	    [YY]YYMMDD		    HHMMSS	*/
! 	if ((strlen(argv[2]) != 6 && strlen(argv[2]) != 8)
! 	    || strlen(argv[3]) != 6) {
! 		printf("%d Date/time must be in form [YY]YYMMDD HHMMSS.\r\n",
  			ERR_CMDSYN);
  		(void) fflush(stdout);
  		return;
***************
*** 92,99 ****
  	argc -= 4;
  	argv += 4;
  
! 	key = datebuf;		/* Unless they specify GMT */
! 	date = dtol(datebuf);
  	if (date < 0) {
  		printf("%d Invalid date specification.\r\n",ERR_CMDSYN);
  		(void) fflush(stdout);
--- 93,106 ----
  	argc -= 4;
  	argv += 4;
  
! 	if (argc > 0 && !strcasecmp(*argv, "GMT")) { /* Which we handle here */
! 		date = dtol(datebuf, 0);
! 		date = gmt_to_local(date);
! 		++argv;
! 		--argc;
! 	} else {
! 		date = dtol(datebuf, 1);
! 	}
  	if (date < 0) {
  		printf("%d Invalid date specification.\r\n",ERR_CMDSYN);
  		(void) fflush(stdout);
***************
*** 100,116 ****
  		return;
  	}
  
- 	if (argc > 0) {
- 		if (!strcasecmp(*argv, "GMT")) { /* Which we handle here */
- 			date = gmt_to_local(date);
- 			++argv;
- 			--argc;
- 		}
- 	}
  	/* now we convert from local to GMT since this is what history */
  	/* file in News 2.11 expects */
  	date = local_to_gmt(date);
  	strcpy(datebuf,ltod(date));	
  	distcount = 0;
  	if (argc > 0) {
  		distcount = get_distlist(&distlist, *argv);
--- 107,117 ----
  		return;
  	}
  
  	/* now we convert from local to GMT since this is what history */
  	/* file in News 2.11 expects */
  	date = local_to_gmt(date);
  	strcpy(datebuf,ltod(date));	
+ 	key = datebuf;
  	distcount = 0;
  	if (argc > 0) {
  		distcount = get_distlist(&distlist, *argv);
***************
*** 240,247 ****
   * seekuntil -- seek through the history file looking for
   * a line with date later than "akey".  Get that line, and return.
   *
!  *	Parameters:	"fp" is the active file.
!  *			"akey" is the date, in form YYMMDDHHMMSS
   *			"line" is storage for the first line we find.
   *
   *	Returns:	-1 on error, 0 otherwise.
--- 241,248 ----
   * seekuntil -- seek through the history file looking for
   * a line with date later than "akey".  Get that line, and return.
   *
!  *	Parameters:	"fp" is the history file.
!  *			"akey" is the date, in form YYYYMMDDHHMMSS
   *			"line" is storage for the first line we find.
   *
   *	Returns:	-1 on error, 0 otherwise.
***************
*** 362,367 ****
--- 363,374 ----
   * yymmddhhmm		(our good one)
   * 0123456789		("x" for w[x])
   */
+ 
+ /* But it would seem that BNEWS is now totally broke for this millennium,
+  * so no attempt to patch this code has been made, except to say:
+  */
+ 		    return (-1);
+ 
  		    w[0] = cp[6];		/* Years */
  		    w[1] = cp[7];
  		    w[2] = cp[0];		/* Months */
***************
*** 374,380 ****
  		    w[9] = cp[13];
  		    w[10] = '\0';
  		}
! 	    else	/* convert new format to yymmddhhmmss */
  		{
  		    long qz;
  		    qz =atol(w);
--- 381,387 ----
  		    w[9] = cp[13];
  		    w[10] = '\0';
  		}
! 	    else	/* convert new format to yyyymmddhhmmss */
  		{
  		    long qz;
  		    qz =atol(w);




Charles H. Lindsey ---------At Home, doing my own thing------------------------
Email:     chl at clw.cs.man.ac.uk  Web:   http://www.cs.man.ac.uk/~chl
Voice/Fax: +44 161 437 4506      Snail: 5 Clerewood Ave, CHEADLE, SK8 3JU, U.K.
PGP: 2C15F1A9     Fingerprint: 73 6D C2 51 93 A0 01 E7  65 E8 64 7E 14 A4 AB A5




More information about the ietf-nntp mailing list