summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs-xml/smbdotconf/security/accessbasedshareenum.xml18
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/param/loadparm.c13
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c58
4 files changed, 71 insertions, 19 deletions
diff --git a/docs-xml/smbdotconf/security/accessbasedshareenum.xml b/docs-xml/smbdotconf/security/accessbasedshareenum.xml
new file mode 100644
index 0000000000..c2977c47ae
--- /dev/null
+++ b/docs-xml/smbdotconf/security/accessbasedshareenum.xml
@@ -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>
diff --git a/source3/include/proto.h b/source3/include/proto.h
index d0e64f7f14..ed79ad03ec 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -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 );
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index c743b89680..7e7a1e505e 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -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 */
@@ -3304,6 +3306,15 @@ static struct parm_struct parm_table[] = {
.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,
.p_class = P_LOCAL,
@@ -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;
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 76b475120d..67ff1fecf6 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -493,6 +493,19 @@ static bool is_hidden_share(int snum)
}
/*******************************************************************
+ 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);
}