commit - caf30c150740e01b41af2fe0d5c32da701c089eb
commit + 33d6c58e6acdb1ccf1ad84e52b2c896e9197b304
blob - 359be0d60a07a35d828fccddf3334f549fa16655
blob + aabcbf865fb6f370e8c90d078b0e262cb6f259e1
--- gpass.c
+++ gpass.c
#include <ctype.h>
+#include <err.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#include <strings.h>
#include <unistd.h>
-#define MAXWORDS 32768
+#define MAXWORDS 32768
+#define NNUM ('9'-'0' + 1)
+#define NALPHA ('z'-'a' + 1)
+
#ifndef PREFIX
-# define PREFIX "/usr/local"
+# define PREFIX "/usr/local"
#endif
-#define NNUM ('9'-'0' + 1)
-#define NALPHA ('z'-'a' + 1)
-
-FILE *dicfp;
-uint32_t nwords = 0;
-int offs[MAXWORDS];
-int plen = 70;
int aflag = 0;
-void
-errx(int eval, const char *fmt, ...)
-{
- fputs("gpass: ", stderr);
- if (fmt != NULL) {
- va_list argp;
- va_start(argp, fmt);
- vfprintf(stderr, fmt, argp);
- va_end(argp);
- }
- fputc('\n', stderr);
- exit(eval);
-}
-
-void
-err(int eval, const char *fmt, ...)
-{
- char *e = strerror(errno);
- fputs("gpass: ", stderr);
- if (fmt != NULL) {
- va_list argp;
- va_start(argp, fmt);
- vfprintf(stderr, fmt, argp);
- va_end(argp);
- }
- fputs(": ", stderr);
- fputs(e, stderr);
- fputc('\n', stderr);
- exit(eval);
-}
-
-int
+static int
usage(void)
{
fprintf(stderr, "usage: gpass [-a] [-d dict] [-e bits] [-n count]\n");
exit(EXIT_FAILURE);
}
-void
-setplen(void) {
- int temp;
+static int
+getplen(int n, int ent) {
+ long temp;
+ int plen;
- temp = log2(nwords);
- plen = plen / temp + !!(plen % temp);
- plen += !plen;
+ temp = log2(n);
+ plen = ent / temp + !!(ent % temp);
+ return (plen > 0) ? plen : 1;
}
-void
-genalpha(void)
+static void
+genalpha(int plen, int max)
{
- int c;
- int left;
- uint32_t n;
+ int c;
+ int left;
+ uint32_t n;
for (left = plen; left; left--) {
- n = arc4random_uniform(NNUM + NALPHA*2);
+ n = arc4random_uniform(max);
if (n < NNUM)
putchar('0' + n);
else if (n < NNUM + NALPHA)
putchar('\n');
}
-void
-gpass_alpha(int npass)
+static void
+gpass_alpha(int npass, int ent)
{
+ int n = NNUM + NALPHA*2, plen;
+
#ifdef __OpenBSD__
if (pledge("stdio rpath", NULL) == -1) /* revoke unveil */
err(1, "pledge");
#endif
- nwords = NNUM + NALPHA*2;
- setplen();
+ plen = getplen(n, ent);
for (int i = 0; i < npass; i++)
- genalpha();
+ genalpha(plen, n);
}
-void
-genwords(void)
+static void
+genwords(int plen, int max, const long *offs, FILE *fp)
{
- int c;
- int left;
- uint32_t n;
+ int c;
+ unsigned int n, left;
- for (left = plen; left; left--) {
- n = arc4random_uniform(nwords) + 1;
- if (fseek(dicfp, offs[n], SEEK_SET) == -1)
+ for (left = plen; left > 0; left--) {
+ n = arc4random_uniform(max);
+ if (fseek(fp, offs[n], SEEK_SET) == -1)
err(1, "fseek");
- while ((c = getc(dicfp)) != EOF && !isspace(c))
+ while ((c = getc(fp)) != EOF && isgraph(c))
putchar(c);
if (left > 1)
putchar(' ');
}
void
-gpass_words(int npass, char *f)
+gpass_words(int npass, int ent, char *f)
{
- char c, isword;
+ FILE *fp;
+ long offs[MAXWORDS];
+ int c, isword = 0, nwords, plen;
#ifdef __OpenBSD__
if (unveil(f, "r") == -1)
if (pledge("stdio rpath", NULL) == -1) /* revoke unveil */
err(1, "pledge");
#endif
- if (!(dicfp = fopen(f, "r")))
+ if (!(fp = fopen(f, "r")))
err(1, "could not open %s", f);
- offs[0] = ftell(dicfp);
- while ((c = getc(dicfp)) != EOF && nwords < MAXWORDS)
- if (isspace(c)) {
- nwords += isword ? 1 : 0;
+ while ((c = getc(fp)) != EOF && nwords < MAXWORDS)
+ if (!isgraph(c))
isword = 0;
- offs[nwords] = ftell(dicfp);
- } else
+ else if (!isword) {
isword = 1;
+ offs[nwords++] = ftell(fp) - 1;
+ }
if (nwords < 2)
errx(1, "%s has less that 2 words", f);
- setplen();
+ plen = getplen(nwords, ent);
for (int i = 0; i < npass; i++)
- genwords();
- fclose(dicfp);
+ genwords(plen, nwords, offs, fp);
+ fclose(fp);
}
int
main(int argc, char *argv[])
{
- int c, npass;
- char *dicname;
+ int c, ent = 70, npass = 1;
+ char *dicname = NULL;
+ const char *errstr = NULL;
- npass = 1;
- dicname = NULL;
-
#ifdef __OpenBSD__
if (pledge("stdio unveil rpath", NULL) == -1) /* first call */
err(1, "pledge");
dicname = optarg;
break;
case 'e':
- if ((plen = atoi(optarg)) < 1)
- errx(1, "less than 1 bit of entropy requested");
+ ent = strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "entropy is %s: %s", errstr, optarg);
break;
case 'n':
- if ((npass = atoi(optarg)) < 1)
- errx(1, "less than 1 passphrase requested");
+ npass = strtonum(optarg, 1, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(1, "npass is %s: %s", errstr, optarg);
break;
default:
usage();
}
if (aflag)
- gpass_alpha(npass);
+ gpass_alpha(npass, ent);
else {
if (!dicname && !(dicname = getenv("GPASS_DIC")))
dicname = PREFIX "/share/gpass/eff.long";
- gpass_words(npass, dicname);
+ gpass_words(npass, ent, dicname);
}
return 0;