#include <sys/types.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <login_cap.h>
#include <limits.h>
#include <readpassphrase.h>
extern char *__progname;
static void __dead usage(void);
static void print_passwd(char *, int, char *);
#define DO_BLF 0
static void __dead
usage(void)
{
(void)fprintf(stderr,
"usage: %s [-b rounds] [-c class] [-p | string]\n",
__progname);
exit(1);
}
static void
print_passwd(char *string, int operation, char *extra)
{
char buffer[_PASSWORD_LEN];
const char *pref;
char prefbuf[64];
if (operation == DO_BLF) {
if (snprintf(prefbuf, sizeof(prefbuf), "blowfish,%s", extra) >=
sizeof(prefbuf))
errx(1, "pref too long");
pref = prefbuf;
} else {
login_cap_t *lc;
if ((lc = login_getclass(extra)) == NULL)
errx(1, "unable to get login class `%s'",
extra ? (char *)extra : "default");
pref = login_getcapstr(lc, "localcipher", NULL, NULL);
}
if (crypt_newhash(string, pref, buffer, sizeof(buffer)) != 0)
err(1, "can't generate hash");
fputs(buffer, stdout);
}
int
main(int argc, char **argv)
{
int opt;
int operation = -1;
int prompt = 0;
char *extra = NULL;
const char *errstr;
if (unveil(_PATH_LOGIN_CONF, "r") == -1)
err(1, "unveil %s", _PATH_LOGIN_CONF);
if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
err(1, "unveil %s.db", _PATH_LOGIN_CONF);
if (unveil(_PATH_LOGIN_CONF_D, "r") == -1)
err(1, "unveil %s", _PATH_LOGIN_CONF_D);
if (pledge("stdio rpath tty", NULL) == -1)
err(1, "pledge");
while ((opt = getopt(argc, argv, "pb:c:")) != -1) {
switch (opt) {
case 'p':
prompt = 1;
break;
case 'b':
if (operation != -1)
usage();
operation = DO_BLF;
if (strcmp(optarg, "a") != 0) {
(void)strtonum(optarg, 4, 31, &errstr);
if (errstr != NULL)
errx(1, "rounds is %s: %s", errstr,
optarg);
}
extra = optarg;
break;
case 'c':
extra = optarg;
operation = -1;
break;
default:
usage();
}
}
if (((argc - optind) < 1)) {
char line[BUFSIZ];
char string[1024];
if (prompt) {
if (readpassphrase("Enter string: ", string,
sizeof(string), RPP_ECHO_OFF) == NULL)
err(1, "readpassphrase");
print_passwd(string, operation, extra);
(void)fputc('\n', stdout);
explicit_bzero(string, sizeof(string));
} else {
size_t len;
while (!feof(stdin) &&
(fgets(line, sizeof(line), stdin) != NULL)) {
len = strlen(line);
if (len == 0 || line[0] == '\n')
continue;
if (line[len - 1] == '\n')
line[len - 1] = '\0';
print_passwd(line, operation, extra);
(void)fputc('\n', stdout);
}
}
} else {
char *string;
if (prompt)
usage();
if ((string = strdup(argv[optind])) == NULL)
err(1, NULL);
explicit_bzero(argv[optind], strlen(argv[optind]));
print_passwd(string, operation, extra);
(void)fputc('\n', stdout);
freezero(string, strlen(string));
}
return 0;
}