components/pwgen/patches/03-fix_CVEs-2013-4440-4443.patch
branchs11-update
changeset 3027 3bcf7d43558b
equal deleted inserted replaced
3026:1c0f96780b0e 3027:3bcf7d43558b
       
     1 Developed by community.
       
     2 http://marc.info/?l=oss-security&m=137049241132104&w=4
       
     3 Fix following CVEs:
       
     4 CVE-2013-4440, CVE-2013-4441, CVE-2013-4442, CVE-2013-4443
       
     5 with an exception of number bias in short passwords (won't be fixed,
       
     6 it's a feature)
       
     7 
       
     8 --- pwgen-2.06/configure.in	2007-07-05 09:42:19.000000000 +1000
       
     9 +++ pwgen-2.06-mik/configure.in	2013-05-27 16:48:46.399195554 +1000
       
    10 @@ -6,7 +6,7 @@
       
    11  AC_PATH_PROG(RM, rm, rm)
       
    12  AC_PATH_PROG(SED, sed, sed)
       
    13  AC_PATH_PROG(PERL, perl, perl)
       
    14 -AC_CHECK_FUNCS(drand48 getopt_long)
       
    15 +AC_CHECK_FUNCS(getopt_long)
       
    16  AC_CHECK_HEADERS(getopt.h)
       
    17  pwgen_sha="internal"
       
    18  SHA_OBJ=""
       
    19 --- pwgen-2.06/debian/control	2013-06-06 09:57:01.000000000 +1000
       
    20 +++ pwgen-2.06-mik/debian/control	2013-06-06 10:05:44.315608968 +1000
       
    21 @@ -8,6 +8,7 @@
       
    22  Package: pwgen
       
    23  Architecture: any
       
    24  Depends: ${shlibs:Depends}
       
    25 +Suggests: passwdqc
       
    26  Description: Automatic Password generation
       
    27   pwgen generates random, meaningless but pronounceable passwords.
       
    28   These passwords contain either only lowercase letters, or upper
       
    29 --- pwgen-2.06/pwgen.c	2013-06-06 09:57:01.000000000 +1000
       
    30 +++ pwgen-2.06-mik/pwgen.c	2013-06-06 13:50:19.541188659 +1000
       
    31 @@ -25,7 +25,7 @@
       
    32  
       
    33  int	pw_length = 8;
       
    34  int	num_pw = -1;
       
    35 -int	pwgen_flags = 0;
       
    36 +int	pwgen_flags = PW_LOWERS | PW_UPPERS | PW_DIGITS;
       
    37  int	do_columns = 0;
       
    38  
       
    39  #ifdef HAVE_GETOPT_LONG
       
    40 @@ -42,11 +42,12 @@
       
    41  	{ "sha1", required_argument, 0, 'H' },
       
    42  	{ "ambiguous", no_argument, 0, 'B' },
       
    43  	{ "no-vowels", no_argument, 0, 'v' },
       
    44 +	{ "insecure-phonemes", no_argument, 0, 'P' },
       
    45  	{ 0, 0, 0, 0}
       
    46  };
       
    47  #endif
       
    48  
       
    49 -const char *pw_options = "01AaBCcnN:shH:vy";
       
    50 +const char *pw_options = "01AaBCcnN:shH:vyP";
       
    51  
       
    52  static void usage(void)
       
    53  {
       
    54 @@ -82,6 +83,8 @@
       
    55  	fputs("  -v or --no-vowels\n", stderr);
       
    56  	fputs("\tDo not use any vowels so as to avoid accidental nasty words\n",
       
    57  	      stderr);
       
    58 +	fputs("  -P or --insecure-phonemes\n", stderr);
       
    59 +	fputs("\tGenerate insecure phonemes, as was previously the default\n", stderr);
       
    60  	exit(1);
       
    61  }
       
    62  
       
    63 @@ -94,11 +97,10 @@
       
    64  	char	*buf, *tmp;
       
    65  	void	(*pwgen)(char *inbuf, int size, int pw_flags);
       
    66  
       
    67 -	pwgen = pw_phonemes;
       
    68 +	pwgen = pw_rand;
       
    69  	pw_number = pw_random_number;
       
    70  	if (isatty(1)) {
       
    71  		do_columns = 1;
       
    72 -		pwgen_flags |= PW_DIGITS | PW_UPPERS;
       
    73  	}
       
    74  
       
    75  	while (1) {
       
    76 @@ -140,6 +144,9 @@
       
    77  			pwgen = pw_rand;
       
    78  			pwgen_flags = PW_DIGITS | PW_UPPERS;
       
    79  			break;
       
    80 +		case 'P':
       
    81 +			pwgen = pw_phonemes;
       
    82 +			break;
       
    83  		case 'C':
       
    84  			do_columns = 1;
       
    85  			break;
       
    86 --- pwgen-2.06/pwgen.h	2007-07-05 09:42:19.000000000 +1000
       
    87 +++ pwgen-2.06-mik/pwgen.h	2013-06-06 10:08:42.186709620 +1000
       
    88 @@ -28,6 +28,7 @@
       
    89  #define PW_SYMBOLS	0x0004
       
    90  #define PW_AMBIGUOUS	0x0008
       
    91  #define PW_NO_VOWELS	0x0010
       
    92 +#define PW_LOWERS	0x0020  /* At least one lowercase! */
       
    93  
       
    94  /* pointer to choose between random or sha1 pseudo random number generator */
       
    95  extern int (*pw_number)(int max_num);
       
    96 --- pwgen-2.06/pw_rand.c	2007-07-05 09:42:19.000000000 +1000
       
    97 +++ pwgen-2.06-mik/pw_rand.c	2013-06-06 13:51:38.948600125 +1000
       
    98 @@ -72,10 +72,12 @@
       
    99  			feature_flags &= ~PW_UPPERS;
       
   100  		if (strchr(pw_symbols, ch))
       
   101  			feature_flags &= ~PW_SYMBOLS;
       
   102 +		if (strchr(pw_lowers, ch))
       
   103 +			feature_flags &= ~PW_LOWERS;
       
   104  	}
       
   105 -	if (feature_flags & (PW_UPPERS | PW_DIGITS | PW_SYMBOLS))
       
   106 +	if (feature_flags & (PW_UPPERS | PW_DIGITS | PW_SYMBOLS | PW_LOWERS))
       
   107  		goto try_again;
       
   108  	buf[size] = 0;
       
   109  	free(chars);
       
   110  	return;
       
   111 -}	
       
   112 +}
       
   113 --- pwgen-2.06/randnum.c	2007-07-05 09:42:19.000000000 +1000
       
   114 +++ pwgen-2.06-mik/randnum.c	2013-06-06 10:00:23.149212710 +1000
       
   115 @@ -7,53 +7,45 @@
       
   116   * License.
       
   117   */
       
   118  
       
   119 +#include <stdio.h>
       
   120 +#include <string.h>
       
   121  #include <unistd.h>
       
   122  #include <stdlib.h>
       
   123  #include <sys/types.h>
       
   124 -#include <sys/time.h>
       
   125  #include <sys/stat.h>
       
   126  #include <fcntl.h>
       
   127  #include <errno.h>
       
   128  
       
   129  #include "pwgen.h"
       
   130  
       
   131 -#ifdef HAVE_DRAND48
       
   132 -extern double drand48(void);
       
   133 -#endif
       
   134 -
       
   135  static int get_random_fd(void);
       
   136  
       
   137  /* Borrowed/adapted from e2fsprogs's UUID generation code */
       
   138  static int get_random_fd()
       
   139  {
       
   140 -	struct timeval	tv;
       
   141 -	static int	fd = -2;
       
   142 -	int		i;
       
   143 +	static int fd = -2;
       
   144  
       
   145 -	if (fd == -2) {
       
   146 -		gettimeofday(&tv, 0);
       
   147 +	if(fd == -2) {
       
   148  		fd = open("/dev/urandom", O_RDONLY);
       
   149 -		if (fd == -1)
       
   150 -			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
       
   151 -#ifdef HAVE_DRAND48
       
   152 -		srand48((tv.tv_sec<<9) ^ (getpgrp()<<15) ^
       
   153 -			(getpid()) ^ (tv.tv_usec>>11));
       
   154 -#else
       
   155 -		srandom((getpid() << 16) ^ (getpgrp() << 8) ^ getuid() 
       
   156 -		      ^ tv.tv_sec ^ tv.tv_usec);
       
   157 -#endif
       
   158 +		if (fd == -1) {
       
   159 +			fprintf(stderr, "Unable to open /dev/urandom: %s\n", strerror(errno));
       
   160 +			abort();
       
   161 +		}
       
   162  	}
       
   163 -	/* Crank the random number generator a few times */
       
   164 -	gettimeofday(&tv, 0);
       
   165 -	for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
       
   166 -#ifdef HAVE_DRAND48
       
   167 -		drand48();
       
   168 -#else
       
   169 -		random();
       
   170 -#endif
       
   171  	return fd;
       
   172  }
       
   173  
       
   174 +static unsigned int get_mask(int max_num)
       
   175 +{
       
   176 +	unsigned int numBits = 0;
       
   177 +	while(max_num > 0)
       
   178 +	{
       
   179 +		numBits++;
       
   180 +		max_num >>= 1;
       
   181 +	}
       
   182 +	return (1<<numBits) - 1;
       
   183 +}
       
   184 +
       
   185  /*
       
   186   * Generate a random number n, where 0 <= n < max_num, using
       
   187   * /dev/urandom if possible.
       
   188 @@ -62,34 +54,20 @@
       
   189  	int max_num;
       
   190  {
       
   191  	int i, fd = get_random_fd();
       
   192 -	int lose_counter = 0, nbytes=4;
       
   193  	unsigned int rand_num;
       
   194 -	char *cp = (char *) &rand_num;
       
   195  
       
   196 -	if (fd >= 0) {
       
   197 -		while (nbytes > 0) {
       
   198 -			i = read(fd, cp, nbytes);
       
   199 -			if ((i < 0) &&
       
   200 -			    ((errno == EINTR) || (errno == EAGAIN)))
       
   201 -				continue;
       
   202 -			if (i <= 0) {
       
   203 -				if (lose_counter++ == 8)
       
   204 -					break;
       
   205 -				continue;
       
   206 -			}
       
   207 -			nbytes -= i;
       
   208 -			cp += i;
       
   209 -			lose_counter = 0;
       
   210 -		}
       
   211 +	i = read(fd, (void *)&rand_num, sizeof(rand_num));
       
   212 +	if(i < 0) {
       
   213 +		fprintf(stderr, "Error reading from /dev/urandom: %s\n", strerror(errno));
       
   214 +		abort();
       
   215  	}
       
   216 -	if (nbytes == 0)
       
   217 -		return (rand_num % max_num);
       
   218  
       
   219 -	/* OK, we weren't able to use /dev/random, fall back to rand/rand48 */
       
   220 +        rand_num &= get_mask(max_num);
       
   221  
       
   222 -#ifdef HAVE_DRAND48
       
   223 -	return ((int) ((drand48() * max_num)));
       
   224 -#else
       
   225 -	return ((int) (random() / ((float) RAND_MAX) * max_num));
       
   226 -#endif
       
   227 +	if(rand_num < max_num) {
       
   228 +		return rand_num;
       
   229 +	}
       
   230 +
       
   231 +	return pw_random_number(max_num); /* tail-recurse */
       
   232  }
       
   233 +