View | Details | Raw Unified | Return to bug 31440
Collapse All | Expand All

(-)htpasswd.c (-3 / +67 lines)
Lines 46-51 Link Here
46
#include "ap.h"
46
#include "ap.h"
47
#include "ap_md5.h"
47
#include "ap_md5.h"
48
#include "ap_sha1.h"
48
#include "ap_sha1.h"
49
#include <math.h>
49
50
50
#ifdef HAVE_CRYPT_H
51
#ifdef HAVE_CRYPT_H
51
#include <crypt.h>
52
#include <crypt.h>
Lines 94-99 Link Here
94
static char *tname_buf = NULL;
95
static char *tname_buf = NULL;
95
#endif
96
#endif
96
97
98
FILE *FP = NULL;
99
97
/*
100
/*
98
 * Get a line of input from the user, not including any terminating
101
 * Get a line of input from the user, not including any terminating
99
 * newline.
102
 * newline.
Lines 127-132 Link Here
127
    fputc('\n', f);
130
    fputc('\n', f);
128
}
131
}
129
132
133
 
134
static void seed_prng()
135
{
136
    int randBits = 0;
137
    int seedInt = 0;
138
    int toAdd = 0;
139
    int intSize = (8*(int)sizeof(int));
140
    int charSize = (8*(int)sizeof(char));
141
    if ( (!FP) && getenv("RANDOM_SEED") ) 
142
    {
143
        /* use the device specified by the user */
144
        FP = fopen(getenv("RANDOM_SEED"), "r");
145
    } else if (!FP) {
146
        /* use /dev/urandom for better (less predictable) seeding if available */
147
        FP = fopen("/dev/urandom", "r");
148
    }
149
    if (FP) 
150
    {
151
        while ( randBits < intSize ) {
152
            /* how many bits to read (maximum == bytes in a char) */
153
            toAdd = (intSize - randBits) > charSize ? charSize : (intSize - randBits);
154
            /* we could watch the fgetc() call for EOF and warn the user,
155
               but the user should know better than to provide a small pool */
156
            seedInt += ((int)fgetc(FP) % (int)pow(2,toAdd)) * (int)pow(2,randBits);
157
            randBits += toAdd;
158
        }
159
        (void) srand(seedInt);
160
        /* deliberately leave FP open in case seed_prng() is called again and
161
           FP behaves like a static file and always provides the same content;
162
           with devices like /dev/urandom and /dev/random, there would be bo reason
163
           not to fclose(FP) here */
164
    } else {
165
        fprintf(stderr,"Warning: weak salt generation!\n");
166
        fprintf(stderr,"For better security, install /dev/urandom or provide the name of a file or device\n");
167
        fprintf(stderr,"that can provide enough random data in the environment variable RANDOM_SEED\n",(intSize/8));
168
        (void) srand((int) time((time_t *) NULL));
169
    }
170
}
171
172
static void generate_salt(char *s, size_t size)
173
{
174
   static unsigned char tbl[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
175
   size_t i;
176
   int bitsUsed = 0;
177
   for (i = 0; i < size; ++i) {
178
       int idx = (int) (64.0 * rand() / (RAND_MAX + 1.0));
179
       bitsUsed += 6;
180
       s[i] = tbl[idx];
181
       /* re-seed the PRNG if already used an integer's worth of bytes, or if the next 
182
          loop iteration would use more than an int, since the seed for rand() is an int.
183
          This will only need to happen on platforms with integers less than 48 bits. */
184
       if ( (bitsUsed + 6) > (8*sizeof(int)) )
185
       {
186
           /* re-seed */
187
           (void)seed_prng();
188
           /* reset our counter */
189
           bitsUsed = 0;
190
       }
191
   }
192
}
193
130
/*
194
/*
131
 * Make a password record from the given information.  A zero return
195
 * Make a password record from the given information.  A zero return
132
 * indicates success; failure means that the output buffer contains an
196
 * indicates success; failure means that the output buffer contains an
Lines 171-178 Link Here
171
	break;
235
	break;
172
236
173
    case ALG_APMD5: 
237
    case ALG_APMD5: 
174
        (void) srand((int) time((time_t *) NULL));
238
        (void)seed_prng();
175
        ap_to64(&salt[0], rand(), 8);
239
        generate_salt(&salt[0], 8);
176
        salt[8] = '\0';
240
        salt[8] = '\0';
177
241
178
	ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
242
	ap_MD5Encode((const unsigned char *)pw, (const unsigned char *)salt,
Lines 186-192 Link Here
186
250
187
    case ALG_CRYPT:
251
    case ALG_CRYPT:
188
    default:
252
    default:
189
        (void) srand((int) time((time_t *) NULL));
253
        (void)seed_prng();
190
        ap_to64(&salt[0], rand(), 8);
254
        ap_to64(&salt[0], rand(), 8);
191
        salt[8] = '\0';
255
        salt[8] = '\0';
192
256

Return to bug 31440