diff options
author | Damien Miller <djm@mindrot.org> | 2010-03-04 21:53:35 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2010-03-04 21:53:35 +1100 |
commit | 1aed65eb27feec505997c98621bdf158f9ab8b99 (patch) | |
tree | 81c2d0b9aff3c2211388ba00cde544e0618750d2 /hostfile.c | |
parent | 2befbad9b3c8fc6e4e564c062870229bc722734c (diff) |
- djm@cvs.openbsd.org 2010/03/04 10:36:03
[auth-rh-rsa.c auth-rsa.c auth.c auth.h auth2-hostbased.c auth2-pubkey.c]
[authfile.c authfile.h hostfile.c hostfile.h servconf.c servconf.h]
[ssh-keygen.c ssh.1 sshconnect.c sshd_config.5]
Add a TrustedUserCAKeys option to sshd_config to specify CA keys that
are trusted to authenticate users (in addition than doing it per-user
in authorized_keys).
Add a RevokedKeys option to sshd_config and a @revoked marker to
known_hosts to allow keys to me revoked and banned for user or host
authentication.
feedback and ok markus@
Diffstat (limited to 'hostfile.c')
-rw-r--r-- | hostfile.c | 102 |
1 files changed, 81 insertions, 21 deletions
diff --git a/hostfile.c b/hostfile.c index fc7f84c79..afab6dad1 100644 --- a/hostfile.c +++ b/hostfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: hostfile.c,v 1.47 2010/02/26 20:29:54 djm Exp $ */ | 1 | /* $OpenBSD: hostfile.c,v 1.48 2010/03/04 10:36:03 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -183,6 +183,41 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen | |||
183 | return 1; | 183 | return 1; |
184 | } | 184 | } |
185 | 185 | ||
186 | static enum { MRK_ERROR, MRK_NONE, MRK_REVOKE, MRK_CA } | ||
187 | check_markers(char **cpp) | ||
188 | { | ||
189 | char marker[32], *sp, *cp = *cpp; | ||
190 | int ret = MRK_NONE; | ||
191 | |||
192 | while (*cp == '@') { | ||
193 | /* Only one marker is allowed */ | ||
194 | if (ret != MRK_NONE) | ||
195 | return MRK_ERROR; | ||
196 | /* Markers are terminated by whitespace */ | ||
197 | if ((sp = strchr(cp, ' ')) == NULL && | ||
198 | (sp = strchr(cp, '\t')) == NULL) | ||
199 | return MRK_ERROR; | ||
200 | /* Extract marker for comparison */ | ||
201 | if (sp <= cp + 1 || sp >= cp + sizeof(marker)) | ||
202 | return MRK_ERROR; | ||
203 | memcpy(marker, cp, sp - cp); | ||
204 | marker[sp - cp] = '\0'; | ||
205 | if (strcmp(marker, CA_MARKER) == 0) | ||
206 | ret = MRK_CA; | ||
207 | else if (strcmp(marker, REVOKE_MARKER) == 0) | ||
208 | ret = MRK_REVOKE; | ||
209 | else | ||
210 | return MRK_ERROR; | ||
211 | |||
212 | /* Skip past marker and any whitespace that follows it */ | ||
213 | cp = sp; | ||
214 | for (; *cp == ' ' || *cp == '\t'; cp++) | ||
215 | ; | ||
216 | } | ||
217 | *cpp = cp; | ||
218 | return ret; | ||
219 | } | ||
220 | |||
186 | /* | 221 | /* |
187 | * Checks whether the given host (which must be in all lowercase) is already | 222 | * Checks whether the given host (which must be in all lowercase) is already |
188 | * in the list of our known hosts. Returns HOST_OK if the host is known and | 223 | * in the list of our known hosts. Returns HOST_OK if the host is known and |
@@ -195,17 +230,21 @@ hostfile_check_key(int bits, const Key *key, const char *host, const char *filen | |||
195 | 230 | ||
196 | static HostStatus | 231 | static HostStatus |
197 | check_host_in_hostfile_by_key_or_type(const char *filename, | 232 | check_host_in_hostfile_by_key_or_type(const char *filename, |
198 | const char *host, const Key *key, int keytype, Key *found, int *numret) | 233 | const char *host, const Key *key, int keytype, Key *found, |
234 | int want_revocation, int *numret) | ||
199 | { | 235 | { |
200 | FILE *f; | 236 | FILE *f; |
201 | char line[8192]; | 237 | char line[8192]; |
202 | int linenum = 0, want_cert = key_is_cert(key); | 238 | int want, have, linenum = 0, want_cert = key_is_cert(key); |
203 | u_int kbits; | 239 | u_int kbits; |
204 | char *cp, *cp2, *hashed_host; | 240 | char *cp, *cp2, *hashed_host; |
205 | HostStatus end_return; | 241 | HostStatus end_return; |
206 | 242 | ||
207 | debug3("check_host_in_hostfile: host %s filename %s", host, filename); | 243 | debug3("check_host_in_hostfile: host %s filename %s", host, filename); |
208 | 244 | ||
245 | if (want_revocation && (key == NULL || keytype != 0 || found != NULL)) | ||
246 | fatal("%s: invalid arguments", __func__); | ||
247 | |||
209 | /* Open the file containing the list of known hosts. */ | 248 | /* Open the file containing the list of known hosts. */ |
210 | f = fopen(filename, "r"); | 249 | f = fopen(filename, "r"); |
211 | if (!f) | 250 | if (!f) |
@@ -229,21 +268,18 @@ check_host_in_hostfile_by_key_or_type(const char *filename, | |||
229 | if (!*cp || *cp == '#' || *cp == '\n') | 268 | if (!*cp || *cp == '#' || *cp == '\n') |
230 | continue; | 269 | continue; |
231 | 270 | ||
232 | /* | 271 | if (want_revocation) |
233 | * Ignore CA keys when looking for raw keys. | 272 | want = MRK_REVOKE; |
234 | * Ignore raw keys when looking for CA keys. | 273 | else if (want_cert) |
235 | */ | 274 | want = MRK_CA; |
236 | if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && | 275 | else |
237 | (cp[sizeof(CA_MARKER) - 1] == ' ' || | 276 | want = MRK_NONE; |
238 | cp[sizeof(CA_MARKER) - 1] == '\t')) { | 277 | |
239 | if (want_cert) { | 278 | if ((have = check_markers(&cp)) == MRK_ERROR) { |
240 | /* Skip the marker and following whitespace */ | 279 | verbose("%s: invalid marker at %s:%d", |
241 | cp += sizeof(CA_MARKER); | 280 | __func__, filename, linenum); |
242 | for (; *cp == ' ' || *cp == '\t'; cp++) | 281 | continue; |
243 | ; | 282 | } else if (want != have) |
244 | } else | ||
245 | continue; | ||
246 | } else if (want_cert) | ||
247 | continue; | 283 | continue; |
248 | 284 | ||
249 | /* Find the end of the host name portion. */ | 285 | /* Find the end of the host name portion. */ |
@@ -267,6 +303,9 @@ check_host_in_hostfile_by_key_or_type(const char *filename, | |||
267 | /* Got a match. Skip host name. */ | 303 | /* Got a match. Skip host name. */ |
268 | cp = cp2; | 304 | cp = cp2; |
269 | 305 | ||
306 | if (want_revocation) | ||
307 | found = key_new(KEY_UNSPEC); | ||
308 | |||
270 | /* | 309 | /* |
271 | * Extract the key from the line. This will skip any leading | 310 | * Extract the key from the line. This will skip any leading |
272 | * whitespace. Ignore badly formatted lines. | 311 | * whitespace. Ignore badly formatted lines. |
@@ -289,6 +328,24 @@ check_host_in_hostfile_by_key_or_type(const char *filename, | |||
289 | if (!hostfile_check_key(kbits, found, host, filename, linenum)) | 328 | if (!hostfile_check_key(kbits, found, host, filename, linenum)) |
290 | continue; | 329 | continue; |
291 | 330 | ||
331 | if (want_revocation) { | ||
332 | if (key_is_cert(key) && | ||
333 | key_equal_public(key->cert->signature_key, found)) { | ||
334 | verbose("check_host_in_hostfile: revoked CA " | ||
335 | "line %d", linenum); | ||
336 | key_free(found); | ||
337 | return HOST_REVOKED; | ||
338 | } | ||
339 | if (key_equal_public(key, found)) { | ||
340 | verbose("check_host_in_hostfile: revoked key " | ||
341 | "line %d", linenum); | ||
342 | key_free(found); | ||
343 | return HOST_REVOKED; | ||
344 | } | ||
345 | key_free(found); | ||
346 | continue; | ||
347 | } | ||
348 | |||
292 | /* Check if the current key is the same as the given key. */ | 349 | /* Check if the current key is the same as the given key. */ |
293 | if (want_cert && key_equal(key->cert->signature_key, found)) { | 350 | if (want_cert && key_equal(key->cert->signature_key, found)) { |
294 | /* Found CA cert for key */ | 351 | /* Found CA cert for key */ |
@@ -325,8 +382,11 @@ check_host_in_hostfile(const char *filename, const char *host, const Key *key, | |||
325 | { | 382 | { |
326 | if (key == NULL) | 383 | if (key == NULL) |
327 | fatal("no key to look up"); | 384 | fatal("no key to look up"); |
328 | return (check_host_in_hostfile_by_key_or_type(filename, host, key, 0, | 385 | if (check_host_in_hostfile_by_key_or_type(filename, host, |
329 | found, numret)); | 386 | key, 0, NULL, 1, NULL) == HOST_REVOKED) |
387 | return HOST_REVOKED; | ||
388 | return check_host_in_hostfile_by_key_or_type(filename, host, key, 0, | ||
389 | found, 0, numret); | ||
330 | } | 390 | } |
331 | 391 | ||
332 | int | 392 | int |
@@ -334,7 +394,7 @@ lookup_key_in_hostfile_by_type(const char *filename, const char *host, | |||
334 | int keytype, Key *found, int *numret) | 394 | int keytype, Key *found, int *numret) |
335 | { | 395 | { |
336 | return (check_host_in_hostfile_by_key_or_type(filename, host, NULL, | 396 | return (check_host_in_hostfile_by_key_or_type(filename, host, NULL, |
337 | keytype, found, numret) == HOST_FOUND); | 397 | keytype, found, 0, numret) == HOST_FOUND); |
338 | } | 398 | } |
339 | 399 | ||
340 | /* | 400 | /* |