summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-06-06 18:22:41 +0000
committerDamien Miller <djm@mindrot.org>2018-06-07 04:27:20 +1000
commit115063a6647007286cc8ca70abfd2a7585f26ccc (patch)
tree7bd8d46ae55ff7fc1f8699740d2d2e106c3d5fe8 /servconf.c
parent7703ae5f5d42eb302ded51705166ff6e19c92892 (diff)
upstream: Add a PermitListen directive to control which server-side
addresses may be listened on when the client requests remote forwarding (ssh -R). This is the converse of the existing PermitOpen directive and this includes some refactoring to share much of its implementation. feedback and ok markus@ OpenBSD-Commit-ID: 15a931238c61a3f2ac74ea18a98c933e358e277f
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c138
1 files changed, 90 insertions, 48 deletions
diff --git a/servconf.c b/servconf.c
index 5ca84515f..b75faf3f8 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.328 2018/04/10 00:10:49 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.329 2018/06/06 18:22:41 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,6 +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->adm_forced_command = NULL; 164 options->adm_forced_command = NULL;
164 options->chroot_directory = NULL; 165 options->chroot_directory = NULL;
165 options->authorized_keys_command = NULL; 166 options->authorized_keys_command = NULL;
@@ -462,7 +463,7 @@ typedef enum {
462 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 463 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
463 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 464 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
464 sAcceptEnv, sPermitTunnel, 465 sAcceptEnv, sPermitTunnel,
465 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 466 sMatch, sPermitOpen, sPermitRemoteOpen, sForceCommand, sChrootDirectory,
466 sUsePrivilegeSeparation, sAllowAgentForwarding, 467 sUsePrivilegeSeparation, sAllowAgentForwarding,
467 sHostCertificate, 468 sHostCertificate,
468 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 469 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
@@ -597,6 +598,7 @@ static struct {
597 { "permituserrc", sPermitUserRC, SSHCFG_ALL }, 598 { "permituserrc", sPermitUserRC, SSHCFG_ALL },
598 { "match", sMatch, SSHCFG_ALL }, 599 { "match", sMatch, SSHCFG_ALL },
599 { "permitopen", sPermitOpen, SSHCFG_ALL }, 600 { "permitopen", sPermitOpen, SSHCFG_ALL },
601 { "permitremoteopen", sPermitRemoteOpen, SSHCFG_ALL },
600 { "forcecommand", sForceCommand, SSHCFG_ALL }, 602 { "forcecommand", sForceCommand, SSHCFG_ALL },
601 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, 603 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
602 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, 604 { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
@@ -632,6 +634,20 @@ static struct {
632 { -1, NULL } 634 { -1, NULL }
633}; 635};
634 636
637/* Returns an opcode name from its number */
638
639static const char *
640lookup_opcode_name(ServerOpCodes code)
641{
642 u_int i;
643
644 for (i = 0; keywords[i].name != NULL; i++)
645 if (keywords[i].opcode == code)
646 return(keywords[i].name);
647 return "UNKNOWN";
648}
649
650
635/* 651/*
636 * Returns the number of the token pointed to by cp or sBadOption. 652 * Returns the number of the token pointed to by cp or sBadOption.
637 */ 653 */
@@ -814,43 +830,59 @@ process_queued_listen_addrs(ServerOptions *options)
814} 830}
815 831
816/* 832/*
817 * Inform channels layer of permitopen options from configuration. 833 * Inform channels layer of permitopen options for a single forwarding
834 * direction (local/remote).
818 */ 835 */
819void 836static void
820process_permitopen(struct ssh *ssh, ServerOptions *options) 837process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
838 char **opens, u_int num_opens)
821{ 839{
822 u_int i; 840 u_int i;
823 int port; 841 int port;
824 char *host, *arg, *oarg; 842 char *host, *arg, *oarg;
843 int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
844 const char *what = lookup_opcode_name(opcode);
825 845
826 channel_clear_adm_permitted_opens(ssh); 846 channel_clear_permission(ssh, FORWARD_ADM, where);
827 if (options->num_permitted_opens == 0) 847 if (num_opens == 0)
828 return; /* permit any */ 848 return; /* permit any */
829 849
830 /* handle keywords: "any" / "none" */ 850 /* handle keywords: "any" / "none" */
831 if (options->num_permitted_opens == 1 && 851 if (num_opens == 1 && strcmp(opens[0], "any") == 0)
832 strcmp(options->permitted_opens[0], "any") == 0)
833 return; 852 return;
834 if (options->num_permitted_opens == 1 && 853 if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
835 strcmp(options->permitted_opens[0], "none") == 0) { 854 channel_disable_admin(ssh, where);
836 channel_disable_adm_local_opens(ssh);
837 return; 855 return;
838 } 856 }
839 /* Otherwise treat it as a list of permitted host:port */ 857 /* Otherwise treat it as a list of permitted host:port */
840 for (i = 0; i < options->num_permitted_opens; i++) { 858 for (i = 0; i < num_opens; i++) {
841 oarg = arg = xstrdup(options->permitted_opens[i]); 859 oarg = arg = xstrdup(opens[i]);
842 host = hpdelim(&arg); 860 host = hpdelim(&arg);
843 if (host == NULL) 861 if (host == NULL)
844 fatal("%s: missing host in PermitOpen", __func__); 862 fatal("%s: missing host in %s", __func__, what);
845 host = cleanhostname(host); 863 host = cleanhostname(host);
846 if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 864 if (arg == NULL || ((port = permitopen_port(arg)) < 0))
847 fatal("%s: bad port number in PermitOpen", __func__); 865 fatal("%s: bad port number in %s", __func__, what);
848 /* Send it to channels layer */ 866 /* Send it to channels layer */
849 channel_add_adm_permitted_opens(ssh, host, port); 867 channel_add_permission(ssh, FORWARD_ADM,
868 where, host, port);
850 free(oarg); 869 free(oarg);
851 } 870 }
852} 871}
853 872
873/*
874 * Inform channels layer of permitopen options from configuration.
875 */
876void
877process_permitopen(struct ssh *ssh, ServerOptions *options)
878{
879 process_permitopen_list(ssh, sPermitOpen,
880 options->permitted_opens, options->num_permitted_opens);
881 process_permitopen_list(ssh, sPermitRemoteOpen,
882 options->permitted_remote_opens,
883 options->num_permitted_remote_opens);
884}
885
854struct connection_info * 886struct connection_info *
855get_connection_info(int populate, int use_dns) 887get_connection_info(int populate, int use_dns)
856{ 888{
@@ -1144,12 +1176,12 @@ process_server_config_line(ServerOptions *options, char *line,
1144 const char *filename, int linenum, int *activep, 1176 const char *filename, int linenum, int *activep,
1145 struct connection_info *connectinfo) 1177 struct connection_info *connectinfo)
1146{ 1178{
1147 char *cp, **charptr, *arg, *arg2, *p; 1179 char *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
1148 int cmdline = 0, *intptr, value, value2, n, port; 1180 int cmdline = 0, *intptr, value, value2, n, port;
1149 SyslogFacility *log_facility_ptr; 1181 SyslogFacility *log_facility_ptr;
1150 LogLevel *log_level_ptr; 1182 LogLevel *log_level_ptr;
1151 ServerOpCodes opcode; 1183 ServerOpCodes opcode;
1152 u_int i, flags = 0; 1184 u_int i, *uintptr, uvalue, flags = 0;
1153 size_t len; 1185 size_t len;
1154 long long val64; 1186 long long val64;
1155 const struct multistate *multistate_ptr; 1187 const struct multistate *multistate_ptr;
@@ -1799,36 +1831,49 @@ process_server_config_line(ServerOptions *options, char *line,
1799 *activep = value; 1831 *activep = value;
1800 break; 1832 break;
1801 1833
1834 case sPermitRemoteOpen:
1802 case sPermitOpen: 1835 case sPermitOpen:
1836 if (opcode == sPermitRemoteOpen) {
1837 uintptr = &options->num_permitted_remote_opens;
1838 chararrayptr = &options->permitted_remote_opens;
1839 } else {
1840 uintptr = &options->num_permitted_opens;
1841 chararrayptr = &options->permitted_opens;
1842 }
1803 arg = strdelim(&cp); 1843 arg = strdelim(&cp);
1804 if (!arg || *arg == '\0') 1844 if (!arg || *arg == '\0')
1805 fatal("%s line %d: missing PermitOpen specification", 1845 fatal("%s line %d: missing %s specification",
1806 filename, linenum); 1846 filename, linenum, lookup_opcode_name(opcode));
1807 value = options->num_permitted_opens; /* modified later */ 1847 uvalue = *uintptr; /* modified later */
1808 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { 1848 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
1809 if (*activep && value == 0) { 1849 if (*activep && uvalue == 0) {
1810 options->num_permitted_opens = 1; 1850 *uintptr = 1;
1811 options->permitted_opens = xcalloc(1, 1851 *chararrayptr = xcalloc(1,
1812 sizeof(*options->permitted_opens)); 1852 sizeof(**chararrayptr));
1813 options->permitted_opens[0] = xstrdup(arg); 1853 (*chararrayptr)[0] = xstrdup(arg);
1814 } 1854 }
1815 break; 1855 break;
1816 } 1856 }
1817 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { 1857 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1818 arg2 = xstrdup(arg); 1858 arg2 = xstrdup(arg);
1819 p = hpdelim(&arg); 1859 p = hpdelim(&arg);
1820 if (p == NULL) 1860 /* XXX support bare port number for PermitRemoteOpen */
1821 fatal("%s line %d: missing host in PermitOpen", 1861 if (p == NULL) {
1822 filename, linenum); 1862 fatal("%s line %d: missing host in %s",
1863 filename, linenum,
1864 lookup_opcode_name(opcode));
1865 }
1823 p = cleanhostname(p); 1866 p = cleanhostname(p);
1824 if (arg == NULL || ((port = permitopen_port(arg)) < 0)) 1867 if (arg == NULL ||
1825 fatal("%s line %d: bad port number in " 1868 ((port = permitopen_port(arg)) < 0)) {
1826 "PermitOpen", filename, linenum); 1869 fatal("%s line %d: bad port number in %s",
1827 if (*activep && value == 0) { 1870 filename, linenum,
1871 lookup_opcode_name(opcode));
1872 }
1873 if (*activep && uvalue == 0) {
1828 array_append(filename, linenum, 1874 array_append(filename, linenum,
1829 "PermitOpen", 1875 lookup_opcode_name(opcode),
1830 &options->permitted_opens, 1876 chararrayptr, uintptr, arg2);
1831 &options->num_permitted_opens, arg2);
1832 } 1877 }
1833 free(arg2); 1878 free(arg2);
1834 } 1879 }
@@ -2307,17 +2352,6 @@ fmt_intarg(ServerOpCodes code, int val)
2307 } 2352 }
2308} 2353}
2309 2354
2310static const char *
2311lookup_opcode_name(ServerOpCodes code)
2312{
2313 u_int i;
2314
2315 for (i = 0; keywords[i].name != NULL; i++)
2316 if (keywords[i].opcode == code)
2317 return(keywords[i].name);
2318 return "UNKNOWN";
2319}
2320
2321static void 2355static void
2322dump_cfg_int(ServerOpCodes code, int val) 2356dump_cfg_int(ServerOpCodes code, int val)
2323{ 2357{
@@ -2562,4 +2596,12 @@ dump_config(ServerOptions *o)
2562 printf(" %s", o->permitted_opens[i]); 2596 printf(" %s", o->permitted_opens[i]);
2563 } 2597 }
2564 printf("\n"); 2598 printf("\n");
2599 printf("permitremoteopen");
2600 if (o->num_permitted_remote_opens == 0)
2601 printf(" any");
2602 else {
2603 for (i = 0; i < o->num_permitted_remote_opens; i++)
2604 printf(" %s", o->permitted_remote_opens[i]);
2605 }
2606 printf("\n");
2565} 2607}