summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-06-06 18:23:32 +0000
committerDamien Miller <djm@mindrot.org>2018-06-07 04:27:20 +1000
commit93c06ab6b77514e0447fe4f1d822afcbb2a9be08 (patch)
tree86b19179eaa51962f0dae9ab02d6d37197942265
parent115063a6647007286cc8ca70abfd2a7585f26ccc (diff)
upstream: permitlisten option for authorized_keys; ok markus@
OpenBSD-Commit-ID: 8650883018d7aa893173d703379e4456a222c672
-rw-r--r--auth-options.c140
-rw-r--r--auth-options.h6
-rw-r--r--auth.c15
-rw-r--r--servconf.c32
-rw-r--r--servconf.h9
-rw-r--r--session.c52
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 */
315static int
316handle_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
307struct sshauthopt * 371struct sshauthopt *
308sshauthopt_parse(const char *opts, const char **errstrp) 372sshauthopt_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).
diff --git a/auth.c b/auth.c
index 573cd03b0..0424f1f79 100644
--- a/auth.c
+++ b/auth.c
@@ -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
886struct connection_info * 886struct 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
255struct connection_info *get_connection_info(int, int); 254struct connection_info *get_connection_info(int, int);
diff --git a/session.c b/session.c
index 3a3fd841a..e72fcb0a8 100644
--- a/session.c
+++ b/session.c
@@ -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
292static void 292static void
293set_permitopen_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) 293set_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) {