1 /* $OpenBSD: encrypt.c,v 1.52 2022/02/10 13:06:46 robert Exp $ */
2
3 /*
4 * Copyright (c) 1996, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/types.h>
29 #include <ctype.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <login_cap.h>
38 #include <limits.h>
39 #include <readpassphrase.h>
40
41 /*
42 * Very simple little program, for encrypting passwords from the command
43 * line. Useful for scripts and such.
44 */
45
46 extern char *__progname;
47
48 static void __dead usage(void);
49 static void print_passwd(char *, int, char *);
50
51 #define DO_BLF 0
52
53 static void __dead
usage(void)54 usage(void)
55 {
56
57 (void)fprintf(stderr,
58 "usage: %s [-b rounds] [-c class] [-p | string]\n",
59 __progname);
60 exit(1);
61 }
62
63 static void
print_passwd(char * string,int operation,char * extra)64 print_passwd(char *string, int operation, char *extra)
65 {
66 char buffer[_PASSWORD_LEN];
67 const char *pref;
68 char prefbuf[64];
69
70 if (operation == DO_BLF) {
71 if (snprintf(prefbuf, sizeof(prefbuf), "blowfish,%s", extra) >=
72 sizeof(prefbuf))
73 errx(1, "pref too long");
74 pref = prefbuf;
75 } else {
76 login_cap_t *lc;
77
78 if ((lc = login_getclass(extra)) == NULL)
79 errx(1, "unable to get login class `%s'",
80 extra ? (char *)extra : "default");
81 pref = login_getcapstr(lc, "localcipher", NULL, NULL);
82 }
83 if (crypt_newhash(string, pref, buffer, sizeof(buffer)) != 0)
84 err(1, "can't generate hash");
85
86 fputs(buffer, stdout);
87 }
88
89 int
main(int argc,char ** argv)90 main(int argc, char **argv)
91 {
92 int opt;
93 int operation = -1;
94 int prompt = 0;
95 char *extra = NULL; /* Store login class or number of rounds */
96 const char *errstr;
97
98 if (unveil(_PATH_LOGIN_CONF, "r") == -1)
99 err(1, "unveil %s", _PATH_LOGIN_CONF);
100 if (unveil(_PATH_LOGIN_CONF ".db", "r") == -1)
101 err(1, "unveil %s.db", _PATH_LOGIN_CONF);
102 if (unveil(_PATH_LOGIN_CONF_D, "r") == -1)
103 err(1, "unveil %s", _PATH_LOGIN_CONF_D);
104 if (pledge("stdio rpath tty", NULL) == -1)
105 err(1, "pledge");
106
107 while ((opt = getopt(argc, argv, "pb:c:")) != -1) {
108 switch (opt) {
109 case 'p':
110 prompt = 1;
111 break;
112 case 'b': /* Blowfish password hash */
113 if (operation != -1)
114 usage();
115 operation = DO_BLF;
116 if (strcmp(optarg, "a") != 0) {
117 (void)strtonum(optarg, 4, 31, &errstr);
118 if (errstr != NULL)
119 errx(1, "rounds is %s: %s", errstr,
120 optarg);
121 }
122 extra = optarg;
123 break;
124 case 'c': /* user login class */
125 extra = optarg;
126 operation = -1;
127 break;
128 default:
129 usage();
130 }
131 }
132
133 if (((argc - optind) < 1)) {
134 char line[BUFSIZ];
135 char string[1024];
136
137 if (prompt) {
138 if (readpassphrase("Enter string: ", string,
139 sizeof(string), RPP_ECHO_OFF) == NULL)
140 err(1, "readpassphrase");
141 print_passwd(string, operation, extra);
142 (void)fputc('\n', stdout);
143 explicit_bzero(string, sizeof(string));
144 } else {
145 size_t len;
146 /* Encrypt stdin to stdout. */
147 while (!feof(stdin) &&
148 (fgets(line, sizeof(line), stdin) != NULL)) {
149 len = strlen(line);
150 if (len == 0 || line[0] == '\n')
151 continue;
152 if (line[len - 1] == '\n')
153 line[len - 1] = '\0';
154
155 print_passwd(line, operation, extra);
156
157 (void)fputc('\n', stdout);
158 }
159 }
160 } else {
161 char *string;
162
163 /* can't combine -p with a supplied string */
164 if (prompt)
165 usage();
166
167 /* Perhaps it isn't worth worrying about, but... */
168 if ((string = strdup(argv[optind])) == NULL)
169 err(1, NULL);
170 /* Wipe the argument. */
171 explicit_bzero(argv[optind], strlen(argv[optind]));
172
173 print_passwd(string, operation, extra);
174
175 (void)fputc('\n', stdout);
176
177 /* Wipe our copy, before we free it. */
178 freezero(string, strlen(string));
179 }
180 return 0;
181 }
182