1/* See LICENSE file for copyright and license details. */
2#include "passwd.h"
3#include "paths.h"
4#include "util.h"
5
6#include <ctype.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12static void
13usage(void)
14{
15 eprintf("usage: %s [-P fd] [-m type] [-S salt] [password] [salt]\n", argv0);
16}
17
18// ?man mkpasswd: encrypt the given password using salt
19// ?man arguments: [password] [salt]
20// ?man encrypt password using crypt(3) with random or provided salt
21int
22main(int argc, char *argv[])
23{
24 char *mflag, *sflag, *parg, *password, *cryptpass;
25 char *prefix;
26 char salt[128];
27 char passbuf[1024];
28 int pfd, len;
29
30 mflag = NULL;
31 sflag = NULL;
32 parg = NULL;
33 password = NULL;
34 cryptpass = NULL;
35 pfd = -1;
36 len = 2;
37 prefix = NULL;
38
39 ARGBEGIN
40 {
41 case 'P':
42 // ?man -P:fd: read password from file descriptor
43 parg = EARGF(usage());
44 pfd = estrtonum(parg, 0, INT_MAX);
45 break;
46 case 'm':
47 // ?man -m:type: encryption method (des, md5, sha256, sha512)
48 mflag = EARGF(usage());
49 break;
50 case 'S':
51 // ?man -S:salt: salt to use
52 sflag = EARGF(usage());
53 break;
54 default:
55 usage();
56 }
57 ARGEND
58
59 if (argc > 2)
60 usage();
61
62 if (argc == 2) {
63 if (sflag)
64 eprintf("duplicate salt\n");
65 sflag = argv[1];
66 }
67
68 if (argc >= 1)
69 password = argv[0];
70
71 if (!mflag)
72 mflag = "des";
73
74 if (strcasecmp(mflag, "des") == 0) {
75 len = 2;
76 prefix = NULL;
77 } else if (strcasecmp(mflag, "md5") == 0) {
78 len = 8;
79 prefix = "$1$";
80 } else if (strcasecmp(mflag, "sha256") == 0) {
81 len = 16;
82 prefix = "$5$";
83 } else if (strcasecmp(mflag, "sha512") == 0) {
84 len = 16;
85 prefix = "$6$";
86 } else {
87 eprintf("bad method: %s\n", mflag);
88 }
89
90 if (sflag) {
91 char *s = sflag;
92 while (*s) {
93 if (!isalnum((unsigned char)*s) && *s != '.' && *s != '/')
94 eprintf("bad SALT (need [a-zA-Z0-9./])\n");
95 s++;
96 }
97 if (prefix)
98 snprintf(salt, sizeof(salt), "%s%s", prefix, sflag);
99 else
100 estrlcpy(salt, sflag, sizeof(salt));
101 } else {
102 if (pw_gensalt_cipher(salt, sizeof(salt), prefix, len) < 0)
103 eprintf("pw_gensalt_cipher:");
104 }
105
106 if (pfd >= 0) {
107 if (dup2(pfd, 0) == -1)
108 eprintf("dup2:");
109 close(pfd);
110 }
111
112 if (!password) {
113 if (isatty(0)) {
114 char *p = getpass("Password: ");
115 if (!p)
116 eprintf("getpass failed\n");
117 estrlcpy(passbuf, p, sizeof(passbuf));
118 password = passbuf;
119 } else {
120 int bytes = read(0, passbuf, sizeof(passbuf) - 1);
121 if (bytes < 0)
122 eprintf("read stdin:");
123 while (bytes > 0 && (passbuf[bytes - 1] == '\n' || passbuf[bytes - 1] == '\r'))
124 bytes--;
125 passbuf[bytes] = '\0';
126 password = passbuf;
127 }
128 }
129
130 cryptpass = crypt(password, salt);
131 if (!cryptpass)
132 eprintf("crypt:");
133 printf("%s\n", cryptpass);
134
135 if (fshut(stdout, "<stdout>"))
136 return 2;
137 return 0;
138}