s3: Add support for access based share enumeration
authorTodd Stecher <todd.stecher@isilon.com>
Thu, 4 Dec 2008 19:33:32 +0000 (11:33 -0800)
committerTim Prouty <tprouty@samba.org>
Tue, 9 Dec 2008 06:23:16 +0000 (22:23 -0800)
docs-xml/smbdotconf/security/accessbasedshareenum.xml [new file with mode: 0644]
source3/include/proto.h
source3/param/loadparm.c
source3/rpc_server/srv_srvsvc_nt.c

diff --git a/docs-xml/smbdotconf/security/accessbasedshareenum.xml b/docs-xml/smbdotconf/security/accessbasedshareenum.xml
new file mode 100644 (file)
index 0000000..c2977c4
--- /dev/null
@@ -0,0 +1,18 @@
+<samba:parameter name="access based share enum"
+                type="boolean"
+                 context="S"
+                 basic="1" advanced="1" developer="1"
+                xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
+ <synonym>public</synonym>
+ <description>
+     <para>If this parameter is <constant>yes</constant> for a
+    service, then the share hosted by the service will only be visible
+    to users who have read or write access to the share during share
+    enumeration (for example net view \\sambaserver).  This has
+    parallels to access based enumeration, the main difference being
+    that only share permissions are evaluated, and security
+    descriptors on files contained on the share are not used in
+    computing enumeration access rights.</para>
+ </description>
+ <value type="default">no</value>
+</samba:parameter>
index d0e64f7..ed79ad0 100644 (file)
@@ -4136,6 +4136,7 @@ bool lp_hide_special_files(int );
 bool lp_hideunreadable(int );
 bool lp_hideunwriteable_files(int );
 bool lp_browseable(int );
+bool lp_access_based_share_enum(int );
 bool lp_readonly(int );
 bool lp_no_set_dir(int );
 bool lp_guest_ok(int );
index c743b89..7e7a1e5 100644 (file)
@@ -425,6 +425,7 @@ struct service {
        bool bHideUnReadable;
        bool bHideUnWriteableFiles;
        bool bBrowseable;
+       bool bAccessBasedShareEnum;
        bool bAvailable;
        bool bRead_only;
        bool bNo_set_dir;
@@ -568,6 +569,7 @@ static struct service sDefault = {
        False,                  /* bHideUnReadable */
        False,                  /* bHideUnWriteableFiles */
        True,                   /* bBrowseable */
+       False,                  /* bAccessBasedShareEnum */
        True,                   /* bAvailable */
        True,                   /* bRead_only */
        True,                   /* bNo_set_dir */
@@ -3303,6 +3305,15 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT,
        },
+       {
+               .label          = "access based share enum",
+               .type           = P_BOOL,
+               .p_class        = P_LOCAL,
+               .ptr            = &sDefault.bAccessBasedShareEnum,
+               .special        = NULL,
+               .enum_list      = NULL,
+               .flags          = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE
+       },
        {
                .label          = "browsable",
                .type           = P_BOOL,
@@ -5331,6 +5342,7 @@ FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
+FN_LOCAL_BOOL(lp_access_based_share_enum, bAccessBasedShareEnum)
 FN_LOCAL_BOOL(lp_readonly, bRead_only)
 FN_LOCAL_BOOL(lp_no_set_dir, bNo_set_dir)
 FN_LOCAL_BOOL(lp_guest_ok, bGuest_ok)
@@ -5925,6 +5937,7 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
        /* set the browseable flag from the global default */
 
        ServicePtrs[i]->bBrowseable = sDefault.bBrowseable;
+       ServicePtrs[i]->bAccessBasedShareEnum = sDefault.bAccessBasedShareEnum;
 
        ServicePtrs[i]->autoloaded = True;
 
index 76b4751..67ff1fe 100644 (file)
@@ -492,6 +492,19 @@ static bool is_hidden_share(int snum)
        return (net_name[strlen(net_name) - 1] == '$') ? True : False;
 }
 
+/*******************************************************************
+ Verify user is allowed to view share, access based enumeration
+********************************************************************/
+static bool is_enumeration_allowed(pipes_struct *p,
+                                   int snum)
+{
+    if (!lp_access_based_share_enum(snum))
+        return true;
+
+    return share_access_check(p->server_info->ptok, lp_servicename(snum),
+                              FILE_READ_DATA);
+}
+
 /*******************************************************************
  Fill in a share info structure.
  ********************************************************************/
@@ -509,6 +522,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
        TALLOC_CTX *ctx = p->mem_ctx;
        int i = 0;
        int valid_share_count = 0;
+       bool *allowed = 0;
        union srvsvc_NetShareCtr ctr;
        uint32_t resume_handle = resume_handle_p ? *resume_handle_p : 0;
 
@@ -521,15 +535,21 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
        num_services = lp_numservices();
        unbecome_root();
 
-       /* Count the number of entries. */
-       for (snum = 0; snum < num_services; snum++) {
-               if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) ) {
-                       DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
-                       num_entries++;
-               } else {
-                       DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
-               }
-       }
+        allowed = TALLOC_ZERO_ARRAY(ctx, int, num_services);
+        W_ERROR_HAVE_NO_MEMORY(allowed);
+
+        /* Count the number of entries. */
+        for (snum = 0; snum < num_services; snum++) {
+                if (lp_browseable(snum) && lp_snum_ok(snum) &&
+                    is_enumeration_allowed(p, snum) &&
+                    (all_shares || !is_hidden_share(snum)) ) {
+                        DEBUG(10, ("counting service %s\n", lp_servicename(snum)));
+                        allowed[snum] = true;
+                        num_entries++;
+                } else {
+                        DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum)));
+                }
+        }
 
        if (!num_entries || (resume_handle >= num_entries)) {
                return WERR_OK;
@@ -547,7 +567,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr0->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_0(p, &ctr.ctr0->array[i++], snum);
                        }
@@ -564,7 +584,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1(p, &ctr.ctr1->array[i++], snum);
                        }
@@ -581,7 +601,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr2->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_2(p, &ctr.ctr2->array[i++], snum);
                        }
@@ -598,7 +618,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr501->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_501(p, &ctr.ctr501->array[i++], snum);
                        }
@@ -615,7 +635,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr502->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_502(p, &ctr.ctr502->array[i++], snum);
                        }
@@ -632,7 +652,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1004->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1004(p, &ctr.ctr1004->array[i++], snum);
                        }
@@ -649,7 +669,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1005->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1005(p, &ctr.ctr1005->array[i++], snum);
                        }
@@ -666,7 +686,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1006->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1006(p, &ctr.ctr1006->array[i++], snum);
                        }
@@ -683,7 +703,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1007->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1007(p, &ctr.ctr1007->array[i++], snum);
                        }
@@ -700,7 +720,7 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p,
                W_ERROR_HAVE_NO_MEMORY(ctr.ctr1501->array);
 
                for (snum = 0; snum < num_services; snum++) {
-                       if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) &&
+                       if (allowed[snum] &&
                            (resume_handle <= (i + valid_share_count++)) ) {
                                init_srv_share_info_1501(p, &ctr.ctr1501->array[i++], snum);
                        }