Blame


1 926e1c04 2022-12-30 aa_src #include <ctype.h>
2 33d6c58e 2024-11-17 aa #include <err.h>
3 7ab29a2b 2022-09-30 src #include <errno.h>
4 aab4ecb3 2022-07-14 src #include <limits.h>
5 aab4ecb3 2022-07-14 src #include <math.h>
6 aab4ecb3 2022-07-14 src #include <stdarg.h>
7 aab4ecb3 2022-07-14 src #include <stdio.h>
8 7ab29a2b 2022-09-30 src #include <stdlib.h>
9 7ab29a2b 2022-09-30 src #include <string.h>
10 e9952e59 2022-08-21 src #include <strings.h>
11 aab4ecb3 2022-07-14 src #include <unistd.h>
12 aab4ecb3 2022-07-14 src
13 33d6c58e 2024-11-17 aa #define MAXWORDS 32768
14 33d6c58e 2024-11-17 aa #define NNUM ('9'-'0' + 1)
15 33d6c58e 2024-11-17 aa #define NALPHA ('z'-'a' + 1)
16 33d6c58e 2024-11-17 aa
17 aab4ecb3 2022-07-14 src #ifndef PREFIX
18 33d6c58e 2024-11-17 aa # define PREFIX "/usr/local"
19 aab4ecb3 2022-07-14 src #endif
20 aab4ecb3 2022-07-14 src
21 caf30c15 2024-11-17 aa int aflag = 0;
22 aab4ecb3 2022-07-14 src
23 33d6c58e 2024-11-17 aa static int
24 aab4ecb3 2022-07-14 src usage(void)
25 aab4ecb3 2022-07-14 src {
26 d8c0fc7b 2024-11-17 aa fprintf(stderr,
27 d8c0fc7b 2024-11-17 aa "usage: gpass [-a] [-d dict] [-e bits] [-l length] [-n count]\n");
28 aab4ecb3 2022-07-14 src exit(EXIT_FAILURE);
29 aab4ecb3 2022-07-14 src }
30 aab4ecb3 2022-07-14 src
31 33d6c58e 2024-11-17 aa static int
32 33d6c58e 2024-11-17 aa getplen(int n, int ent) {
33 33d6c58e 2024-11-17 aa long temp;
34 33d6c58e 2024-11-17 aa int plen;
35 caf30c15 2024-11-17 aa
36 33d6c58e 2024-11-17 aa temp = log2(n);
37 33d6c58e 2024-11-17 aa plen = ent / temp + !!(ent % temp);
38 33d6c58e 2024-11-17 aa return (plen > 0) ? plen : 1;
39 caf30c15 2024-11-17 aa }
40 caf30c15 2024-11-17 aa
41 33d6c58e 2024-11-17 aa static void
42 33d6c58e 2024-11-17 aa genalpha(int plen, int max)
43 aab4ecb3 2022-07-14 src {
44 33d6c58e 2024-11-17 aa int c;
45 33d6c58e 2024-11-17 aa int left;
46 33d6c58e 2024-11-17 aa uint32_t n;
47 699d07dd 2022-09-30 src
48 926e1c04 2022-12-30 aa_src for (left = plen; left; left--) {
49 33d6c58e 2024-11-17 aa n = arc4random_uniform(max);
50 caf30c15 2024-11-17 aa if (n < NNUM)
51 caf30c15 2024-11-17 aa putchar('0' + n);
52 caf30c15 2024-11-17 aa else if (n < NNUM + NALPHA)
53 caf30c15 2024-11-17 aa putchar('A' + (n - NNUM));
54 caf30c15 2024-11-17 aa else
55 caf30c15 2024-11-17 aa putchar('a' + (n - NNUM - NALPHA));
56 caf30c15 2024-11-17 aa }
57 caf30c15 2024-11-17 aa putchar('\n');
58 caf30c15 2024-11-17 aa }
59 caf30c15 2024-11-17 aa
60 33d6c58e 2024-11-17 aa static void
61 d8c0fc7b 2024-11-17 aa gpass_alpha(int npass, int plen, int ent)
62 caf30c15 2024-11-17 aa {
63 d8c0fc7b 2024-11-17 aa int n = NNUM + NALPHA*2;
64 33d6c58e 2024-11-17 aa
65 caf30c15 2024-11-17 aa #ifdef __OpenBSD__
66 caf30c15 2024-11-17 aa if (pledge("stdio rpath", NULL) == -1) /* revoke unveil */
67 caf30c15 2024-11-17 aa err(1, "pledge");
68 caf30c15 2024-11-17 aa #endif
69 d8c0fc7b 2024-11-17 aa if (plen == 0)
70 d8c0fc7b 2024-11-17 aa plen = getplen(n, ent);
71 caf30c15 2024-11-17 aa for (int i = 0; i < npass; i++)
72 33d6c58e 2024-11-17 aa genalpha(plen, n);
73 caf30c15 2024-11-17 aa }
74 caf30c15 2024-11-17 aa
75 33d6c58e 2024-11-17 aa static void
76 33d6c58e 2024-11-17 aa genwords(int plen, int max, const long *offs, FILE *fp)
77 caf30c15 2024-11-17 aa {
78 33d6c58e 2024-11-17 aa int c;
79 33d6c58e 2024-11-17 aa unsigned int n, left;
80 caf30c15 2024-11-17 aa
81 33d6c58e 2024-11-17 aa for (left = plen; left > 0; left--) {
82 33d6c58e 2024-11-17 aa n = arc4random_uniform(max);
83 33d6c58e 2024-11-17 aa if (fseek(fp, offs[n], SEEK_SET) == -1)
84 926e1c04 2022-12-30 aa_src err(1, "fseek");
85 33d6c58e 2024-11-17 aa while ((c = getc(fp)) != EOF && isgraph(c))
86 699d07dd 2022-09-30 src putchar(c);
87 926e1c04 2022-12-30 aa_src if (left > 1)
88 926e1c04 2022-12-30 aa_src putchar(' ');
89 aab4ecb3 2022-07-14 src }
90 aab4ecb3 2022-07-14 src putchar('\n');
91 aab4ecb3 2022-07-14 src }
92 aab4ecb3 2022-07-14 src
93 caf30c15 2024-11-17 aa void
94 d8c0fc7b 2024-11-17 aa gpass_words(int npass, int plen, int ent, char *f)
95 caf30c15 2024-11-17 aa {
96 33d6c58e 2024-11-17 aa FILE *fp;
97 33d6c58e 2024-11-17 aa long offs[MAXWORDS];
98 d8c0fc7b 2024-11-17 aa int c, isword = 0, nwords;
99 caf30c15 2024-11-17 aa
100 caf30c15 2024-11-17 aa #ifdef __OpenBSD__
101 caf30c15 2024-11-17 aa if (unveil(f, "r") == -1)
102 caf30c15 2024-11-17 aa err(1, "unveil %s", f);
103 caf30c15 2024-11-17 aa if (pledge("stdio rpath", NULL) == -1) /* revoke unveil */
104 caf30c15 2024-11-17 aa err(1, "pledge");
105 caf30c15 2024-11-17 aa #endif
106 33d6c58e 2024-11-17 aa if (!(fp = fopen(f, "r")))
107 caf30c15 2024-11-17 aa err(1, "could not open %s", f);
108 33d6c58e 2024-11-17 aa while ((c = getc(fp)) != EOF && nwords < MAXWORDS)
109 33d6c58e 2024-11-17 aa if (!isgraph(c))
110 caf30c15 2024-11-17 aa isword = 0;
111 33d6c58e 2024-11-17 aa else if (!isword) {
112 caf30c15 2024-11-17 aa isword = 1;
113 33d6c58e 2024-11-17 aa offs[nwords++] = ftell(fp) - 1;
114 33d6c58e 2024-11-17 aa }
115 caf30c15 2024-11-17 aa if (nwords < 2)
116 caf30c15 2024-11-17 aa errx(1, "%s has less that 2 words", f);
117 d8c0fc7b 2024-11-17 aa if (plen == 0)
118 d8c0fc7b 2024-11-17 aa plen = getplen(nwords, ent);
119 caf30c15 2024-11-17 aa for (int i = 0; i < npass; i++)
120 33d6c58e 2024-11-17 aa genwords(plen, nwords, offs, fp);
121 33d6c58e 2024-11-17 aa fclose(fp);
122 caf30c15 2024-11-17 aa }
123 caf30c15 2024-11-17 aa
124 aab4ecb3 2022-07-14 src int
125 aab4ecb3 2022-07-14 src main(int argc, char *argv[])
126 aab4ecb3 2022-07-14 src {
127 d8c0fc7b 2024-11-17 aa int c, ent = 70, npass = 1, plen = 0;
128 33d6c58e 2024-11-17 aa char *dicname = NULL;
129 33d6c58e 2024-11-17 aa const char *errstr = NULL;
130 699d07dd 2022-09-30 src
131 699d07dd 2022-09-30 src #ifdef __OpenBSD__
132 bb118a6c 2022-10-19 src if (pledge("stdio unveil rpath", NULL) == -1) /* first call */
133 699d07dd 2022-09-30 src err(1, "pledge");
134 699d07dd 2022-09-30 src #endif
135 d8c0fc7b 2024-11-17 aa while ((c = getopt(argc, argv, "ad:e:l:n:")) != -1) {
136 aab4ecb3 2022-07-14 src switch (c) {
137 caf30c15 2024-11-17 aa case 'a':
138 caf30c15 2024-11-17 aa aflag = 1;
139 caf30c15 2024-11-17 aa break;
140 aab4ecb3 2022-07-14 src case 'd':
141 699d07dd 2022-09-30 src dicname = optarg;
142 aab4ecb3 2022-07-14 src break;
143 aab4ecb3 2022-07-14 src case 'e':
144 d8c0fc7b 2024-11-17 aa ent = strtonum(optarg, 0, INT_MAX, &errstr);
145 33d6c58e 2024-11-17 aa if (errstr != NULL)
146 33d6c58e 2024-11-17 aa errx(1, "entropy is %s: %s", errstr, optarg);
147 aab4ecb3 2022-07-14 src break;
148 d8c0fc7b 2024-11-17 aa case 'l':
149 d8c0fc7b 2024-11-17 aa plen = strtonum(optarg, 0, INT_MAX, &errstr);
150 d8c0fc7b 2024-11-17 aa if (errstr != NULL)
151 d8c0fc7b 2024-11-17 aa errx(1, "length is %s: %s", errstr, optarg);
152 d8c0fc7b 2024-11-17 aa break;
153 aab4ecb3 2022-07-14 src case 'n':
154 d8c0fc7b 2024-11-17 aa npass = strtonum(optarg, 0, INT_MAX, &errstr);
155 33d6c58e 2024-11-17 aa if (errstr != NULL)
156 33d6c58e 2024-11-17 aa errx(1, "npass is %s: %s", errstr, optarg);
157 aab4ecb3 2022-07-14 src break;
158 aab4ecb3 2022-07-14 src default:
159 aab4ecb3 2022-07-14 src usage();
160 aab4ecb3 2022-07-14 src }
161 aab4ecb3 2022-07-14 src }
162 ffe25f1f 2022-08-21 src
163 d8c0fc7b 2024-11-17 aa if (npass == 0 || (plen == 0 && ent == 0))
164 d8c0fc7b 2024-11-17 aa return 0;
165 d8c0fc7b 2024-11-17 aa
166 caf30c15 2024-11-17 aa if (aflag)
167 d8c0fc7b 2024-11-17 aa gpass_alpha(npass, plen, ent);
168 caf30c15 2024-11-17 aa else {
169 caf30c15 2024-11-17 aa if (!dicname && !(dicname = getenv("GPASS_DIC")))
170 caf30c15 2024-11-17 aa dicname = PREFIX "/share/gpass/eff.long";
171 d8c0fc7b 2024-11-17 aa gpass_words(npass, plen, ent, dicname);
172 caf30c15 2024-11-17 aa }
173 926e1c04 2022-12-30 aa_src
174 56fdb92d 2022-08-21 src return 0;
175 aab4ecb3 2022-07-14 src }