source: freewrt/tools/mkpasswd/src/mkpasswd.c@ 9cf508e

freewrt_1_0 freewrt_2_0
Last change on this file since 9cf508e was 9cf508e, checked in by Markus Wigge <markus@…>, 19 years ago
  • added runtime config for password
  • added runtime config for ssh-key
  • added mkpasswd for crypt-md5 generation (needed for runtime password config)

git-svn-id: svn://www.freewrt.org/trunk/freewrt@325 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Copyright (C) 2001-2002 Marco d'Itri
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#define _XOPEN_SOURCE
20#define _BSD_SOURCE
21#include <stdio.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include "config.h"
25#ifdef HAVE_GETOPT_LONG
26#include <getopt.h>
27#endif
28#include <string.h>
29#include <time.h>
30#include <sys/types.h>
31
32#ifdef HAVE_GETOPT_LONG
33static struct option longopts[] = {
34 {"hash", optional_argument, NULL, 'H'},
35 {"help", no_argument, NULL, 'h'},
36 {"password-fd", required_argument, NULL, 'P'},
37 {"stdin", no_argument, NULL, 's'},
38 {"salt", required_argument, NULL, 'S'},
39 {"version", no_argument, NULL, 'V'},
40 {NULL, 0, NULL, 0 }
41};
42#endif
43
44static char valid_salts[] = "abcdefghijklmnopqrstuvwxyz"
45"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
46
47struct salt_prefix {
48 const char *algo; /* short name used by the command line option */
49 const char *prefix; /* salt prefix */
50 unsigned int len; /* salt lenght */
51 const char *desc; /* long description for the algorithms list */
52};
53
54struct salt_prefix salt_prefixes[] = {
55 { "des", "", 2, N_("\tstandard 56 bit DES-based crypt(3)") },
56 { "md5", "$1$", 8, "\tMD5" },
57/* untested! is the salt correctly generated? */
58#if defined OpenBSD || defined FreeBSD
59 { "blf", "$2$", 16, "\tBlowfish" },
60#endif
61/* untested too, and does not even compile */
62#if defined HAVE_XCRYPT
63 { "blf", "$2a$", 16, "\tBlowfish" },
64 { "sha", "{SHA}", , "\tSHA-1" },
65#endif
66 { NULL, NULL, 0, NULL }
67};
68
69void generate_salt(char *buf, const unsigned int len);
70void display_help(void);
71void display_version(void);
72void display_algorithms(void);
73
74int main(int argc, char *argv[])
75{
76 int ch;
77 int password_fd = -1;
78 unsigned int i, salt_len = 0;
79 const char *salt_prefix = NULL;
80 char *salt = NULL;
81 char *password = NULL;
82
83#ifdef ENABLE_NLS
84 setlocale(LC_ALL, "");
85 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
86 textdomain(NLS_CAT_NAME);
87#endif
88
89 while ((ch = GETOPT_LONGISH(argc, argv, "hH:P:sS:V", longopts, 0)) > 0) {
90 switch (ch) {
91 case 'H':
92 if (!optarg || strcasecmp("help", optarg) == 0) {
93 display_algorithms();
94 exit(0);
95 }
96 for (i = 0; salt_prefixes[i].algo != NULL; i++)
97 if (strcasecmp(salt_prefixes[i].algo, optarg) == 0) {
98 salt_prefix = salt_prefixes[i].prefix;
99 salt_len = salt_prefixes[i].len;
100 break;
101 }
102 if (!salt_prefix) {
103 fprintf(stderr, _("Invalid hash type '%s'.\n"), optarg);
104 exit(1);
105 }
106 break;
107 case 'P':
108 {
109 char *p;
110 password_fd = strtol(optarg, &p, 10);
111 if (p == NULL || *p != '\0' || password_fd < 0) {
112 fprintf(stderr, _("Invalid number '%s'.\n"), optarg);
113 exit(1);
114 }
115 }
116 break;
117 case 's':
118 password_fd = 0;
119 break;
120 case 'S':
121 salt = optarg;
122 break;
123 case 'V':
124 display_version();
125 exit(0);
126 case 'h':
127 display_help();
128 exit(0);
129 default:
130 fprintf(stderr, _("Try '%s --help' for more information.\n"),
131 argv[0]);
132 exit(1);
133 }
134 }
135 argc -= optind;
136 argv += optind;
137
138 if (argc == 2 && !salt) {
139 password = argv[0];
140 salt = argv[1];
141 } else if (argc == 1) {
142 password = argv[0];
143 } else if (argc == 0) {
144 } else {
145 display_help();
146 exit(1);
147 }
148
149 /* default: DES password */
150 if (!salt_len) {
151 salt_len = salt_prefixes[0].len;
152 salt_prefix = salt_prefixes[0].prefix;
153 }
154
155 if (salt) {
156 unsigned int c = strlen(salt);
157 if (c != salt_len) {
158 fprintf(stderr,
159 _("Wrong salt length: %d byte(s) when %d expected.\n"),
160 c, salt_len);
161 exit(1);
162 }
163 while (c-- > 0)
164 if (strchr(valid_salts, salt[c]) == NULL) {
165 fprintf(stderr, _("Illegal salt character '%c'.\n"), salt[c]);
166 exit(1);
167 }
168 } else {
169#ifdef HAVE_XCRYPT
170 char *entropy = gather_entropy(4096);
171 salt = crypt_gensalt(salt_prefix, 0, entropy, 4096);
172 if (!salt) {
173 perror("crypt");
174 exit(2);
175 }
176 free(entropy);
177#else
178 salt = malloc(salt_len + 1);
179 generate_salt(salt, salt_len);
180#endif
181 }
182
183 if (!password) {
184 if (password_fd != -1) {
185 FILE *fp;
186 unsigned char *p;
187
188 if (isatty(password_fd))
189 fprintf(stderr, _("Password: "));
190 password = malloc(128);
191 fp = fdopen(password_fd, "r");
192 if (!fp) {
193 perror("fdopen");
194 exit(2);
195 }
196 if (!fgets(password, 128, fp)) {
197 perror("fgets");
198 exit(2);
199 }
200
201 p = (unsigned char *)password;
202 while (*p) {
203 if (*p == '\n') {
204 *p = '\0';
205 break;
206 }
207 /* which characters are valid? */
208 if (*p > 0x7f) {
209 fprintf(stderr,
210 _("Illegal password character '0x%hhx'.\n"), *p);
211 exit(1);
212 }
213 p++;
214 }
215 } else {
216 password = getpass(_("Password: "));
217 if (!password) {
218 perror("getpass");
219 exit(2);
220 }
221 }
222 }
223
224 {
225 char *pw, *result;
226 pw = malloc(strlen(salt_prefix) + strlen(salt) + 1);
227 *pw = '\0';
228 strcat(pw, salt_prefix);
229 strcat(pw, salt);
230 result = crypt(password, pw);
231 if (!result) {
232 perror("crypt");
233 exit(2);
234 }
235 printf("%s\n", result);
236 }
237 exit(0);
238}
239
240#ifndef HAVE_XCRYPT
241void generate_salt(char *buf, const unsigned int len)
242{
243 unsigned int i;
244
245 srand(time(NULL) + getpid());
246 for (i = 0; i < len; i++)
247 buf[i] = valid_salts[rand() % (sizeof valid_salts - 1)];
248 buf[i] = '\0';
249}
250#endif
251
252void display_help(void)
253{
254 fprintf(stderr, _("Usage: mkpasswd [OPTIONS]... [PASSWORD [SALT]]\n"
255 "Crypts the PASSWORD using crypt(3).\n\n"));
256 fprintf(stderr, _(
257" -H, --hash=TYPE select hash TYPE\n"
258" -S, --salt=SALT use the specified SALT\n"
259" -P, --password-fd=NUM read the password from file descriptor NUM\n"
260" instead of /dev/tty\n"
261" -s, --stdin like --password-fd=0\n"
262" -h, --help display this help and exit\n"
263" -V, --version output version information and exit\n"
264"\n"
265"If PASSWORD is missing then it is asked interactively.\n"
266"If no SALT is specified, a random one is generated.\n"
267"If TYPE is 'help', available algorithms are printed.\n"
268"\n"
269"Report bugs to %s.\n"), "<md+whois@linux.it>");
270}
271
272void display_version(void)
273{
274 printf("GNU mkpasswd %s\n\n", VERSION);
275 puts("Copyright (C) 2001-2004 Marco d'Itri\n"
276"This is free software; see the source for copying conditions. There is NO\n"
277"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
278}
279
280void display_algorithms(void)
281{
282 int i;
283
284 printf(_("Available algorithms:\n"));
285 for (i = 0; salt_prefixes[i].algo != NULL; i++)
286 printf("%s%s\n", salt_prefixes[i].algo, salt_prefixes[i].desc);
287}
Note: See TracBrowser for help on using the repository browser.