mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
r6141: Fix OS/2 EA's for NTcreate. OpenX and mkdir to follow.
Jeremy.
(This used to be commit 106f91ff65
)
This commit is contained in:
parent
f1977014f4
commit
b7c6e71b26
@ -1718,6 +1718,11 @@ struct ea_struct {
|
||||
DATA_BLOB value;
|
||||
};
|
||||
|
||||
struct ea_list {
|
||||
struct ea_list *next, *prev;
|
||||
struct ea_struct ea;
|
||||
};
|
||||
|
||||
/* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
|
||||
#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
|
||||
/* EA to use for DOS attributes */
|
||||
|
@ -1165,6 +1165,34 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
|
||||
****************************************************************************/
|
||||
|
||||
static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
|
||||
{
|
||||
struct ea_list *ea_list_head = NULL;
|
||||
size_t offset = 0;
|
||||
|
||||
if (data_size < 4) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (offset + 4 <= data_size) {
|
||||
size_t next_offset = IVAL(pdata,offset);
|
||||
struct ea_list *tmp;
|
||||
struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
|
||||
|
||||
DLIST_ADD_END(ea_list_head, eal, tmp);
|
||||
if (next_offset == 0) {
|
||||
break;
|
||||
}
|
||||
offset += next_offset;
|
||||
}
|
||||
|
||||
return ea_list_head;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
|
||||
****************************************************************************/
|
||||
@ -1194,11 +1222,15 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
uint32 create_disposition;
|
||||
uint32 create_options;
|
||||
uint32 sd_len;
|
||||
uint32 ea_len;
|
||||
uint16 root_dir_fid;
|
||||
SMB_BIG_UINT allocation_size = 0;
|
||||
int smb_ofun;
|
||||
int smb_open_mode;
|
||||
time_t c_time;
|
||||
struct ea_list *ea_list = NULL;
|
||||
TALLOC_CTX *ctx = NULL;
|
||||
char *pdata = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(5,("call_nt_transact_create\n"));
|
||||
@ -1224,7 +1256,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
|
||||
if(parameter_count < 54) {
|
||||
DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
|
||||
return ERROR_DOS(ERRDOS,ERRnoaccess);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
flags = IVAL(params,0);
|
||||
@ -1234,8 +1266,24 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
create_disposition = IVAL(params,28);
|
||||
create_options = IVAL(params,32);
|
||||
sd_len = IVAL(params,36);
|
||||
ea_len = IVAL(params,40);
|
||||
root_dir_fid = (uint16)IVAL(params,4);
|
||||
|
||||
/* Ensure the data_len is correct for the sd and ea values given. */
|
||||
if ((ea_len + sd_len > data_count) ||
|
||||
(ea_len > data_count) || (sd_len > data_count) ||
|
||||
(ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (ea_len && !lp_ea_support(SNUM(conn))) {
|
||||
return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (ea_len < 10) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (create_options & FILE_OPEN_BY_FILE_ID) {
|
||||
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
@ -1368,6 +1416,23 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
}
|
||||
}
|
||||
|
||||
ctx = talloc_init("NTTRANS_CREATE_EA");
|
||||
if (!ctx) {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(NT_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
pdata = data + sd_len;
|
||||
|
||||
/* We have already checked that ea_len <= data_count here. */
|
||||
ea_list = read_nttrans_ea_list(ctx, pdata, ea_len);
|
||||
if (!ea_list ) {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a request for a directory open, deal with it separately.
|
||||
*/
|
||||
@ -1376,6 +1441,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
|
||||
/* Can't open a temp directory. IFS kit test. */
|
||||
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
@ -1390,6 +1457,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
|
||||
|
||||
if(!fsp) {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
|
||||
}
|
||||
@ -1422,10 +1490,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
|
||||
|
||||
if(!fsp) {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
|
||||
}
|
||||
} else {
|
||||
talloc_destroy(ctx);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
|
||||
/* We have re-scheduled this call. */
|
||||
@ -1442,9 +1512,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
fmode = FILE_ATTRIBUTE_NORMAL;
|
||||
|
||||
if (fmode & aDIR) {
|
||||
talloc_destroy(ctx);
|
||||
close_file(fsp,False);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_DOS(ERRDOS,ERRnoaccess);
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1453,11 +1524,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
* correct bit for extended oplock reply.
|
||||
*/
|
||||
|
||||
if (oplock_request && lp_fake_oplocks(SNUM(conn)))
|
||||
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
|
||||
extended_oplock_granted = True;
|
||||
}
|
||||
|
||||
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
|
||||
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
|
||||
extended_oplock_granted = True;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1474,9 +1547,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) {
|
||||
uint32 saved_access = fsp->desired_access;
|
||||
|
||||
/* We have already checked that sd_len <= data_count here. */
|
||||
|
||||
fsp->desired_access = FILE_GENERIC_ALL;
|
||||
|
||||
if (!NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
|
||||
talloc_destroy(ctx);
|
||||
close_file(fsp,False);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(status);
|
||||
@ -1484,6 +1560,16 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
fsp->desired_access = saved_access;
|
||||
}
|
||||
|
||||
if (ea_len && smb_action == FILE_WAS_CREATED) {
|
||||
status = set_ea(conn, fsp, fname, ea_list);
|
||||
talloc_destroy(ctx);
|
||||
if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) {
|
||||
close_file(fsp,False);
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
}
|
||||
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
|
||||
/* Save the requested allocation size. */
|
||||
|
@ -95,11 +95,6 @@ static BOOL samba_private_attr_name(const char *unix_ea_name)
|
||||
return False;
|
||||
}
|
||||
|
||||
struct ea_list {
|
||||
struct ea_list *next, *prev;
|
||||
struct ea_struct ea;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
Get one EA value. Fill in a struct ea_struct.
|
||||
****************************************************************************/
|
||||
@ -313,7 +308,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con
|
||||
Set or delete an extended attribute.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
|
||||
NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
|
||||
{
|
||||
if (!lp_ea_support(SNUM(conn))) {
|
||||
return NT_STATUS_EAS_NOT_SUPPORTED;
|
||||
@ -419,6 +414,63 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
|
||||
return ea_list_head;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Read one EA list entry from the buffer.
|
||||
****************************************************************************/
|
||||
|
||||
struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
|
||||
{
|
||||
struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
|
||||
uint16 val_len;
|
||||
unsigned int namelen;
|
||||
|
||||
if (!eal) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data_size < 6) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eal->ea.flags = CVAL(pdata,0);
|
||||
namelen = CVAL(pdata,1);
|
||||
val_len = SVAL(pdata,2);
|
||||
|
||||
if (4 + namelen + 1 + val_len > data_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensure the name is null terminated. */
|
||||
if (pdata[namelen + 4] != '\0') {
|
||||
return NULL;
|
||||
}
|
||||
pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
|
||||
if (!eal->ea.name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
|
||||
if (!eal->ea.value.data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
|
||||
|
||||
/* Ensure we're null terminated just in case we print the value. */
|
||||
eal->ea.value.data[val_len] = '\0';
|
||||
/* But don't count the null. */
|
||||
eal->ea.value.length--;
|
||||
|
||||
if (pbytes_used) {
|
||||
*pbytes_used = 4 + namelen + 1 + val_len;
|
||||
}
|
||||
|
||||
DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
|
||||
dump_data(10, eal->ea.value.data, eal->ea.value.length);
|
||||
|
||||
return eal;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
|
||||
****************************************************************************/
|
||||
@ -427,63 +479,18 @@ static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t d
|
||||
{
|
||||
struct ea_list *ea_list_head = NULL;
|
||||
size_t offset = 0;
|
||||
size_t bytes_used = 0;
|
||||
|
||||
if (data_size < 10) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Each entry must be at least 6 bytes in length. */
|
||||
while (offset + 6 <= data_size) {
|
||||
while (offset < data_size) {
|
||||
struct ea_list *tmp;
|
||||
struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
|
||||
uint16 val_len;
|
||||
unsigned int namelen;
|
||||
struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
|
||||
|
||||
eal->ea.flags = CVAL(pdata,offset);
|
||||
namelen = CVAL(pdata,offset + 1);
|
||||
val_len = SVAL(pdata,offset + 2);
|
||||
|
||||
/* integer wrap paranioa. */
|
||||
if ((offset + namelen + 5 + val_len < offset) ||
|
||||
(offset + namelen + 5 + val_len < namelen) ||
|
||||
(offset + namelen + 5 + val_len < val_len) ||
|
||||
(offset > data_size) ||
|
||||
(namelen > data_size) ||
|
||||
(offset + namelen >= data_size)) {
|
||||
if (!eal) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (offset + 4 + namelen + 1 + val_len > data_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensure the name is null terminated. */
|
||||
if (pdata[offset + 4 + namelen] != '\0') {
|
||||
return NULL;
|
||||
}
|
||||
pull_ascii_talloc(ctx, &eal->ea.name, pdata + offset + 4);
|
||||
if (!eal->ea.name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
|
||||
if (!eal->ea.value.data) {
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(eal->ea.value.data, pdata + offset + 4 + namelen + 1, val_len);
|
||||
|
||||
/* Ensure we're null terminated just in case we print the value. */
|
||||
eal->ea.value.data[val_len] = '\0';
|
||||
/* But don't count the null. */
|
||||
eal->ea.value.length--;
|
||||
|
||||
offset += 4 + namelen + 1 + val_len;
|
||||
|
||||
DLIST_ADD_END(ea_list_head, eal, tmp);
|
||||
|
||||
DEBUG(10,("read_ea_list: read ea name %s\n", eal->ea.name));
|
||||
dump_data(10, eal->ea.value.data, eal->ea.value.length);
|
||||
offset += bytes_used;
|
||||
}
|
||||
|
||||
return ea_list_head;
|
||||
|
Loading…
Reference in New Issue
Block a user