summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-01-31 05:14:31 +0000
committerJeremy Allison <jra@samba.org>2001-01-31 05:14:31 +0000
commit4d6b6eb94a3bb53ab47d458a4071ba805281c6a1 (patch)
tree014be4f0431b34ee434dadeee3e0d2e1d05746ef
parent66f6ad97297fe09b3cbd91aab6099fd3c98b078b (diff)
downloadsamba-4d6b6eb94a3bb53ab47d458a4071ba805281c6a1.tar.gz
samba-4d6b6eb94a3bb53ab47d458a4071ba805281c6a1.tar.bz2
samba-4d6b6eb94a3bb53ab47d458a4071ba805281c6a1.zip
lib/system.c: Fix for pw caching.
srv_samr.c: Fix for pw caching. smbd/nttrans.c: Fix to allow trans create to set ACL on open. Jeremy. (This used to be commit c4f810a7588a2faf41f4222dc77678c53ab1dec0)
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/include/rpc_secdes.h2
-rw-r--r--source3/lib/system.c49
-rw-r--r--source3/rpc_server/srv_samr.c12
-rw-r--r--source3/smbd/nttrans.c139
5 files changed, 141 insertions, 64 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index ffd6a8bfe5..b452d1c9f1 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -649,6 +649,9 @@ void sys_srandom(unsigned int seed);
int groups_max(void);
int sys_getgroups(int setlen, gid_t *gidset);
int sys_setgroups(int setlen, gid_t *gidset);
+void sys_setpwent(void);
+struct passwd *sys_getpwent(void);
+void sys_endpwent(void);
struct passwd *sys_getpwnam(const char *name);
struct passwd *sys_getpwuid(uid_t uid);
int wsys_stat(const smb_ucs2_t *wfname,SMB_STRUCT_STAT *sbuf);
diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h
index ab8a24d2d6..d32ab3f3e7 100644
--- a/source3/include/rpc_secdes.h
+++ b/source3/include/rpc_secdes.h
@@ -73,6 +73,8 @@
#define DACL_SECURITY_INFORMATION 0x00000004
#define SACL_SECURITY_INFORMATION 0x00000008
+#define ALL_SECURITY_INFORMATION (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|\
+ DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION)
#ifndef _SEC_ACCESS
/* SEC_ACCESS */
diff --git a/source3/lib/system.c b/source3/lib/system.c
index a2b9a7dbf7..48a8a3f687 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -611,6 +611,13 @@ static struct passwd *setup_pwret(struct passwd *pass)
getpw[nam|uid]() call. Patch by "Richard Bollinger"
<rabollinger@home.com> */
+/*
+ * This next static pointer is used to cache the results
+ * from the real getpwXX calls. It is never returned to
+ * the caller, only the output from calling setup_pwret with
+ * this is returned. JRA.
+ */
+
static struct passwd *sv_pw_ret; /* implicitly initialized to NULL */
static int num_lookups; /* Counter so we don't always use cache. */
#ifndef PW_RET_CACHE_MAX_LOOKUPS
@@ -618,13 +625,33 @@ static int num_lookups; /* Counter so we don't always use cache. */
#endif
/**************************************************************************
+ Wrappers for setpwent(), getpwent() and endpwent()
+****************************************************************************/
+
+void sys_setpwent(void)
+{
+ sv_pw_ret = NULL;
+ setpwent();
+}
+
+struct passwd *sys_getpwent(void)
+{
+ sv_pw_ret = getpwent();
+ return setup_pwret(sv_pw_ret);
+}
+
+void sys_endpwent(void)
+{
+ sv_pw_ret = NULL;
+ endpwent();
+}
+
+/**************************************************************************
Wrapper for getpwnam(). Always returns a static that can be modified.
****************************************************************************/
struct passwd *sys_getpwnam(const char *name)
{
- struct passwd *pw_ret;
-
if (!name || !name[0])
return NULL;
@@ -634,17 +661,17 @@ struct passwd *sys_getpwnam(const char *name)
DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name));
num_lookups++;
num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
- return sv_pw_ret;
+ return setup_pwret(sv_pw_ret);
}
/* no cache hit--use old lookup instead */
DEBUG(2,("getpwnam(%s) called\n",name));
- if (!(pw_ret = getpwnam(name)))
- return NULL;
num_lookups = 1;
- return (sv_pw_ret = setup_pwret(pw_ret));
+ sv_pw_ret = getpwnam(name);
+
+ return setup_pwret(sv_pw_ret);
}
/**************************************************************************
@@ -653,23 +680,21 @@ struct passwd *sys_getpwnam(const char *name)
struct passwd *sys_getpwuid(uid_t uid)
{
- struct passwd *pw_ret;
-
if (num_lookups && sv_pw_ret && (uid == sv_pw_ret->pw_uid))
{
DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid));
num_lookups++;
num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
- return sv_pw_ret;
+ return setup_pwret(sv_pw_ret);
}
DEBUG(2,("getpwuid(%d) called\n",uid));
- if (!(pw_ret = getpwuid(uid)))
- return NULL;
num_lookups = 1;
- return (sv_pw_ret = setup_pwret(pw_ret));
+ sv_pw_ret = getpwuid(uid);
+
+ return setup_pwret(sv_pw_ret);
}
/**************************************************************************
diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c
index 30a0350f67..857581a471 100644
--- a/source3/rpc_server/srv_samr.c
+++ b/source3/rpc_server/srv_samr.c
@@ -217,7 +217,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
if (pw_buf == NULL) return False;
if (current_idx == 0) {
- setpwent();
+ sys_setpwent();
}
/* These two cases are inefficient, but should be called very rarely */
@@ -230,7 +230,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
char *unmap_name;
if(!orig_done) {
- if ((pwd = getpwent()) == NULL) break;
+ if ((pwd = sys_getpwent()) == NULL) break;
current_idx++;
orig_done = True;
}
@@ -248,8 +248,8 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
}
} else if (start_idx < current_idx) {
/* We are already too far; start over and advance to start_idx */
- endpwent();
- setpwent();
+ sys_endpwent();
+ sys_setpwent();
current_idx = 0;
mapped_idx = 0;
orig_done = False;
@@ -257,7 +257,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
char *unmap_name;
if(!orig_done) {
- if ((pwd = getpwent()) == NULL) break;
+ if ((pwd = sys_getpwent()) == NULL) break;
current_idx++;
orig_done = True;
}
@@ -284,7 +284,7 @@ static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
/* This does the original UNIX user itself */
if(!orig_done) {
- if ((pwd = getpwent()) == NULL) break;
+ if ((pwd = sys_getpwent()) == NULL) break;
/* Don't enumerate winbind users as they are not local */
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 3aaaa9aebb..19f5859abb 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1058,6 +1058,77 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
}
/****************************************************************************
+ Internal fn to set security descriptors.
+****************************************************************************/
+
+static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint security_info_sent, int *pdef_class,uint32 *pdef_code)
+{
+ prs_struct pd;
+ SEC_DESC *psd = NULL;
+ TALLOC_CTX *mem_ctx;
+ BOOL ret;
+
+ if (sd_len == 0) {
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRbadaccess;
+ return False;
+ }
+
+ /*
+ * Init the parse struct we will unmarshall from.
+ */
+
+ if ((mem_ctx = talloc_init()) == NULL) {
+ DEBUG(0,("set_sd: talloc_init failed.\n"));
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnomem;
+ return False;
+ }
+
+ prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL);
+
+ /*
+ * Setup the prs_struct to point at the memory we just
+ * allocated.
+ */
+
+ prs_give_memory( &pd, data, sd_len, False);
+
+ /*
+ * Finally, unmarshall from the data buffer.
+ */
+
+ if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
+ free_sec_desc(&psd);
+ DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n"));
+ /*
+ * Return access denied for want of a better error message..
+ */
+ talloc_destroy(mem_ctx);
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnomem;
+ return False;
+ }
+
+ ret = set_nt_acl( fsp, security_info_sent, psd);
+
+ if (!ret) {
+ free_sec_desc(&psd);
+ talloc_destroy(mem_ctx);
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnoaccess;
+ return False;
+ }
+
+ free_sec_desc(&psd);
+ talloc_destroy(mem_ctx);
+
+ *pdef_class = 0;
+ *pdef_code = 0;
+ return True;
+}
+
+/****************************************************************************
Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
****************************************************************************/
@@ -1068,6 +1139,7 @@ static int call_nt_transact_create(connection_struct *conn,
{
pstring fname;
char *params = *ppparams;
+ char *data = *ppdata;
int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
@@ -1088,10 +1160,13 @@ static int call_nt_transact_create(connection_struct *conn,
uint32 create_disposition;
uint32 create_options;
uint32 fname_len;
+ uint32 sd_len;
uint16 root_dir_fid;
int smb_ofun;
int smb_open_mode;
int smb_attr;
+ int error_class;
+ uint32 error_code;
DEBUG(5,("call_nt_transact_create\n"));
@@ -1122,6 +1197,7 @@ static int call_nt_transact_create(connection_struct *conn,
share_access = IVAL(params,24);
create_disposition = IVAL(params,28);
create_options = IVAL(params,32);
+ sd_len = IVAL(params,36);
fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1));
root_dir_fid = (uint16)IVAL(params,4);
smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
@@ -1336,6 +1412,16 @@ static int call_nt_transact_create(connection_struct *conn,
smb_action |= EXTENDED_OPLOCK_GRANTED;
}
+ /*
+ * Now try and apply the desired SD.
+ */
+
+ if (!set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) {
+ close_file(fsp,False);
+ restore_case_semantics(file_attributes);
+ return(ERROR(error_class, error_code));
+ }
+
restore_case_semantics(file_attributes);
/* Realloc the size of parameters and data we will return */
@@ -1621,13 +1707,11 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
char *params= *ppparams;
char *data = *ppdata;
- prs_struct pd;
- SEC_DESC *psd = NULL;
uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount);
files_struct *fsp = NULL;
uint32 security_info_sent = 0;
- TALLOC_CTX *mem_ctx;
- BOOL ret;
+ int error_class;
+ uint32 error_code;
if(!lp_nt_acl_support())
return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -1643,49 +1727,9 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name,
(unsigned int)security_info_sent ));
- /*
- * Init the parse struct we will unmarshall from.
- */
-
- if ((mem_ctx = talloc_init()) == NULL) {
- DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n"));
- return(ERROR(ERRDOS,ERRnomem));
- }
-
- prs_init(&pd, 0, 4, mem_ctx, UNMARSHALL);
-
- /*
- * Setup the prs_struct to point at the memory we just
- * allocated.
- */
-
- prs_give_memory( &pd, data, total_data_count, False);
-
- /*
- * Finally, unmarshall from the data buffer.
- */
-
- if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
- free_sec_desc(&psd);
- DEBUG(0,("call_nt_transact_set_security_desc: Error in unmarshalling \
-security descriptor.\n"));
- /*
- * Return access denied for want of a better error message..
- */
- talloc_destroy(mem_ctx);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- ret = set_nt_acl( fsp, security_info_sent, psd);
+ if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code))
+ return (ERROR(error_class, error_code));
- if (!ret) {
- free_sec_desc(&psd);
- talloc_destroy(mem_ctx);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- free_sec_desc(&psd);
- talloc_destroy(mem_ctx);
send_nt_replies(inbuf, outbuf, bufsize, 0, NULL, 0, NULL, 0);
return -1;
}
@@ -1774,6 +1818,9 @@ due to being in oplock break state.\n" ));
if ((total_parameter_count && !params) || (total_data_count && !data) ||
(setup_count && !setup)) {
+ safe_free(setup);
+ safe_free(params);
+ safe_free(data);
DEBUG(0,("reply_nttrans : Out of memory\n"));
END_PROFILE(SMBnttrans);
return(ERROR(ERRDOS,ERRnomem));