diff options
author | Colin Watson <cjwatson@debian.org> | 2018-08-24 12:49:36 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2018-08-30 00:57:27 +0100 |
commit | 816386e17654ca36834bebbf351419e460fad8f6 (patch) | |
tree | 3dc79d831cb73bc25b92f5a4d18f8e328c0c570a /auth-options.c | |
parent | 3e6f76c7039d3df22b1d0a3a5f30150efb09b69d (diff) | |
parent | 16a47fc4b04977a14f44dd433c8da1499fa80671 (diff) |
New upstream release (7.8p1)
Closes: #907534
Diffstat (limited to 'auth-options.c')
-rw-r--r-- | auth-options.c | 152 |
1 files changed, 106 insertions, 46 deletions
diff --git a/auth-options.c b/auth-options.c index ef57ebf43..27c0eb05e 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.c,v 1.79 2018/04/06 04:15:45 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.c,v 1.83 2018/06/19 02:59:41 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> | 3 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> |
4 | * | 4 | * |
@@ -283,6 +283,10 @@ sshauthopt_free(struct sshauthopt *opts) | |||
283 | free(opts->permitopen[i]); | 283 | free(opts->permitopen[i]); |
284 | free(opts->permitopen); | 284 | free(opts->permitopen); |
285 | 285 | ||
286 | for (i = 0; i < opts->npermitlisten; i++) | ||
287 | free(opts->permitlisten[i]); | ||
288 | free(opts->permitlisten); | ||
289 | |||
286 | explicit_bzero(opts, sizeof(*opts)); | 290 | explicit_bzero(opts, sizeof(*opts)); |
287 | free(opts); | 291 | free(opts); |
288 | } | 292 | } |
@@ -304,10 +308,82 @@ sshauthopt_new_with_keys_defaults(void) | |||
304 | return ret; | 308 | return ret; |
305 | } | 309 | } |
306 | 310 | ||
311 | /* | ||
312 | * Parse and record a permitopen/permitlisten directive. | ||
313 | * Return 0 on success. Return -1 on failure and sets *errstrp to error reason. | ||
314 | */ | ||
315 | static int | ||
316 | handle_permit(const char **optsp, int allow_bare_port, | ||
317 | char ***permitsp, size_t *npermitsp, const char **errstrp) | ||
318 | { | ||
319 | char *opt, *tmp, *cp, *host, **permits = *permitsp; | ||
320 | size_t npermits = *npermitsp; | ||
321 | const char *errstr = "unknown error"; | ||
322 | |||
323 | if (npermits > INT_MAX) { | ||
324 | *errstrp = "too many permission directives"; | ||
325 | return -1; | ||
326 | } | ||
327 | if ((opt = opt_dequote(optsp, &errstr)) == NULL) { | ||
328 | return -1; | ||
329 | } | ||
330 | if (allow_bare_port && strchr(opt, ':') == NULL) { | ||
331 | /* | ||
332 | * Allow a bare port number in permitlisten to indicate a | ||
333 | * listen_host wildcard. | ||
334 | */ | ||
335 | if (asprintf(&tmp, "*:%s", opt) < 0) { | ||
336 | *errstrp = "memory allocation failed"; | ||
337 | return -1; | ||
338 | } | ||
339 | free(opt); | ||
340 | opt = tmp; | ||
341 | } | ||
342 | if ((tmp = strdup(opt)) == NULL) { | ||
343 | free(opt); | ||
344 | *errstrp = "memory allocation failed"; | ||
345 | return -1; | ||
346 | } | ||
347 | cp = tmp; | ||
348 | /* validate syntax before recording it. */ | ||
349 | host = hpdelim(&cp); | ||
350 | if (host == NULL || strlen(host) >= NI_MAXHOST) { | ||
351 | free(tmp); | ||
352 | free(opt); | ||
353 | *errstrp = "invalid permission hostname"; | ||
354 | return -1; | ||
355 | } | ||
356 | /* | ||
357 | * don't want to use permitopen_port to avoid | ||
358 | * dependency on channels.[ch] here. | ||
359 | */ | ||
360 | if (cp == NULL || | ||
361 | (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) { | ||
362 | free(tmp); | ||
363 | free(opt); | ||
364 | *errstrp = "invalid permission port"; | ||
365 | return -1; | ||
366 | } | ||
367 | /* XXX - add streamlocal support */ | ||
368 | free(tmp); | ||
369 | /* Record it */ | ||
370 | if ((permits = recallocarray(permits, npermits, npermits + 1, | ||
371 | sizeof(*permits))) == NULL) { | ||
372 | free(opt); | ||
373 | /* NB. don't update *permitsp if alloc fails */ | ||
374 | *errstrp = "memory allocation failed"; | ||
375 | return -1; | ||
376 | } | ||
377 | permits[npermits++] = opt; | ||
378 | *permitsp = permits; | ||
379 | *npermitsp = npermits; | ||
380 | return 0; | ||
381 | } | ||
382 | |||
307 | struct sshauthopt * | 383 | struct sshauthopt * |
308 | sshauthopt_parse(const char *opts, const char **errstrp) | 384 | sshauthopt_parse(const char *opts, const char **errstrp) |
309 | { | 385 | { |
310 | char **oarray, *opt, *cp, *tmp, *host; | 386 | char **oarray, *opt, *cp, *tmp; |
311 | int r; | 387 | int r; |
312 | struct sshauthopt *ret = NULL; | 388 | struct sshauthopt *ret = NULL; |
313 | const char *errstr = "unknown error"; | 389 | const char *errstr = "unknown error"; |
@@ -410,48 +486,13 @@ sshauthopt_parse(const char *opts, const char **errstrp) | |||
410 | } | 486 | } |
411 | ret->env[ret->nenv++] = opt; | 487 | ret->env[ret->nenv++] = opt; |
412 | } else if (opt_match(&opts, "permitopen")) { | 488 | } else if (opt_match(&opts, "permitopen")) { |
413 | if (ret->npermitopen > INT_MAX) { | 489 | if (handle_permit(&opts, 0, &ret->permitopen, |
414 | errstr = "too many permitopens"; | 490 | &ret->npermitopen, &errstr) != 0) |
415 | goto fail; | ||
416 | } | ||
417 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) | ||
418 | goto fail; | ||
419 | if ((tmp = strdup(opt)) == NULL) { | ||
420 | free(opt); | ||
421 | goto alloc_fail; | ||
422 | } | ||
423 | cp = tmp; | ||
424 | /* validate syntax of permitopen before recording it. */ | ||
425 | host = hpdelim(&cp); | ||
426 | if (host == NULL || strlen(host) >= NI_MAXHOST) { | ||
427 | free(tmp); | ||
428 | free(opt); | ||
429 | errstr = "invalid permitopen hostname"; | ||
430 | goto fail; | 491 | goto fail; |
431 | } | 492 | } else if (opt_match(&opts, "permitlisten")) { |
432 | /* | 493 | if (handle_permit(&opts, 1, &ret->permitlisten, |
433 | * don't want to use permitopen_port to avoid | 494 | &ret->npermitlisten, &errstr) != 0) |
434 | * dependency on channels.[ch] here. | ||
435 | */ | ||
436 | if (cp == NULL || | ||
437 | (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) { | ||
438 | free(tmp); | ||
439 | free(opt); | ||
440 | errstr = "invalid permitopen port"; | ||
441 | goto fail; | 495 | goto fail; |
442 | } | ||
443 | /* XXX - add streamlocal support */ | ||
444 | free(tmp); | ||
445 | /* Record it */ | ||
446 | oarray = ret->permitopen; | ||
447 | if ((ret->permitopen = recallocarray(ret->permitopen, | ||
448 | ret->npermitopen, ret->npermitopen + 1, | ||
449 | sizeof(*ret->permitopen))) == NULL) { | ||
450 | free(opt); | ||
451 | ret->permitopen = oarray; | ||
452 | goto alloc_fail; | ||
453 | } | ||
454 | ret->permitopen[ret->npermitopen++] = opt; | ||
455 | } else if (opt_match(&opts, "tunnel")) { | 496 | } else if (opt_match(&opts, "tunnel")) { |
456 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) | 497 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) |
457 | goto fail; | 498 | goto fail; |
@@ -554,7 +595,10 @@ sshauthopt_merge(const struct sshauthopt *primary, | |||
554 | if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) | 595 | if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) |
555 | goto alloc_fail; | 596 | goto alloc_fail; |
556 | 597 | ||
557 | /* force_tun_device, permitopen and environment prefer the primary. */ | 598 | /* |
599 | * force_tun_device, permitopen/permitlisten and environment all | ||
600 | * prefer the primary. | ||
601 | */ | ||
558 | ret->force_tun_device = primary->force_tun_device; | 602 | ret->force_tun_device = primary->force_tun_device; |
559 | if (ret->force_tun_device == -1) | 603 | if (ret->force_tun_device == -1) |
560 | ret->force_tun_device = additional->force_tun_device; | 604 | ret->force_tun_device = additional->force_tun_device; |
@@ -577,6 +621,16 @@ sshauthopt_merge(const struct sshauthopt *primary, | |||
577 | goto alloc_fail; | 621 | goto alloc_fail; |
578 | } | 622 | } |
579 | 623 | ||
624 | if (primary->npermitlisten > 0) { | ||
625 | if (dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
626 | primary->permitlisten, primary->npermitlisten) != 0) | ||
627 | goto alloc_fail; | ||
628 | } else if (additional->npermitlisten > 0) { | ||
629 | if (dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
630 | additional->permitlisten, additional->npermitlisten) != 0) | ||
631 | goto alloc_fail; | ||
632 | } | ||
633 | |||
580 | /* Flags are logical-AND (i.e. must be set in both for permission) */ | 634 | /* Flags are logical-AND (i.e. must be set in both for permission) */ |
581 | #define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) | 635 | #define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) |
582 | OPTFLAG(permit_port_forwarding_flag); | 636 | OPTFLAG(permit_port_forwarding_flag); |
@@ -669,7 +723,9 @@ sshauthopt_copy(const struct sshauthopt *orig) | |||
669 | 723 | ||
670 | if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || | 724 | if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || |
671 | dup_strings(&ret->permitopen, &ret->npermitopen, | 725 | dup_strings(&ret->permitopen, &ret->npermitopen, |
672 | orig->permitopen, orig->npermitopen) != 0) { | 726 | orig->permitopen, orig->npermitopen) != 0 || |
727 | dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
728 | orig->permitlisten, orig->npermitlisten) != 0) { | ||
673 | sshauthopt_free(ret); | 729 | sshauthopt_free(ret); |
674 | return NULL; | 730 | return NULL; |
675 | } | 731 | } |
@@ -805,7 +861,9 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, | |||
805 | if ((r = serialise_array(m, opts->env, | 861 | if ((r = serialise_array(m, opts->env, |
806 | untrusted ? 0 : opts->nenv)) != 0 || | 862 | untrusted ? 0 : opts->nenv)) != 0 || |
807 | (r = serialise_array(m, opts->permitopen, | 863 | (r = serialise_array(m, opts->permitopen, |
808 | untrusted ? 0 : opts->npermitopen)) != 0) | 864 | untrusted ? 0 : opts->npermitopen)) != 0 || |
865 | (r = serialise_array(m, opts->permitlisten, | ||
866 | untrusted ? 0 : opts->npermitlisten)) != 0) | ||
809 | return r; | 867 | return r; |
810 | 868 | ||
811 | /* success */ | 869 | /* success */ |
@@ -859,7 +917,9 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp) | |||
859 | /* Array options */ | 917 | /* Array options */ |
860 | if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 || | 918 | if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 || |
861 | (r = deserialise_array(m, | 919 | (r = deserialise_array(m, |
862 | &opts->permitopen, &opts->npermitopen)) != 0) | 920 | &opts->permitopen, &opts->npermitopen)) != 0 || |
921 | (r = deserialise_array(m, | ||
922 | &opts->permitlisten, &opts->npermitlisten)) != 0) | ||
863 | goto out; | 923 | goto out; |
864 | 924 | ||
865 | /* success */ | 925 | /* success */ |