rpc_server: Allow to configure the port range for RPC services
authorAndreas Schneider <asn@samba.org>
Mon, 16 Jan 2017 11:05:09 +0000 (12:05 +0100)
committerStefan Metzmacher <metze@samba.org>
Fri, 27 Jan 2017 07:09:15 +0000 (08:09 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12521

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
docs-xml/smbdotconf/protocol/rpcserverport.xml
docs-xml/smbdotconf/rpc/rpcserverdynamicportrange.xml [new file with mode: 0644]
lib/param/loadparm.c
lib/param/loadparm.h
lib/param/param.h
python/samba/tests/docs.py
source3/include/proto.h
source3/param/loadparm.c
source3/rpc_server/rpc_server.c
source4/smbd/service_stream.c

index 8a70835..0fd87d6 100644 (file)
@@ -4,11 +4,19 @@
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
        <para>Specifies which port the server should listen on for DCE/RPC over TCP/IP traffic.</para>
-       <para>This controls default port for all protocols, except for NETLOGON.  If unset, the first available port after 1024 is used.</para>
-       <para>The NETLOGON server will use the next available port, eg 1025.  To change this port use (eg) rpc server port:netlogon = 4000.</para>
+       <para>This controls the default port for all protocols, except for NETLOGON.</para>
+       <para>If unset, the first available port from <smbconfoption name="rpc server dynamic port range"/> is used, e.g. 49152.</para>
+       <para>The NETLOGON server will use the next available port, e.g. 49153.  To change this port use (eg) rpc server port:netlogon = 4000.</para>
        <para>Furthermore, all RPC servers can have the port they use specified independenty, with (for example) rpc server port:drsuapi = 5000.</para>
 
+       <para>This option applies currently only when
+       <citerefentry><refentrytitle>samba</refentrytitle> <manvolnum>8</manvolnum></citerefentry>
+       runs as an active directory domain controller.</para>
+
+       <para>The default value 0 causes Samba to select the first available port from <smbconfoption name="rpc server dynamic port range"/>.</para>
 </description>
-<para>The default value 0 causes Samba to select the first available port after 1024.</para>
+
+<related>rpc server dynamic port range</related>
+
 <value type="default">0</value>
 </samba:parameter>
diff --git a/docs-xml/smbdotconf/rpc/rpcserverdynamicportrange.xml b/docs-xml/smbdotconf/rpc/rpcserverdynamicportrange.xml
new file mode 100644 (file)
index 0000000..a9c51d2
--- /dev/null
@@ -0,0 +1,22 @@
+<samba:parameter name="rpc server dynamic port range"
+                 context="G"
+                 type="string"
+                 handler="handle_rpc_server_dynamic_port_range"
+                 xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+<description>
+       <para>
+               This parameter tells the RPC server which port range it is
+               allowed to use to create a listening socket for LSA, SAM,
+               Netlogon and others without wellknown tcp ports.
+               The first value is the lowest number of the port
+               range and the second the hightest.
+       </para>
+       <para>
+               This applies to RPC servers in all server roles.
+       </para>
+</description>
+
+<related>rpc server port</related>
+
+<value type="default">49152-65535</value>
+</samba:parameter>
index a056101..335c54a 100644 (file)
@@ -83,6 +83,16 @@ struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
        return lp_ctx->sDefault;
 }
 
