MFC if_ethersubr.c rev1.77:
[dragonfly.git] / crypto / openssh-5 / ssh-vulnkey.c
blob3297c431a7969849582b945133daa0eda9d1529a
1 /*
2 * Copyright (c) 2008 Canonical Ltd. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 #include "includes.h"
27 #include <sys/types.h>
28 #include <sys/stat.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <fcntl.h>
33 #include <unistd.h>
35 #include <openssl/evp.h>
37 #include "xmalloc.h"
38 #include "ssh.h"
39 #include "log.h"
40 #include "key.h"
41 #include "authfile.h"
42 #include "pathnames.h"
43 #include "misc.h"
45 extern char *__progname;
47 /* Default files to check */
48 static char *default_host_files[] = {
49 _PATH_HOST_RSA_KEY_FILE,
50 _PATH_HOST_DSA_KEY_FILE,
51 _PATH_HOST_KEY_FILE,
52 NULL
54 static char *default_files[] = {
55 _PATH_SSH_CLIENT_ID_RSA,
56 _PATH_SSH_CLIENT_ID_DSA,
57 _PATH_SSH_CLIENT_IDENTITY,
58 _PATH_SSH_USER_PERMITTED_KEYS,
59 _PATH_SSH_USER_PERMITTED_KEYS2,
60 NULL
63 static int quiet = 0;
65 static void
66 usage(void)
68 fprintf(stderr, "usage: %s [-aq] [file ...]\n", __progname);
69 fprintf(stderr, "Options:\n");
70 fprintf(stderr, " -a Check keys of all users.\n");
71 fprintf(stderr, " -q Quiet mode.\n");
72 exit(1);
75 void
76 describe_key(const char *msg, const Key *key, const char *comment)
78 char *fp;
80 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
81 if (!quiet)
82 printf("%s: %u %s %s\n", msg, key_size(key), fp, comment);
83 xfree(fp);
86 int
87 do_key(const Key *key, const char *comment)
89 char *blacklist_file;
90 struct stat st;
91 int ret = 1;
93 blacklist_file = blacklist_filename(key);
94 if (stat(blacklist_file, &st) < 0)
95 describe_key("Unknown (no blacklist information)",
96 key, comment);
97 else if (blacklisted_key(key)) {
98 describe_key("COMPROMISED", key, comment);
99 ret = 0;
100 } else
101 describe_key("Not blacklisted", key, comment);
102 xfree(blacklist_file);
104 return ret;
108 do_filename(const char *filename, int quiet_open)
110 FILE *f;
111 char line[SSH_MAX_PUBKEY_BYTES];
112 char *cp;
113 u_long linenum = 0;
114 Key *key;
115 char *comment = NULL;
116 int found = 0, ret = 1;
118 /* Copy much of key_load_public's logic here so that we can read
119 * several keys from a single file (e.g. authorized_keys).
122 if (strcmp(filename, "-") != 0) {
123 f = fopen(filename, "r");
124 if (!f) {
125 char pubfile[MAXPATHLEN];
126 if (strlcpy(pubfile, filename, sizeof pubfile) <
127 sizeof(pubfile) &&
128 strlcat(pubfile, ".pub", sizeof pubfile) <
129 sizeof(pubfile))
130 f = fopen(pubfile, "r");
132 if (!f) {
133 if (!quiet_open)
134 perror(filename);
135 return -1;
137 } else
138 f = stdin;
139 while (read_keyfile_line(f, filename, line, sizeof(line),
140 &linenum) != -1) {
141 int i;
142 char *space;
143 int type;
145 /* Chop trailing newline. */
146 i = strlen(line) - 1;
147 if (line[i] == '\n')
148 line[i] = '\0';
150 /* Skip leading whitespace, empty and comment lines. */
151 for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
153 if (!*cp || *cp == '\n' || *cp == '#')
154 continue;
156 /* Cope with ssh-keyscan output and options in
157 * authorized_keys files.
159 space = strchr(cp, ' ');
160 if (!space)
161 continue;
162 *space = '\0';
163 type = key_type_from_name(cp);
164 *space = ' ';
165 /* Leading number (RSA1) or valid type (RSA/DSA) indicates
166 * that we have no host name or options to skip.
168 if (atoi(cp) == 0 && type == KEY_UNSPEC) {
169 int quoted = 0;
171 for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
172 if (*cp == '\\' && cp[1] == '"')
173 cp++; /* Skip both */
174 else if (*cp == '"')
175 quoted = !quoted;
177 /* Skip remaining whitespace. */
178 for (; *cp == ' ' || *cp == '\t'; cp++)
180 if (!*cp)
181 continue;
184 /* Read and process the key itself. */
185 key = key_new(KEY_RSA1);
186 if (key_read(key, &cp) == 1) {
187 while (*cp == ' ' || *cp == '\t')
188 cp++;
189 if (!do_key(key, *cp ? cp : filename))
190 ret = 0;
191 found = 1;
192 } else {
193 key_free(key);
194 key = key_new(KEY_UNSPEC);
195 if (key_read(key, &cp) == 1) {
196 while (*cp == ' ' || *cp == '\t')
197 cp++;
198 if (!do_key(key, *cp ? cp : filename))
199 ret = 0;
200 found = 1;
203 key_free(key);
205 if (f != stdin)
206 fclose(f);
208 if (!found && filename) {
209 key = key_load_public(filename, &comment);
210 if (key) {
211 if (!do_key(key, comment))
212 ret = 0;
213 found = 1;
215 if (comment)
216 xfree(comment);
219 return ret;
223 do_host(void)
225 int i;
226 struct stat st;
227 int ret = 1;
229 for (i = 0; default_host_files[i]; i++) {
230 if (stat(default_host_files[i], &st) < 0)
231 continue;
232 if (!do_filename(default_host_files[i], 1))
233 ret = 0;
236 return ret;
240 do_user(const char *dir)
242 int i;
243 char buf[MAXPATHLEN];
244 struct stat st;
245 int ret = 1;
247 for (i = 0; default_files[i]; i++) {
248 snprintf(buf, sizeof(buf), "%s/%s", dir, default_files[i]);
249 if (stat(buf, &st) < 0)
250 continue;
251 if (!do_filename(buf, 0))
252 ret = 0;
255 return ret;
259 main(int argc, char **argv)
261 int opt, all_users = 0;
262 int ret = 1;
263 extern int optind;
265 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
266 sanitise_stdfd();
268 __progname = ssh_get_progname(argv[0]);
270 SSLeay_add_all_algorithms();
271 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
273 /* We don't need the RNG ourselves, but symbol references here allow
274 * ld to link us properly.
276 init_rng();
277 seed_rng();
279 while ((opt = getopt(argc, argv, "ahq")) != -1) {
280 switch (opt) {
281 case 'a':
282 all_users = 1;
283 break;
284 case 'q':
285 quiet = 1;
286 break;
287 case 'h':
288 default:
289 usage();
293 if (all_users) {
294 struct passwd *pw;
296 if (!do_host())
297 ret = 0;
299 while ((pw = getpwent()) != NULL) {
300 if (pw->pw_dir) {
301 if (!do_user(pw->pw_dir))
302 ret = 0;
305 } else if (optind == argc) {
306 struct passwd *pw;
308 if (!do_host())
309 ret = 0;
311 if ((pw = getpwuid(getuid())) == NULL)
312 fprintf(stderr, "No user found with uid %u\n",
313 (u_int)getuid());
314 else {
315 if (!do_user(pw->pw_dir))
316 ret = 0;
318 } else {
319 while (optind < argc)
320 if (!do_filename(argv[optind++], 0))
321 ret = 0;
324 return ret;