summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/include/proto.h2
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c159
-rw-r--r--source3/smbd/server.c4
-rw-r--r--source3/smbd/service.c23
4 files changed, 170 insertions, 18 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 4d42664f25..a41c810816 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3765,7 +3765,7 @@ BOOL api_srvsvc_rpc(pipes_struct *p);
/*The following definitions come from rpc_server/srv_srvsvc_nt.c */
BOOL share_info_db_init(void);
-SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize);
+BOOL share_access_check(int snum, uint16 vuid, uint32 desired_access);
uint32 _srv_net_srv_get_info(pipes_struct *p, SRV_Q_NET_SRV_GET_INFO *q_u, SRV_R_NET_SRV_GET_INFO *r_u);
uint32 _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u);
uint32 _srv_net_conn_enum(pipes_struct *p, SRV_Q_NET_CONN_ENUM *q_u, SRV_R_NET_CONN_ENUM *r_u);
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 5c1c16c02a..4395a20e46 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -158,7 +158,7 @@ static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *
Pull a security descriptor from the share tdb.
********************************************************************/
-SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
+static SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
{
prs_struct ps;
fstring key;
@@ -184,7 +184,7 @@ SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
Store a security descriptor in the share db.
********************************************************************/
-static BOOL set_share_security(TALLOC_CTX *ctx, int snum, SEC_DESC *psd)
+static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
{
prs_struct ps;
TALLOC_CTX *mem_ctx = NULL;
@@ -201,13 +201,13 @@ static BOOL set_share_security(TALLOC_CTX *ctx, int snum, SEC_DESC *psd)
goto out;
}
- slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+ slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
if (tdb_prs_store(share_tdb, key, &ps)==0) {
ret = True;
- DEBUG(5,("set_share_security: stored secdesc for %s\n", lp_servicename(snum) ));
+ DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
} else {
- DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", lp_servicename(snum) ));
+ DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
}
/* Free malloc'ed memory */
@@ -243,6 +243,73 @@ static BOOL delete_share_security(int snum)
}
/*******************************************************************
+ Does this security descriptor map to a read only share ?
+********************************************************************/
+
+static BOOL read_only_share_sd(SEC_DESC *psd)
+{
+ int i;
+ SEC_ACL *ps_dacl = psd->dacl;
+
+ if (!ps_dacl)
+ return True;
+
+ for (i = 0; i < ps_dacl->num_aces; i++) {
+ SEC_ACE *psa = &ps_dacl->ace[i];
+
+ if (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED &&
+ psa->info.mask & FILE_WRITE_DATA)
+ return False;
+ }
+
+ return True;
+}
+
+/*******************************************************************
+ Can this user access with share with the required permissions ?
+********************************************************************/
+
+BOOL share_access_check(int snum, uint16 vuid, uint32 desired_access)
+{
+ uint32 granted, status;
+ TALLOC_CTX *mem_ctx = NULL;
+ SEC_DESC *psd = NULL;
+ size_t sd_size;
+ struct current_user tmp_user;
+ struct current_user *puser = NULL;
+ user_struct *vuser = get_valid_user_struct(vuid);
+ BOOL ret = True;
+
+ mem_ctx = talloc_init();
+ if (mem_ctx == NULL)
+ return False;
+
+ psd = get_share_security(mem_ctx, snum, &sd_size);
+
+ if (!psd)
+ goto out;
+
+ if (vuser) {
+ ZERO_STRUCT(tmp_user);
+ tmp_user.vuid = vuid;
+ tmp_user.uid = vuser->uid;
+ tmp_user.gid = vuser->gid;
+ tmp_user.ngroups = vuser->n_groups;
+ tmp_user.groups = vuser->groups;
+ tmp_user.nt_user_token = vuser->nt_user_token;
+ puser = &tmp_user;
+ }
+
+ ret = se_access_check(psd, puser, desired_access, &granted, &status);
+
+ out:
+
+ talloc_destroy(mem_ctx);
+
+ return ret;
+}
+
+/*******************************************************************
Fill in a share info level 502 structure.
********************************************************************/
@@ -1120,7 +1187,8 @@ uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
int snum;
int ret;
char *ptr;
- BOOL read_only;
+ SEC_DESC *psd = NULL;
+ BOOL read_only = False;
DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
@@ -1139,27 +1207,76 @@ uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
if (user.uid != 0)
return ERROR_ACCESS_DENIED;
- if (!lp_change_share_cmd())
- return ERROR_ACCESS_DENIED;
-
switch (q_u->info_level) {
case 1:
+ /* Not enough info in a level 1 to do anything. */
return ERROR_ACCESS_DENIED;
- break;
case 2:
- return ERROR_ACCESS_DENIED;
+ unistr2_to_ascii(comment, &q_u->info.share.info2.info_2_str.uni_remark, sizeof(share_name));
+ unistr2_to_ascii(pathname, &q_u->info.share.info2.info_2_str.uni_path, sizeof(share_name));
+ type = q_u->info.share.info2.info_2.type;
+ read_only = False; /* No SD means "Everyone full access. */
break;
case 502:
- /* we set sd's here. FIXME. JRA */
- return ERROR_ACCESS_DENIED;
+ unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
+ unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(share_name));
+ type = q_u->info.share.info502.info_502.type;
+ psd = q_u->info.share.info502.info_502_str.sd;
+ read_only = read_only_share_sd(psd);
break;
case 1005:
return ERROR_ACCESS_DENIED;
- break;
default:
DEBUG(5,("_srv_net_share_set_info: unsupported switch value %d\n", q_u->info_level));
return NT_STATUS_INVALID_INFO_CLASS;
- break;
+ }
+
+ /* We can only modify disk shares. */
+ if (type != STYPE_DISKTREE)
+ return ERROR_ACCESS_DENIED;
+
+ /* Check if the pathname is valid. */
+ if (!(ptr = valid_share_pathname( pathname )))
+ return ERRbadpath;
+
+ /* Ensure share name, pathname and comment don't contain '"' characters. */
+ string_replace(share_name, '"', ' ');
+ string_replace(ptr, '"', ' ');
+ string_replace(comment, '"', ' ');
+
+ /* Only call modify function if something changed. */
+
+ if (read_only != lp_readonly(snum) || strcmp(ptr, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) {
+ if (!lp_change_share_cmd())
+ return ERROR_ACCESS_DENIED;
+
+ slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
+ lp_change_share_cmd(), share_name, ptr, comment,
+ read_only ? "read only = yes" : "read only = no" );
+ dos_to_unix(command, True); /* Convert to unix-codepage */
+
+ DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command ));
+ if ((ret = smbrun(command, NULL, False)) != 0) {
+ DEBUG(0,("_srv_net_share_set_info: Running [%s] returned (%d)\n", command, ret ));
+ return ERROR_ACCESS_DENIED;
+ }
+
+ /* Send SIGHUP to process group. */
+ kill(0, SIGHUP);
+ }
+
+ /* Replace SD if changed. */
+ if (psd) {
+ SEC_DESC *old_sd;
+ size_t sd_size;
+
+ old_sd = get_share_security(p->mem_ctx, snum, &sd_size);
+
+ if (old_sd && !sec_desc_equal(old_sd, psd)) {
+ if (!set_share_security(p->mem_ctx, share_name, psd))
+ DEBUG(0,("_srv_net_share_set_info: Failed to change security info in share %s.\n",
+ share_name ));
+ }
}
DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__));
@@ -1168,7 +1285,7 @@ uint32 _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S
}
/*******************************************************************
- Net share add. Call 'add_share_command "sharename" "pathname" "comment"'
+ Net share add. Call 'add_share_command "sharename" "pathname" "comment" "read only = xxx"'
********************************************************************/
uint32 _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_SHARE_ADD *r_u)
@@ -1183,6 +1300,7 @@ uint32 _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
int ret;
char *ptr;
BOOL read_only = False;
+ SEC_DESC *psd = NULL;
DEBUG(5,("_srv_net_share_add: %d\n", __LINE__));
@@ -1208,11 +1326,12 @@ uint32 _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
read_only = False; /* No SD means "Everyone full access. */
break;
case 502:
- /* we set sd's here. FIXME. JRA */
unistr2_to_ascii(share_name, &q_u->info.share.info502.info_502_str.uni_netname, sizeof(share_name));
unistr2_to_ascii(comment, &q_u->info.share.info502.info_502_str.uni_remark, sizeof(share_name));
unistr2_to_ascii(pathname, &q_u->info.share.info502.info_502_str.uni_path, sizeof(share_name));
type = q_u->info.share.info502.info_502.type;
+ psd = q_u->info.share.info502.info_502_str.sd;
+ read_only = read_only_share_sd(psd);
break;
case 1005:
/* DFS only level. */
@@ -1252,6 +1371,12 @@ uint32 _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S
return ERROR_ACCESS_DENIED;
}
+ if (psd) {
+ if (!set_share_security(p->mem_ctx, share_name, psd))
+ DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n",
+ share_name ));
+ }
+
/* Send SIGHUP to process group. */
kill(0, SIGHUP);
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index adf57b3f55..84b7109294 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -765,6 +765,10 @@ static void usage(char *pname)
exit(1);
}
+ if (!share_info_db_init()) {
+ exit(1);
+ }
+
if(!initialize_password_db(False)) {
exit(1);
}
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index e20786595c..11ae11054a 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -343,6 +343,29 @@ connection_struct *make_connection(char *service,char *user,char *password, int
conn->read_only = lp_readonly(snum);
+ /*
+ * New code to check if there's a share security descripter
+ * added from NT server manager. This is an additional check
+ * before the smb.conf checks are done. JRA.
+ */
+
+ {
+ BOOL can_write = share_access_check(snum, vuid, FILE_WRITE_DATA);
+
+ if (!can_write) {
+ if (!share_access_check(snum, vuid, FILE_READ_DATA)) {
+ /* No access, read or write. */
+ *ecode = ERRaccess;
+ DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
+ service ));
+ conn_free(conn);
+ return NULL;
+ } else {
+ conn->read_only = True;
+ }
+ }
+ }
+
{
pstring list;
StrnCpy(list,lp_readlist(snum),sizeof(pstring)-1);