summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-04-11 21:40:01 +0000
committerGerald Carter <jerry@samba.org>2005-04-11 21:40:01 +0000
commitdae1a1db3c946093333d9e5001e30f75140fd3ca (patch)
tree77a0b497d3495c153ec0f7b6ec162c6d57314812
parente1d96ed97614ef847df6038044143666a02c195f (diff)
downloadsamba-dae1a1db3c946093333d9e5001e30f75140fd3ca.tar.gz
r6299: last commits for 3.0.14samba-3.0.14
-rw-r--r--WHATSNEW.txt12
-rw-r--r--source/lib/account_pol.c4
-rw-r--r--source/nsswitch/winbindd_cm.c10
-rw-r--r--source/param/loadparm.c2
-rw-r--r--source/smbd/dosmode.c21
-rw-r--r--source/smbd/posix_acls.c148
6 files changed, 147 insertions, 50 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index f304eab4d22..e02cb1e8fab 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -24,6 +24,16 @@ Changes
Changes since 3.0.13
--------------------
+smb.conf changes
+----------------
+
+ Parameter Name Action
+ -------------- ------
+ dos filetimes Enabled by default
+
+
+commits
+-------
o Jeremy Allison <jra@samba.org>
* Prevent nt_status code support when negotiating protocols
earlier than NT1.
@@ -35,6 +45,8 @@ o Jeremy Allison <jra@samba.org>
FindNext().
* BUG 2581 (partial): Ensure if realloc fails on an internal
tdb we fail gracefully.
+ * Ensure that 'dos filetimes' works with ACLs.
+ * Set 'dos filefimes = yes' as the default for smb.conf.
o Gerald (Jerry) Carter <jerry@samba.org>
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index 5997d9180ae..72d6e77ddda 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -118,8 +118,8 @@ static const struct {
{AP_MIN_PASSWORD_LEN, "min password length"},
{AP_PASSWORD_HISTORY, "password history"},
{AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"},
- {AP_MAX_PASSWORD_AGE, "maximum password age (seconds since 1970)"},
- {AP_MIN_PASSWORD_AGE,"minimum password age (seconds since 1970)"},
+ {AP_MAX_PASSWORD_AGE, "maximum password age"},
+ {AP_MIN_PASSWORD_AGE,"minimum password age"},
{AP_LOCK_ACCOUNT_DURATION, "lockout duration"},
{AP_RESET_COUNT_TIME, "reset count minutes"},
{AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"},
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index 832672e64cb..c5cf1d5f464 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -1021,6 +1021,16 @@ NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **retu
cli_shutdown(conn->cli);
DLIST_REMOVE(cm_conns, conn);
SAFE_FREE(conn);
+
+ /* log a message for possible Windows 2003 SP1 DC's */
+ if ( NT_STATUS_EQUAL(result,NT_STATUS_ACCESS_DENIED) && (lp_security() == SEC_DOMAIN) ) {
+ DEBUG(0,("samr_connect() received NT_STATUS_ACCESS_DENIED. If you are connecting \n"));
+ DEBUGADD(0,("to a Windows 2003 SP1 DC, this is a known issue. There are two current \n"));
+ DEBUGADD(0,("workarounds:\n"));
+ DEBUGADD(0,("(a) Move your configuration to security = ads, or\n"));
+ DEBUGADD(0,("(b) set 'client schannel = no' in smb.conf and use 'wbinfo --set-auth-user'\n"));
+ DEBUGADD(0,(" to define the credentials when connecting to the DC\n"));
+ }
return result;
}
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index d86f4b391a2..493f1142daa 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -533,7 +533,7 @@ static service sDefault = {
False, /* bFakeOplocks */
False, /* bDeleteVetoFiles */
False, /* bDosFilemode */
- False, /* bDosFiletimes */
+ True, /* bDosFiletimes */
False, /* bDosFiletimeResolution */
False, /* bFakeDirCreateTimes */
True, /* bBlockingLocks */
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index fefcaca09d5..ff00b5dc6b1 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -433,8 +433,6 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
{
- extern struct current_user current_user;
- SMB_STRUCT_STAT sb;
int ret = -1;
errno = 0;
@@ -454,21 +452,12 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
(as DOS does).
*/
- if(SMB_VFS_STAT(conn,fname,&sb) != 0)
- return -1;
-
/* Check if we have write access. */
- if (CAN_WRITE(conn)) {
- if (((sb.st_mode & S_IWOTH) || conn->admin_user ||
- ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
- ((sb.st_mode & S_IWGRP) &&
- in_group(sb.st_gid,current_user.gid,
- current_user.ngroups,current_user.groups)))) {
- /* We are allowed to become root and change the filetime. */
- become_root();
- ret = SMB_VFS_UTIME(conn,fname, times);
- unbecome_root();
- }
+ if (can_write_to_file(conn, fname)) {
+ /* We are allowed to become root and change the filetime. */
+ become_root();
+ ret = SMB_VFS_UTIME(conn,fname, times);
+ unbecome_root();
}
return ret;
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index c5fa035c69c..52ddf4cad6d 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -3758,23 +3758,27 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
Check for POSIX group ACLs. If none use stat entry.
****************************************************************************/
-static int check_posix_acl_group_write(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *psbuf)
+static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
{
extern struct current_user current_user;
SMB_ACL_T posix_acl = NULL;
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
int i;
+ BOOL seen_mask = False;
int ret = -1;
- if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, dname, SMB_ACL_TYPE_ACCESS)) == NULL) {
+ if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) {
goto check_stat;
}
/* First ensure the group mask allows group read. */
+ /* Also check any user entries (these take preference over group). */
+
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
+ int have_write = -1;
/* get_next... */
if (entry_id == SMB_ACL_FIRST_ENTRY)
@@ -3788,20 +3792,51 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam
goto check_stat;
}
+ have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
+ if (have_write == -1) {
+ goto check_stat;
+ }
+
switch(tagtype) {
case SMB_ACL_MASK:
- if (!SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE)) {
- /* We don't have group write permission. */
+ if (!have_write) {
+ /* We don't have any group or explicit user write permission. */
ret = -1; /* Allow caller to check "other" permissions. */
+ DEBUG(10,("check_posix_acl_group_write: file %s \
+refusing write due to mask.\n", fname));
goto done;
}
+ seen_mask = True;
break;
+ case SMB_ACL_USER:
+ {
+ /* Check against current_user.uid. */
+ uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (puid == NULL) {
+ goto check_stat;
+ }
+ if (current_user.uid == *puid) {
+ /* We have a uid match but we must ensure we have seen the acl mask. */
+ ret = have_write;
+ DEBUG(10,("check_posix_acl_group_write: file %s \
+match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "cannot write"));
+ if (seen_mask) {
+ goto done;
+ }
+ }
+ break;
+ }
default:
continue;
}
}
- /* Now check all group entries. */
+ /* If ret is anything other than -1 we matched on a user entry. */
+ if (ret != -1) {
+ goto done;
+ }
+
+ /* Next check all group entries. */
entry_id = SMB_ACL_FIRST_ENTRY;
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
SMB_ACL_TAG_T tagtype;
@@ -3826,50 +3861,54 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam
}
switch(tagtype) {
- case SMB_ACL_USER:
- {
- /* Check against current_user.uid. */
- uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
- if (puid == NULL) {
- goto check_stat;
- }
- if (current_user.uid == *puid) {
- /* We're done now we have a uid match. */
- ret = have_write;
- goto done;
- }
- }
- break;
case SMB_ACL_GROUP:
- {
- gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
- if (pgid == NULL) {
- goto check_stat;
- }
- for (i = 0; i < current_user.ngroups; i++) {
- if (current_user.groups[i] == *pgid) {
- /* We're done now we have a gid match. */
- ret = have_write;
+ {
+ gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (pgid == NULL) {
+ goto check_stat;
+ }
+ for (i = 0; i < current_user.ngroups; i++) {
+ if (current_user.groups[i] == *pgid) {
+ ret = have_write;
+ DEBUG(10,("check_posix_acl_group_write: file %s \
+match on group %u -> can write.\n", fname, (unsigned int)*pgid ));
+
+ /* If we don't have write permission this entry doesn't
+ terminate the enumeration of the entries. */
+ if (have_write) {
goto done;
}
+ /* But does terminate the group iteration. */
+ break;
}
}
break;
+ }
default:
continue;
}
}
+ /* If we get here we know ret == 0. */
+ SMB_ASSERT(ret == 0);
check_stat:
for (i = 0; i < current_user.ngroups; i++) {
if (current_user.groups[i] == psbuf->st_gid) {
ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0;
+ DEBUG(10,("check_posix_acl_group_write: file %s \
+match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write"));
break;
}
}
+ if (i == current_user.ngroups) {
+ SMB_ASSERT(ret != 1);
+ DEBUG(10,("check_posix_acl_group_write: file %s \
+failed to match on user or group in token.\n", fname ));
+ }
+
done:
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
@@ -3877,7 +3916,7 @@ static int check_posix_acl_group_write(connection_struct *conn, const char *dnam
}
/****************************************************************************
- Actually emulate the in-kernel access checking for write access. We need
+ Actually emulate the in-kernel access checking for delete access. We need
this to successfully return ACCESS_DENIED on a file open for delete access.
****************************************************************************/
@@ -3888,6 +3927,11 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
pstring dname;
int ret;
+ if (!CAN_WRITE(conn)) {
+ return False;
+ }
+
+ /* Get the parent directory permission mask and owners. */
pstrcpy(dname, parent_dirname(fname));
if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
return False;
@@ -3895,11 +3939,12 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
if (!S_ISDIR(sbuf.st_mode)) {
return False;
}
- if (current_user.uid == 0) {
+ if (current_user.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
+ /* Check primary owner write access. */
if (current_user.uid == sbuf.st_uid) {
return (sbuf.st_mode & S_IWUSR) ? True : False;
}
@@ -3918,11 +3963,52 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
}
#endif
- /* Check group ownership. */
+ /* Check group or explicit user acl entry write access. */
ret = check_posix_acl_group_write(conn, dname, &sbuf);
if (ret == 0 || ret == 1) {
return ret ? True : False;
}
+ /* Finally check other write access. */
+ return (sbuf.st_mode & S_IWOTH) ? True : False;
+}
+
+/****************************************************************************
+ Actually emulate the in-kernel access checking for write access. We need
+ this to successfully check for ability to write for dos filetimes.
+****************************************************************************/
+
+BOOL can_write_to_file(connection_struct *conn, const char *fname)
+{
+ extern struct current_user current_user;
+ SMB_STRUCT_STAT sbuf;
+ int ret;
+
+ if (!CAN_WRITE(conn)) {
+ return False;
+ }
+
+ if (current_user.uid == 0 || conn->admin_user) {
+ /* I'm sorry sir, I didn't know you were root... */
+ return True;
+ }
+
+ /* Get the file permission mask and owners. */
+ if(SMB_VFS_STAT(conn, fname, &sbuf) != 0) {
+ return False;
+ }
+
+ /* Check primary owner write access. */
+ if (current_user.uid == sbuf.st_uid) {
+ return (sbuf.st_mode & S_IWUSR) ? True : False;
+ }
+
+ /* Check group or explicit user acl entry write access. */
+ ret = check_posix_acl_group_write(conn, fname, &sbuf);
+ if (ret == 0 || ret == 1) {
+ return ret ? True : False;
+ }
+
+ /* Finally check other write access. */
return (sbuf.st_mode & S_IWOTH) ? True : False;
}