2
* pw_phonemes.c --- generate secure passwords using phoneme rules
4
* Copyright (C) 2001 by Theodore Ts'o
6
* This file may be distributed under the terms of the GNU Public
12
struct pw_element elements[] = {
14
{ "ae", VOWEL | DIPTHONG },
15
{ "ah", VOWEL | DIPTHONG },
16
{ "ai", VOWEL | DIPTHONG },
19
{ "ch", CONSONANT | DIPTHONG },
22
{ "ee", VOWEL | DIPTHONG },
23
{ "ei", VOWEL | DIPTHONG },
26
{ "gh", CONSONANT | DIPTHONG | NOT_FIRST },
29
{ "ie", VOWEL | DIPTHONG },
35
{ "ng", CONSONANT | DIPTHONG | NOT_FIRST },
37
{ "oh", VOWEL | DIPTHONG },
38
{ "oo", VOWEL | DIPTHONG},
40
{ "ph", CONSONANT | DIPTHONG },
41
{ "qu", CONSONANT | DIPTHONG},
44
{ "sh", CONSONANT | DIPTHONG},
46
{ "th", CONSONANT | DIPTHONG},
55
#define NUM_ELEMENTS (sizeof(elements) / sizeof (struct pw_element))
57
void pw_phonemes(char *buf, int size, int pw_flags)
59
int c, i, len, flags, feature_flags;
60
int prev, should_be, first;
64
feature_flags = pw_flags;
70
should_be = pw_random_number(1) ? VOWEL : CONSONANT;
73
i = pw_random_number(NUM_ELEMENTS);
74
str = elements[i].str;
76
flags = elements[i].flags;
77
/* Filter on the basic type of the next element */
78
if ((flags & should_be) == 0)
80
/* Handle the NOT_FIRST flag */
81
if (first && (flags & NOT_FIRST))
83
/* Don't allow VOWEL followed a Vowel/Dipthong pair */
84
if ((prev & VOWEL) && (flags & VOWEL) &&
87
/* Don't allow us to overflow the buffer */
91
* OK, we found an element which matches our criteria,
96
/* Handle PW_ONE_CASE */
97
if (feature_flags & PW_ONE_CASE) {
98
if ((first || flags & CONSONANT) &&
99
(pw_random_number(10) < 3)) {
100
buf[c] = toupper(buf[c]);
101
feature_flags &= ~PW_ONE_CASE;
112
* Handle PW_ONE_NUMBER
114
if (feature_flags & PW_ONE_NUMBER) {
115
if (!first && (pw_random_number(10) < 3)) {
116
buf[c++] = pw_random_number(9)+'0';
118
feature_flags &= ~PW_ONE_NUMBER;
122
should_be = pw_random_number(1) ?
129
* OK, figure out what the next element should be
131
if (should_be == CONSONANT) {
133
} else { /* should_be == VOWEL */
134
if ((prev & VOWEL) ||
135
(flags & DIPTHONG) ||
136
(pw_random_number(10) > 3))
137
should_be = CONSONANT;
144
if (feature_flags & (PW_ONE_CASE | PW_ONE_NUMBER))