+int lpcfg_rpc_low_port(struct loadparm_context *lp_ctx)
+{
+       return lp_ctx->globals->rpc_low_port;
+}
+
+int lpcfg_rpc_high_port(struct loadparm_context *lp_ctx)
+{
+       return lp_ctx->globals->rpc_high_port;
+}
+
 /**
  * Convenience routine to grab string parameters into temporary memory
  * and run standard_sub_basic on them.
@@ -1435,6 +1445,37 @@ bool handle_smb_ports(struct loadparm_context *lp_ctx, struct loadparm_service *
        return true;
 }
 
+bool handle_rpc_server_dynamic_port_range(struct loadparm_context *lp_ctx,
+                                         struct loadparm_service *service,
+                                         const char *pszParmValue,
+                                         char **ptr)
+{
+       int low_port = -1, high_port = -1;
+       int rc;
+
+       if (pszParmValue == NULL || pszParmValue[0] == '\0') {
+               return false;
+       }
+
+       rc = sscanf(pszParmValue, "%d - %d", &low_port, &high_port);
+       if (rc != 2) {
+               return false;
+       }
+
+       if (low_port > high_port) {
+               return false;
+       }
+
+       if (low_port < SERVER_TCP_PORT_MIN|| high_port > SERVER_TCP_PORT_MAX) {
+               return false;
+       }
+
+       lp_ctx->globals->rpc_low_port = low_port;
+       lp_ctx->globals->rpc_high_port = high_port;
+
+       return true;
+}
+
 bool handle_smb2_max_credits(struct loadparm_context *lp_ctx,
                             struct loadparm_service *service,
                             const char *pszParmValue, char **ptr)
@@ -2498,6 +2539,8 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
        lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
        /* This appears odd, but globals in s3 isn't a pointer */
        lp_ctx->globals->ctx = lp_ctx->globals;
+       lp_ctx->globals->rpc_low_port = SERVER_TCP_LOW_PORT;
+       lp_ctx->globals->rpc_high_port = SERVER_TCP_HIGH_PORT;
        lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
        lp_ctx->flags = talloc_zero_array(lp_ctx, unsigned int, num_parameters());
 
@@ -2901,6 +2944,10 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
 
        lpcfg_do_global_parameter(lp_ctx, "kerberos encryption types", "all");
 
+       lpcfg_do_global_parameter(lp_ctx,
+                                 "rpc server dynamic port range",
+                                 "49152-65535");
+
        /* Allow modules to adjust defaults */
        for (defaults_hook = defaults_hooks; defaults_hook;
                 defaults_hook = defaults_hook->next) {
index 6d01b37..d1e2b7c 100644 (file)
@@ -194,6 +194,11 @@ enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX,
 #endif /* DEVELOPER */
 };
 
+#define SERVER_TCP_LOW_PORT  49152
+#define SERVER_TCP_HIGH_PORT 65535
+
+#define SERVER_TCP_PORT_MIN 1024
+#define SERVER_TCP_PORT_MAX 65535
 
 
 
@@ -275,7 +280,9 @@ enum mangled_names_options {MANGLED_NAMES_NO, MANGLED_NAMES_YES, MANGLED_NAMES_I
 #define LOADPARM_EXTRA_GLOBALS \
        struct parmlist_entry *param_opt;                               \
        char *dnsdomain;                                                \
-       char *realm_original;
+       char *realm_original;                                           \
+       int rpc_low_port;                                               \
+       int rpc_high_port;
 
 const char* server_role_str(uint32_t role);
 int lp_find_server_role(int server_role, int security, int domain_logons, int domain_master);
index 66037e2..e123e67 100644 (file)
@@ -313,6 +313,9 @@ void lpcfg_default_kdc_policy(struct loadparm_context *lp_ctx,
                                time_t *usr_tkt_lifetime,
                                time_t *renewal_lifetime);
 
+int lpcfg_rpc_port_low(struct loadparm_context *lp_ctx);
+int lpcfg_rpc_port_high(struct loadparm_context *lp_ctx);
+
 /* The following definitions come from lib/version.c  */
 
 const char *samba_version_string(void);
index 22e0225..65df573 100644 (file)
@@ -108,7 +108,7 @@ class SmbDotConfTests(TestCase):
                          'lprm command', 'lpq command', 'print command', 'template homedir',
                          'spoolss: os_major', 'spoolss: os_minor', 'spoolss: os_build',
                          'max open files', 'fss: prune stale', 'fss: sequence timeout',
-                         'include system krb5 conf'])
+                         'include system krb5 conf', 'rpc server dynamic port range'])
 
     def setUp(self):
         super(SmbDotConfTests, self).setUp()
