summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/param/loadparm.c21
-rw-r--r--source3/smbd/dosmode.c13
3 files changed, 31 insertions, 6 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 922864ecff..e3d151f9ed 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1723,4 +1723,7 @@ typedef struct uuid_flat {
uint8 info[UUID_FLAT_SIZE];
} UUID_FLAT;
+/* map readonly options */
+enum mapreadonly_options {MAP_READONLY_NO, MAP_READONLY_YES, MAP_READONLY_PERMISSIONS};
+
#endif /* _SMB_H */
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index dc2784804d..383b1d7047 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -439,6 +439,7 @@ typedef struct
int iallocation_roundup_size;
int iAioReadSize;
int iAioWriteSize;
+ int iMap_readonly;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -572,6 +573,7 @@ static service sDefault = {
SMB_ROUNDUP_ALLOCATION_SIZE, /* iallocation_roundup_size */
0, /* iAioReadSize */
0, /* iAioWriteSize */
+ MAP_READONLY_YES, /* iMap_readonly */
NULL, /* Parametric options */
@@ -692,6 +694,18 @@ static const struct enum_list enum_announce_as[] = {
{-1, NULL}
};
+static const struct enum_list enum_map_readonly[] = {
+ {MAP_READONLY_NO, "no"},
+ {MAP_READONLY_NO, "false"},
+ {MAP_READONLY_NO, "0"},
+ {MAP_READONLY_YES, "yes"},
+ {MAP_READONLY_YES, "true"},
+ {MAP_READONLY_YES, "1"},
+ {MAP_READONLY_PERMISSIONS, "permissions"},
+ {MAP_READONLY_PERMISSIONS, "perms"},
+ {-1, NULL}
+};
+
static const struct enum_list enum_case[] = {
{CASE_LOWER, "lower"},
{CASE_UPPER, "upper"},
@@ -1046,9 +1060,11 @@ static struct parm_struct parm_table[] = {
{"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL },
{"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL },
{"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL },
- {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
- {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"map readonly", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"map read only", P_ENUM, P_LOCAL, &sDefault.iMap_readonly, NULL, enum_map_readonly, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED },
{"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED},
@@ -1995,6 +2011,7 @@ FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size)
FN_LOCAL_INTEGER(lp_aio_read_size, iAioReadSize)
FN_LOCAL_INTEGER(lp_aio_write_size, iAioWriteSize)
+FN_LOCAL_INTEGER(lp_map_readonly, iMap_readonly)
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_INTEGER(lp_winbind_max_idle_children, &Globals.winbind_max_idle_children)
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index efbd5f04cb..fec148b8e6 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -129,14 +129,19 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c
uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
{
int result = 0;
+ enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
- if (lp_acl_check_permissions(SNUM(conn))) {
+ if (ro_opts == MAP_READONLY_YES) {
+ /* Original Samba method - map inverse of user "w" bit. */
+ if ((sbuf->st_mode & S_IWUSR) == 0) {
+ result |= aRONLY;
+ }
+ } else if (ro_opts == MAP_READONLY_PERMISSIONS) {
+ /* Check actual permissions for read-only. */
if (!can_write_to_file(conn, path, sbuf)) {
result |= aRONLY;
}
- } else if ((sbuf->st_mode & S_IWUSR) == 0) {
- result |= aRONLY;
- }
+ } /* Else never set the readonly bit. */
if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
result |= aARCH;