diff options
author | djm@openbsd.org <djm@openbsd.org> | 2018-06-06 18:23:32 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2018-06-07 04:27:20 +1000 |
commit | 93c06ab6b77514e0447fe4f1d822afcbb2a9be08 (patch) | |
tree | 86b19179eaa51962f0dae9ab02d6d37197942265 | |
parent | 115063a6647007286cc8ca70abfd2a7585f26ccc (diff) |
upstream: permitlisten option for authorized_keys; ok markus@
OpenBSD-Commit-ID: 8650883018d7aa893173d703379e4456a222c672
-rw-r--r-- | auth-options.c | 140 | ||||
-rw-r--r-- | auth-options.h | 6 | ||||
-rw-r--r-- | auth.c | 15 | ||||
-rw-r--r-- | servconf.c | 32 | ||||
-rw-r--r-- | servconf.h | 9 | ||||
-rw-r--r-- | session.c | 52 |
6 files changed, 165 insertions, 89 deletions
diff --git a/auth-options.c b/auth-options.c index ef57ebf43..c55c3ed06 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.80 2018/06/06 18:23:32 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,70 @@ 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 *opts, char ***permitsp, size_t *npermitsp, | ||
317 | 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(&opts, &errstr)) == NULL) { | ||
328 | return -1; | ||
329 | } | ||
330 | if ((tmp = strdup(opt)) == NULL) { | ||
331 | free(opt); | ||
332 | *errstrp = "memory allocation failed"; | ||
333 | return -1; | ||
334 | } | ||
335 | cp = tmp; | ||
336 | /* validate syntax before recording it. */ | ||
337 | host = hpdelim(&cp); | ||
338 | if (host == NULL || strlen(host) >= NI_MAXHOST) { | ||
339 | free(tmp); | ||
340 | free(opt); | ||
341 | *errstrp = "invalid permission hostname"; | ||
342 | return -1; | ||
343 | } | ||
344 | /* | ||
345 | * don't want to use permitopen_port to avoid | ||
346 | * dependency on channels.[ch] here. | ||
347 | */ | ||
348 | if (cp == NULL || | ||
349 | (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) { | ||
350 | free(tmp); | ||
351 | free(opt); | ||
352 | *errstrp = "invalid permission port"; | ||
353 | return -1; | ||
354 | } | ||
355 | /* XXX - add streamlocal support */ | ||
356 | free(tmp); | ||
357 | /* Record it */ | ||
358 | if ((permits = recallocarray(permits, npermits, npermits + 1, | ||
359 | sizeof(*permits))) == NULL) { | ||
360 | free(opt); | ||
361 | /* NB. don't update *permitsp if alloc fails */ | ||
362 | *errstrp = "memory allocation failed"; | ||
363 | return -1; | ||
364 | } | ||
365 | permits[npermits++] = opt; | ||
366 | *permitsp = permits; | ||
367 | *npermitsp = npermits; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
307 | struct sshauthopt * | 371 | struct sshauthopt * |
308 | sshauthopt_parse(const char *opts, const char **errstrp) | 372 | sshauthopt_parse(const char *opts, const char **errstrp) |
309 | { | 373 | { |
310 | char **oarray, *opt, *cp, *tmp, *host; | 374 | char **oarray, *opt, *cp, *tmp; |
311 | int r; | 375 | int r; |
312 | struct sshauthopt *ret = NULL; | 376 | struct sshauthopt *ret = NULL; |
313 | const char *errstr = "unknown error"; | 377 | const char *errstr = "unknown error"; |
@@ -410,48 +474,13 @@ sshauthopt_parse(const char *opts, const char **errstrp) | |||
410 | } | 474 | } |
411 | ret->env[ret->nenv++] = opt; | 475 | ret->env[ret->nenv++] = opt; |
412 | } else if (opt_match(&opts, "permitopen")) { | 476 | } else if (opt_match(&opts, "permitopen")) { |
413 | if (ret->npermitopen > INT_MAX) { | 477 | if (handle_permit(opts, &ret->permitopen, |
414 | errstr = "too many permitopens"; | 478 | &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; | 479 | goto fail; |
431 | } | 480 | } else if (opt_match(&opts, "permitlisten")) { |
432 | /* | 481 | if (handle_permit(opts, &ret->permitlisten, |
433 | * don't want to use permitopen_port to avoid | 482 | &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; | 483 | 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")) { | 484 | } else if (opt_match(&opts, "tunnel")) { |
456 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) | 485 | if ((opt = opt_dequote(&opts, &errstr)) == NULL) |
457 | goto fail; | 486 | goto fail; |
@@ -554,7 +583,10 @@ sshauthopt_merge(const struct sshauthopt *primary, | |||
554 | if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) | 583 | if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) |
555 | goto alloc_fail; | 584 | goto alloc_fail; |
556 | 585 | ||
557 | /* force_tun_device, permitopen and environment prefer the primary. */ | 586 | /* |
587 | * force_tun_device, permitopen/permitlisten and environment all | ||
588 | * prefer the primary. | ||
589 | */ | ||
558 | ret->force_tun_device = primary->force_tun_device; | 590 | ret->force_tun_device = primary->force_tun_device; |
559 | if (ret->force_tun_device == -1) | 591 | if (ret->force_tun_device == -1) |
560 | ret->force_tun_device = additional->force_tun_device; | 592 | ret->force_tun_device = additional->force_tun_device; |
@@ -577,6 +609,16 @@ sshauthopt_merge(const struct sshauthopt *primary, | |||
577 | goto alloc_fail; | 609 | goto alloc_fail; |
578 | } | 610 | } |
579 | 611 | ||
612 | if (primary->npermitlisten > 0) { | ||
613 | if (dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
614 | primary->permitlisten, primary->npermitlisten) != 0) | ||
615 | goto alloc_fail; | ||
616 | } else if (additional->npermitlisten > 0) { | ||
617 | if (dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
618 | additional->permitlisten, additional->npermitlisten) != 0) | ||
619 | goto alloc_fail; | ||
620 | } | ||
621 | |||
580 | /* Flags are logical-AND (i.e. must be set in both for permission) */ | 622 | /* 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) | 623 | #define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) |
582 | OPTFLAG(permit_port_forwarding_flag); | 624 | OPTFLAG(permit_port_forwarding_flag); |
@@ -669,7 +711,9 @@ sshauthopt_copy(const struct sshauthopt *orig) | |||
669 | 711 | ||
670 | if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || | 712 | if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || |
671 | dup_strings(&ret->permitopen, &ret->npermitopen, | 713 | dup_strings(&ret->permitopen, &ret->npermitopen, |
672 | orig->permitopen, orig->npermitopen) != 0) { | 714 | orig->permitopen, orig->npermitopen) != 0 || |
715 | dup_strings(&ret->permitlisten, &ret->npermitlisten, | ||
716 | orig->permitlisten, orig->npermitlisten) != 0) { | ||
673 | sshauthopt_free(ret); | 717 | sshauthopt_free(ret); |
674 | return NULL; | 718 | return NULL; |
675 | } | 719 | } |
@@ -805,7 +849,9 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, | |||
805 | if ((r = serialise_array(m, opts->env, | 849 | if ((r = serialise_array(m, opts->env, |
806 | untrusted ? 0 : opts->nenv)) != 0 || | 850 | untrusted ? 0 : opts->nenv)) != 0 || |
807 | (r = serialise_array(m, opts->permitopen, | 851 | (r = serialise_array(m, opts->permitopen, |
808 | untrusted ? 0 : opts->npermitopen)) != 0) | 852 | untrusted ? 0 : opts->npermitopen)) || |
853 | (r = serialise_array(m, opts->permitlisten, | ||
854 | untrusted ? 0 : opts->npermitlisten)) != 0) | ||
809 | return r; | 855 | return r; |
810 | 856 | ||
811 | /* success */ | 857 | /* success */ |
@@ -859,7 +905,9 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp) | |||
859 | /* Array options */ | 905 | /* Array options */ |
860 | if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 || | 906 | if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 || |
861 | (r = deserialise_array(m, | 907 | (r = deserialise_array(m, |
862 | &opts->permitopen, &opts->npermitopen)) != 0) | 908 | &opts->permitopen, &opts->npermitopen)) != 0 || |
909 | (r = deserialise_array(m, | ||
910 | &opts->permitlisten, &opts->npermitlisten)) != 0) | ||
863 | goto out; | 911 | goto out; |
864 | 912 | ||
865 | /* success */ | 913 | /* success */ |
diff --git a/auth-options.h b/auth-options.h index bf59b30be..0462983b5 100644 --- a/auth-options.h +++ b/auth-options.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.h,v 1.26 2018/03/12 00:52:01 djm Exp $ */ | 1 | /* $OpenBSD: auth-options.h,v 1.27 2018/06/06 18:23:32 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> | 4 | * Copyright (c) 2018 Damien Miller <djm@mindrot.org> |
@@ -55,6 +55,10 @@ struct sshauthopt { | |||
55 | size_t npermitopen; | 55 | size_t npermitopen; |
56 | char **permitopen; | 56 | char **permitopen; |
57 | 57 | ||
58 | /* Permitted listens (remote forwarding) */ | ||
59 | size_t npermitlisten; | ||
60 | char **permitlisten; | ||
61 | |||
58 | /* | 62 | /* |
59 | * Permitted host/addresses (comma-separated) | 63 | * Permitted host/addresses (comma-separated) |
60 | * Caller must check source address matches both lists (if present). | 64 | * Caller must check source address matches both lists (if present). |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.129 2018/06/01 03:33:53 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.130 2018/06/06 18:23:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -1005,17 +1005,20 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) | |||
1005 | int do_env = options.permit_user_env && opts->nenv > 0; | 1005 | int do_env = options.permit_user_env && opts->nenv > 0; |
1006 | int do_permitopen = opts->npermitopen > 0 && | 1006 | int do_permitopen = opts->npermitopen > 0 && |
1007 | (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0; | 1007 | (options.allow_tcp_forwarding & FORWARD_LOCAL) != 0; |
1008 | int do_permitlisten = opts->npermitlisten > 0 && | ||
1009 | (options.allow_tcp_forwarding & FORWARD_REMOTE) != 0; | ||
1008 | size_t i; | 1010 | size_t i; |
1009 | char msg[1024], buf[64]; | 1011 | char msg[1024], buf[64]; |
1010 | 1012 | ||
1011 | snprintf(buf, sizeof(buf), "%d", opts->force_tun_device); | 1013 | snprintf(buf, sizeof(buf), "%d", opts->force_tun_device); |
1012 | /* Try to keep this alphabetically sorted */ | 1014 | /* Try to keep this alphabetically sorted */ |
1013 | snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s", | 1015 | snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s", |
1014 | opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", | 1016 | opts->permit_agent_forwarding_flag ? " agent-forwarding" : "", |
1015 | opts->force_command == NULL ? "" : " command", | 1017 | opts->force_command == NULL ? "" : " command", |
1016 | do_env ? " environment" : "", | 1018 | do_env ? " environment" : "", |
1017 | opts->valid_before == 0 ? "" : "expires", | 1019 | opts->valid_before == 0 ? "" : "expires", |
1018 | do_permitopen ? " permitopen" : "", | 1020 | do_permitopen ? " permitopen" : "", |
1021 | do_permitlisten ? " permitlisten" : "", | ||
1019 | opts->permit_port_forwarding_flag ? " port-forwarding" : "", | 1022 | opts->permit_port_forwarding_flag ? " port-forwarding" : "", |
1020 | opts->cert_principals == NULL ? "" : " principals", | 1023 | opts->cert_principals == NULL ? "" : " principals", |
1021 | opts->permit_pty_flag ? " pty" : "", | 1024 | opts->permit_pty_flag ? " pty" : "", |
@@ -1049,12 +1052,18 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) | |||
1049 | } | 1052 | } |
1050 | if (opts->force_command != NULL) | 1053 | if (opts->force_command != NULL) |
1051 | debug("%s: forced command: \"%s\"", loc, opts->force_command); | 1054 | debug("%s: forced command: \"%s\"", loc, opts->force_command); |
1052 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) { | 1055 | if (do_permitopen) { |
1053 | for (i = 0; i < opts->npermitopen; i++) { | 1056 | for (i = 0; i < opts->npermitopen; i++) { |
1054 | debug("%s: permitted open: %s", | 1057 | debug("%s: permitted open: %s", |
1055 | loc, opts->permitopen[i]); | 1058 | loc, opts->permitopen[i]); |
1056 | } | 1059 | } |
1057 | } | 1060 | } |
1061 | if (do_permitlisten) { | ||
1062 | for (i = 0; i < opts->npermitlisten; i++) { | ||
1063 | debug("%s: permitted listen: %s", | ||
1064 | loc, opts->permitlisten[i]); | ||
1065 | } | ||
1066 | } | ||
1058 | } | 1067 | } |
1059 | 1068 | ||
1060 | /* Activate a new set of key/cert options; merging with what is there. */ | 1069 | /* Activate a new set of key/cert options; merging with what is there. */ |
diff --git a/servconf.c b/servconf.c index b75faf3f8..3c41490b3 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | /* $OpenBSD: servconf.c,v 1.329 2018/06/06 18:22:41 djm Exp $ */ | 2 | /* $OpenBSD: servconf.c,v 1.330 2018/06/06 18:23:32 djm Exp $ */ |
3 | /* | 3 | /* |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
5 | * All rights reserved | 5 | * All rights reserved |
@@ -160,7 +160,7 @@ initialize_server_options(ServerOptions *options) | |||
160 | options->num_accept_env = 0; | 160 | options->num_accept_env = 0; |
161 | options->permit_tun = -1; | 161 | options->permit_tun = -1; |
162 | options->permitted_opens = NULL; | 162 | options->permitted_opens = NULL; |
163 | options->permitted_remote_opens = NULL; | 163 | options->permitted_listens = NULL; |
164 | options->adm_forced_command = NULL; | 164 | options->adm_forced_command = NULL; |
165 | options->chroot_directory = NULL; | 165 | options->chroot_directory = NULL; |
166 | options->authorized_keys_command = NULL; | 166 | options->authorized_keys_command = NULL; |
@@ -463,7 +463,7 @@ typedef enum { | |||
463 | sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, | 463 | sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, |
464 | sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, | 464 | sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, |
465 | sAcceptEnv, sPermitTunnel, | 465 | sAcceptEnv, sPermitTunnel, |
466 | sMatch, sPermitOpen, sPermitRemoteOpen, sForceCommand, sChrootDirectory, | 466 | sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, |
467 | sUsePrivilegeSeparation, sAllowAgentForwarding, | 467 | sUsePrivilegeSeparation, sAllowAgentForwarding, |
468 | sHostCertificate, | 468 | sHostCertificate, |
469 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, | 469 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
@@ -598,7 +598,7 @@ static struct { | |||
598 | { "permituserrc", sPermitUserRC, SSHCFG_ALL }, | 598 | { "permituserrc", sPermitUserRC, SSHCFG_ALL }, |
599 | { "match", sMatch, SSHCFG_ALL }, | 599 | { "match", sMatch, SSHCFG_ALL }, |
600 | { "permitopen", sPermitOpen, SSHCFG_ALL }, | 600 | { "permitopen", sPermitOpen, SSHCFG_ALL }, |
601 | { "permitremoteopen", sPermitRemoteOpen, SSHCFG_ALL }, | 601 | { "permitlisten", sPermitListen, SSHCFG_ALL }, |
602 | { "forcecommand", sForceCommand, SSHCFG_ALL }, | 602 | { "forcecommand", sForceCommand, SSHCFG_ALL }, |
603 | { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, | 603 | { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, |
604 | { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, | 604 | { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, |
@@ -878,9 +878,9 @@ process_permitopen(struct ssh *ssh, ServerOptions *options) | |||
878 | { | 878 | { |
879 | process_permitopen_list(ssh, sPermitOpen, | 879 | process_permitopen_list(ssh, sPermitOpen, |
880 | options->permitted_opens, options->num_permitted_opens); | 880 | options->permitted_opens, options->num_permitted_opens); |
881 | process_permitopen_list(ssh, sPermitRemoteOpen, | 881 | process_permitopen_list(ssh, sPermitListen, |
882 | options->permitted_remote_opens, | 882 | options->permitted_listens, |
883 | options->num_permitted_remote_opens); | 883 | options->num_permitted_listens); |
884 | } | 884 | } |
885 | 885 | ||
886 | struct connection_info * | 886 | struct connection_info * |
@@ -1831,11 +1831,11 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1831 | *activep = value; | 1831 | *activep = value; |
1832 | break; | 1832 | break; |
1833 | 1833 | ||
1834 | case sPermitRemoteOpen: | 1834 | case sPermitListen: |
1835 | case sPermitOpen: | 1835 | case sPermitOpen: |
1836 | if (opcode == sPermitRemoteOpen) { | 1836 | if (opcode == sPermitListen) { |
1837 | uintptr = &options->num_permitted_remote_opens; | 1837 | uintptr = &options->num_permitted_listens; |
1838 | chararrayptr = &options->permitted_remote_opens; | 1838 | chararrayptr = &options->permitted_listens; |
1839 | } else { | 1839 | } else { |
1840 | uintptr = &options->num_permitted_opens; | 1840 | uintptr = &options->num_permitted_opens; |
1841 | chararrayptr = &options->permitted_opens; | 1841 | chararrayptr = &options->permitted_opens; |
@@ -1857,7 +1857,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1857 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { | 1857 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { |
1858 | arg2 = xstrdup(arg); | 1858 | arg2 = xstrdup(arg); |
1859 | p = hpdelim(&arg); | 1859 | p = hpdelim(&arg); |
1860 | /* XXX support bare port number for PermitRemoteOpen */ | 1860 | /* XXX support bare port number for PermitListen */ |
1861 | if (p == NULL) { | 1861 | if (p == NULL) { |
1862 | fatal("%s line %d: missing host in %s", | 1862 | fatal("%s line %d: missing host in %s", |
1863 | filename, linenum, | 1863 | filename, linenum, |
@@ -2596,12 +2596,12 @@ dump_config(ServerOptions *o) | |||
2596 | printf(" %s", o->permitted_opens[i]); | 2596 | printf(" %s", o->permitted_opens[i]); |
2597 | } | 2597 | } |
2598 | printf("\n"); | 2598 | printf("\n"); |
2599 | printf("permitremoteopen"); | 2599 | printf("permitlisten"); |
2600 | if (o->num_permitted_remote_opens == 0) | 2600 | if (o->num_permitted_listens == 0) |
2601 | printf(" any"); | 2601 | printf(" any"); |
2602 | else { | 2602 | else { |
2603 | for (i = 0; i < o->num_permitted_remote_opens; i++) | 2603 | for (i = 0; i < o->num_permitted_listens; i++) |
2604 | printf(" %s", o->permitted_remote_opens[i]); | 2604 | printf(" %s", o->permitted_listens[i]); |
2605 | } | 2605 | } |
2606 | printf("\n"); | 2606 | printf("\n"); |
2607 | } | 2607 | } |
diff --git a/servconf.h b/servconf.h index 62acd8938..450b94ec4 100644 --- a/servconf.h +++ b/servconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: servconf.h,v 1.132 2018/06/06 18:22:41 djm Exp $ */ | 1 | /* $OpenBSD: servconf.h,v 1.133 2018/06/06 18:23:32 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -183,8 +183,8 @@ typedef struct { | |||
183 | 183 | ||
184 | char **permitted_opens; /* May also be one of PERMITOPEN_* */ | 184 | char **permitted_opens; /* May also be one of PERMITOPEN_* */ |
185 | u_int num_permitted_opens; | 185 | u_int num_permitted_opens; |
186 | char **permitted_remote_opens; /* May also be one of PERMITOPEN_* */ | 186 | char **permitted_listens; /* May also be one of PERMITOPEN_* */ |
187 | u_int num_permitted_remote_opens; | 187 | u_int num_permitted_listens; |
188 | 188 | ||
189 | char *chroot_directory; | 189 | char *chroot_directory; |
190 | char *revoked_keys_file; | 190 | char *revoked_keys_file; |
@@ -248,8 +248,7 @@ struct connection_info { | |||
248 | M_CP_STRARRAYOPT(accept_env, num_accept_env); \ | 248 | M_CP_STRARRAYOPT(accept_env, num_accept_env); \ |
249 | M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ | 249 | M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ |
250 | M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ | 250 | M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ |
251 | M_CP_STRARRAYOPT(permitted_remote_opens, \ | 251 | M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \ |
252 | num_permitted_remote_opens); \ | ||
253 | } while (0) | 252 | } while (0) |
254 | 253 | ||
255 | struct connection_info *get_connection_info(int, int); | 254 | struct connection_info *get_connection_info(int, int); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.296 2018/06/06 18:22:41 djm Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.297 2018/06/06 18:23:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -290,27 +290,43 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info) | |||
290 | } | 290 | } |
291 | 291 | ||
292 | static void | 292 | static void |
293 | set_permitopen_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) | 293 | set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) |
294 | { | 294 | { |
295 | char *tmp, *cp, *host; | 295 | char *tmp, *cp, *host; |
296 | int port; | 296 | int port; |
297 | size_t i; | 297 | size_t i; |
298 | 298 | ||
299 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) | 299 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) { |
300 | return; | 300 | channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL); |
301 | channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL); | 301 | for (i = 0; i < auth_opts->npermitopen; i++) { |
302 | for (i = 0; i < auth_opts->npermitopen; i++) { | 302 | tmp = cp = xstrdup(auth_opts->permitopen[i]); |
303 | tmp = cp = xstrdup(auth_opts->permitopen[i]); | 303 | /* This shouldn't fail as it has already been checked */ |
304 | /* This shouldn't fail as it has already been checked */ | 304 | if ((host = hpdelim(&cp)) == NULL) |
305 | if ((host = hpdelim(&cp)) == NULL) | 305 | fatal("%s: internal error: hpdelim", __func__); |
306 | fatal("%s: internal error: hpdelim", __func__); | 306 | host = cleanhostname(host); |
307 | host = cleanhostname(host); | 307 | if (cp == NULL || (port = permitopen_port(cp)) < 0) |
308 | if (cp == NULL || (port = permitopen_port(cp)) < 0) | 308 | fatal("%s: internal error: permitopen port", |
309 | fatal("%s: internal error: permitopen port", | 309 | __func__); |
310 | __func__); | 310 | channel_add_permission(ssh, |
311 | channel_add_permission(ssh, FORWARD_USER, FORWARD_LOCAL, | 311 | FORWARD_USER, FORWARD_LOCAL, host, port); |
312 | host, port); | 312 | free(tmp); |
313 | free(tmp); | 313 | } |
314 | } | ||
315 | if ((options.allow_tcp_forwarding & FORWARD_REMOTE) != 0) { | ||
316 | channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE); | ||
317 | for (i = 0; i < auth_opts->npermitlisten; i++) { | ||
318 | tmp = cp = xstrdup(auth_opts->permitlisten[i]); | ||
319 | /* This shouldn't fail as it has already been checked */ | ||
320 | if ((host = hpdelim(&cp)) == NULL) | ||
321 | fatal("%s: internal error: hpdelim", __func__); | ||
322 | host = cleanhostname(host); | ||
323 | if (cp == NULL || (port = permitopen_port(cp)) < 0) | ||
324 | fatal("%s: internal error: permitlisten port", | ||
325 | __func__); | ||
326 | channel_add_permission(ssh, | ||
327 | FORWARD_USER, FORWARD_REMOTE, host, port); | ||
328 | free(tmp); | ||
329 | } | ||
314 | } | 330 | } |
315 | } | 331 | } |
316 | 332 | ||
@@ -323,7 +339,7 @@ do_authenticated(struct ssh *ssh, Authctxt *authctxt) | |||
323 | 339 | ||
324 | /* setup the channel layer */ | 340 | /* setup the channel layer */ |
325 | /* XXX - streamlocal? */ | 341 | /* XXX - streamlocal? */ |
326 | set_permitopen_from_authopts(ssh, auth_opts); | 342 | set_fwdpermit_from_authopts(ssh, auth_opts); |
327 | 343 | ||
328 | if (!auth_opts->permit_port_forwarding_flag || | 344 | if (!auth_opts->permit_port_forwarding_flag || |
329 | options.disable_forwarding) { | 345 | options.disable_forwarding) { |