@@ -162,14 +162,16 @@ class SmbDotConfTests(TestCase):
             exceptions = ['client lanman auth',
                           'client plaintext auth',
                           'registry shares',
-                          'smb ports'])
+                          'smb ports',
+                          'rpc server dynamic port range'])
         self._test_empty(['bin/testparm'])
 
     def test_default_s4(self):
         self._test_default(['bin/samba-tool', 'testparm'])
         self._set_defaults(['bin/samba-tool', 'testparm'])
         self._set_arbitrary(['bin/samba-tool', 'testparm'],
-            exceptions = ['smb ports'])
+            exceptions = ['smb ports',
+                          'rpc server dynamic port range'])
         self._test_empty(['bin/samba-tool', 'testparm'])
 
     def _test_default(self, program):
@@ -178,6 +180,7 @@ class SmbDotConfTests(TestCase):
 
         for tuples in self.defaults:
             param, default, context, param_type = tuples
+
             if param in self.special_cases:
                 continue
             section = None
@@ -206,7 +209,7 @@ class SmbDotConfTests(TestCase):
         for tuples in self.defaults:
             param, default, context, param_type = tuples
 
-            if param in ['printing']:
+            if param in ['printing', 'rpc server dynamic port range']:
                 continue
 
             section = None
index 642900e..b3d3ca0 100644 (file)
@@ -889,6 +889,8 @@ int lp_client_ipc_signing(void);
 int lp_smb2_max_credits(void);
 int lp_cups_encrypt(void);
 bool lp_widelinks(int );
+int lp_rpc_low_port(void);
+int lp_rpc_high_port(void);
 
 int lp_wi_scan_global_parametrics(
        const char *regex, size_t max_matches,
index 0ce4f92..c65e613 100644 (file)
@@ -929,6 +929,12 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
        Globals.aio_max_threads = 100;
 
+       lpcfg_string_set(Globals.ctx,
+                        &Globals.rpc_server_dynamic_port_range,
+                        "49152-65535");
+       Globals.rpc_low_port = SERVER_TCP_LOW_PORT;
+       Globals.rpc_high_port = SERVER_TCP_HIGH_PORT;
+
        /* Now put back the settings that were set with lp_set_cmdline() */
        apply_lp_set_cmdline();
 }
@@ -4548,6 +4554,16 @@ int lp_client_ipc_signing(void)
        return client_ipc_signing;
 }
 
+int lp_rpc_low_port(void)
+{
+       return Globals.rpc_low_port;
+}
+
+int lp_rpc_high_port(void)
+{
+       return Globals.rpc_high_port;
+}
+
 struct loadparm_global * get_globals(void)
 {
        return &Globals;
index 37fe68f..f7fb8ef 100644 (file)
@@ -34,9 +34,6 @@
 #include "rpc_server/srv_pipe_hnd.h"
 #include "rpc_server/srv_pipe.h"
 
-#define SERVER_TCP_LOW_PORT  49152
-#define SERVER_TCP_HIGH_PORT 65535
-
 /* Creates a pipes_struct and initializes it with the information
  * sent from the client */
 int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
@@ -608,7 +605,7 @@ int create_tcpip_socket(const struct sockaddr_storage *ifss, uint16_t *port)
        if (*port == 0) {
                uint16_t i;
 
-               for (i = SERVER_TCP_LOW_PORT; i <= SERVER_TCP_HIGH_PORT; i++) {
+               for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
                        fd = open_socket_in(SOCK_STREAM,
                                            i,
                                            0,
index 8abaaca..29e6515 100644 (file)
 #include "../lib/tsocket/tsocket.h"
 #include "lib/util/util_net.h"
 
-/* the range of ports to try for dcerpc over tcp endpoints */
-#define SERVER_TCP_LOW_PORT  49152
-#define SERVER_TCP_HIGH_PORT 65535
-
 /* size of listen() backlog in smbd */
 #define SERVER_LISTEN_BACKLOG 10
 
@@ -332,7 +328,9 @@ NTSTATUS stream_setup_socket(TALLOC_CTX *mem_ctx,
        if (!port) {
                status = socket_listen(stream_socket->sock, socket_address, SERVER_LISTEN_BACKLOG, 0);
        } else if (*port == 0) {
-               for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
+               for (i = lpcfg_rpc_low_port(lp_ctx);
+                    i <= lpcfg_rpc_high_port(lp_ctx);
+                    i++) {
                        socket_address->port = i;
                        status = socket_listen(stream_socket->sock, socket_address, 
                                               SERVER_LISTEN_BACKLOG, 0);