2 Unix SMB/CIFS implementation.
4 Functions to create reasonable random numbers for crypto use.
6 Copyright (C) Jeremy Allison 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/locale.h"
27 * @brief Random number generation
31 generate a single random uint32_t
33 _PUBLIC_
uint32_t generate_random(void)
36 generate_random_buffer(v
, 4);
42 Microsoft composed the following rules (among others) for quality
43 checks. This is an abridgment from
44 http://msdn.microsoft.com/en-us/subscriptions/cc786468%28v=ws.10%29.aspx:
46 Passwords must contain characters from three of the following five
49 - Uppercase characters of European languages (A through Z, with
50 diacritic marks, Greek and Cyrillic characters)
51 - Lowercase characters of European languages (a through z, sharp-s,
52 with diacritic marks, Greek and Cyrillic characters)
53 - Base 10 digits (0 through 9)
54 - Nonalphanumeric characters: ~!@#$%^&*_-+=`|\(){}[]:;"'<>,.?/
55 - Any Unicode character that is categorized as an alphabetic character
56 but is not uppercase or lowercase. This includes Unicode characters
59 Note: for now do not check if the unicode category is
62 _PUBLIC_
bool check_password_quality(const char *pwd
)
66 size_t num_digits
= 0;
69 size_t num_nonalpha
= 0;
70 size_t num_unicode
= 0;
71 size_t num_categories
= 0;
78 const char *s
= &pwd
[ofs
];
82 c
= next_codepoint(s
, &len
);
83 if (c
== INVALID_CODEPOINT
) {
92 const char *na
= "~!@#$%^&*_-+=`|\\(){}[]:;\"'<>,.?/";
115 * the rest does not belong to
132 * Note: for now do not check if the unicode category is
133 * alphabetic character
135 * We would have to import the details from
136 * ftp://ftp.unicode.org/Public/6.3.0/ucd/UnicodeData-6.3.0d1.txt
142 if (num_digits
> 0) {
151 if (num_nonalpha
> 0) {
154 if (num_unicode
> 0) {
158 if (num_categories
>= 3) {
166 Use the random number generator to generate a random string.
169 _PUBLIC_
char *generate_random_str_list(TALLOC_CTX
*mem_ctx
, size_t len
, const char *list
)
172 size_t list_len
= strlen(list
);
174 char *retstr
= talloc_array(mem_ctx
, char, len
+ 1);
175 if (!retstr
) return NULL
;
177 generate_random_buffer((uint8_t *)retstr
, len
);
178 for (i
= 0; i
< len
; i
++) {
179 retstr
[i
] = list
[retstr
[i
] % list_len
];
187 * Generate a random text string consisting of the specified length.
188 * The returned string will be allocated.
190 * Characters used are: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,
193 _PUBLIC_
char *generate_random_str(TALLOC_CTX
*mem_ctx
, size_t len
)
196 const char *c_list
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,";
199 retstr
= generate_random_str_list(mem_ctx
, len
, c_list
);
200 if (!retstr
) return NULL
;
202 /* we need to make sure the random string passes basic quality tests
203 or it might be rejected by windows as a password */
204 if (len
>= 7 && !check_password_quality(retstr
)) {
213 * Generate a random text password.
216 _PUBLIC_
char *generate_random_password(TALLOC_CTX
*mem_ctx
, size_t min
, size_t max
)
219 /* This list does not include { or } because they cause
220 * problems for our provision (it can create a substring
221 * ${...}, and for Fedora DS (which treats {...} at the start
222 * of a stored password as special
223 * -- Andrew Bartlett 2010-03-11
225 const char *c_list
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,@$%&!?:;<=>()[]~";
239 generate_random_buffer((uint8_t *)&tmp
, sizeof(tmp
));
247 retstr
= generate_random_str_list(mem_ctx
, len
, c_list
);
248 if (!retstr
) return NULL
;
250 /* we need to make sure the random string passes basic quality tests
251 or it might be rejected by windows as a password */
252 if (len
>= 7 && !check_password_quality(retstr
)) {
261 * Generate an array of unique text strings all of the same length.
262 * The returned string will be allocated.
263 * Returns NULL if the number of unique combinations cannot be created.
265 * Characters used are: abcdefghijklmnopqrstuvwxyz0123456789+_-#.,
267 _PUBLIC_
char** generate_unique_strs(TALLOC_CTX
*mem_ctx
, size_t len
,
270 const char *c_list
= "abcdefghijklmnopqrstuvwxyz0123456789+_-#.,";
271 const unsigned c_size
= 42;
276 if (num
== 0 || len
== 0)
279 strs
= talloc_array(mem_ctx
, char *, num
);
280 if (strs
== NULL
) return NULL
;
282 for (i
= 0; i
< num
; i
++) {
283 char *retstr
= (char *)talloc_size(strs
, len
+ 1);
284 if (retstr
== NULL
) {
289 for (j
= 0; j
< len
; j
++) {
290 retstr
[j
] = c_list
[rem
% c_size
];
296 /* we were not able to fit the number of
297 * combinations asked for in the length
299 DEBUG(0,(__location__
": Too many combinations %u for length %u\n",
300 num
, (unsigned)len
));