This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
static char *nttrans_realloc(char **ptr, size_t size)
{
if (ptr==NULL) {
- smb_panic("nttrans_realloc() called with NULL ptr\n");
+ smb_panic("nttrans_realloc() called with NULL ptr");
}
*ptr = (char *)SMB_REALLOC(*ptr, size);
return (strchr_m(fname, ':') != NULL) ? True : False;
}
+struct case_semantics_state {
+ connection_struct *conn;
+ BOOL case_sensitive;
+ BOOL case_preserve;
+ BOOL short_case_preserve;
+};
+
/****************************************************************************
- Save case statics.
+ Restore case semantics.
****************************************************************************/
-
-static BOOL saved_case_sensitive;
-static BOOL saved_case_preserve;
-static BOOL saved_short_case_preserve;
+static int restore_case_semantics(struct case_semantics_state *state)
+{
+ state->conn->case_sensitive = state->case_sensitive;
+ state->conn->case_preserve = state->case_preserve;
+ state->conn->short_case_preserve = state->short_case_preserve;
+ return 0;
+}
/****************************************************************************
Save case semantics.
****************************************************************************/
-
-static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
+static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
+ connection_struct *conn)
{
- if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
- return file_attributes;
+ struct case_semantics_state *result;
+
+ if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
}
- saved_case_sensitive = conn->case_sensitive;
- saved_case_preserve = conn->case_preserve;
- saved_short_case_preserve = conn->short_case_preserve;
+ result->case_sensitive = conn->case_sensitive;
+ result->case_preserve = conn->case_preserve;
+ result->short_case_preserve = conn->short_case_preserve;
/* Set to POSIX. */
conn->case_sensitive = True;
conn->case_preserve = True;
conn->short_case_preserve = True;
- return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
-}
-
-/****************************************************************************
- Restore case semantics.
-****************************************************************************/
+ talloc_set_destructor(result, restore_case_semantics);
-static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
-{
- if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
- return;
- }
-
- conn->case_sensitive = saved_case_sensitive;
- conn->case_preserve = saved_case_preserve;
- conn->short_case_preserve = saved_short_case_preserve;
+ return result;
}
/****************************************************************************
char *p = NULL;
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+ srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), fname, smb_buf(inbuf),
+ sizeof(fname), STR_TERMINATE);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
return ret;
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
- uint32 new_file_attributes;
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
struct timespec m_timespec;
BOOL extended_oplock_granted = False;
NTSTATUS status;
+ struct smb_request req;
+ struct case_semantics_state *case_state = NULL;
START_PROFILE(SMBntcreateX);
(unsigned int)create_options,
(unsigned int)root_dir_fid ));
+ init_smb_request(&req, (uint8 *)inbuf);
+
/*
* If it's an IPC, use the pipe handler.
*/
if(!dir_fsp->is_directory) {
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
+ smb_buf(inbuf), sizeof(fname), 0,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
dir_name_len++;
}
- srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), rel_fname,
+ smb_buf(inbuf), sizeof(rel_fname), 0,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
pstrcat(fname, rel_fname);
} else {
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
+ smb_buf(inbuf), sizeof(fname), 0,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
* Check if POSIX semantics are wanted.
*/
- new_file_attributes = set_posix_case_semantics(conn, file_attributes);
+ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ case_state = set_posix_case_semantics(NULL, conn);
+ file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
/* All file access must go through check_name() */
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
&& (access_mask & DELETE_ACCESS)) {
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
!can_delete_file_in_directory(conn, fname)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
}
+#if 0
+ /* We need to support SeSecurityPrivilege for this. */
+ if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) &&
+ !user_has_privileges(current_user.nt_user_token,
+ &se_security)) {
+ TALLOC_FREE(case_state);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD);
+ }
+#endif
+
/*
* If it's a request for a directory open, deal with it separately.
*/
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
oplock_request = 0;
- status = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, &req, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
&info, &fsp);
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
if(!NT_STATUS_IS_OK(status)) {
if (!use_nt_status() && NT_STATUS_EQUAL(
* before issuing an oplock break request to
* our client. JRA. */
- status = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn, &req, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
oplock_request,
&info, &fsp);
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
- status = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, &req, fname,
+ &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
&info, &fsp);
if(!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
if (!use_nt_status() && NT_STATUS_EQUAL(
status, NT_STATUS_OBJECT_NAME_COLLISION)) {
status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
return ERROR_NT(status);
}
} else {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
}
}
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
flags = IVAL(params,0);
- srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53,
+ sizeof(fname), parameter_count-53, STR_TERMINATE,
+ &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
prs_struct pd;
SEC_DESC *psd = NULL;
TALLOC_CTX *mem_ctx;
- BOOL ret;
+ NTSTATUS status;
if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
security_info_sent &= ~DACL_SECURITY_INFORMATION;
}
- ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
-
- if (!ret) {
- talloc_destroy(mem_ctx);
- return NT_STATUS_ACCESS_DENIED;
- }
+ status = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
talloc_destroy(mem_ctx);
-
- return NT_STATUS_OK;
+ return status;
}
/****************************************************************************
uint32 flags;
uint32 access_mask;
uint32 file_attributes;
- uint32 new_file_attributes;
uint32 share_access;
uint32 create_disposition;
uint32 create_options;
char *pdata = NULL;
NTSTATUS status;
size_t param_len;
+ struct smb_request req;
+ struct case_semantics_state *case_state = NULL;
DEBUG(5,("call_nt_transact_create\n"));
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
+ init_smb_request(&req, (uint8 *)inbuf);
+
flags = IVAL(params,0);
access_mask = IVAL(params,8);
file_attributes = IVAL(params,20);
}
if(!dir_fsp->is_directory) {
- srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
+ params+53, sizeof(fname),
+ parameter_count-53, STR_TERMINATE,
+ &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
{
pstring tmpname;
- srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), tmpname,
+ params+53, sizeof(tmpname),
+ parameter_count-53, STR_TERMINATE,
+ &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
pstrcat(fname, tmpname);
}
} else {
- srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53,
+ sizeof(fname), parameter_count-53,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/*
* Check if POSIX semantics are wanted.
*/
+
+ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ case_state = set_posix_case_semantics(NULL, conn);
+ file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+ }
- new_file_attributes = set_posix_case_semantics(conn, file_attributes);
-
status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(case_state);
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
}
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
/* All file access must go through check_name() */
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
&& (access_mask & DELETE_ACCESS)) {
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
!can_delete_file_in_directory(conn, fname)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
}
+#if 0
+ /* We need to support SeSecurityPrivilege for this. */
+ if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) &&
+ !user_has_privileges(current_user.nt_user_token,
+ &se_security)) {
+ TALLOC_FREE(case_state);
+ return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD);
+ }
+#endif
+
if (ea_len) {
pdata = data + sd_len;
ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata,
ea_len);
if (!ea_list ) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
}
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
*/
oplock_request = 0;
- status = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, &req, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
&info, &fsp);
if(!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
* Ordinary file case.
*/
- status = open_file_ntcreate(conn,fname,&sbuf,
+ status = open_file_ntcreate(conn,&req,fname,&sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
oplock_request,
&info, &fsp);
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
- status = open_directory(conn, fname, &sbuf,
+ status = open_directory(conn, &req, fname,
+ &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- new_file_attributes,
+ file_attributes,
&info, &fsp);
if(!NT_STATUS_IS_OK(status)) {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
} else {
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(ctx);
close_file(fsp,ERROR_CLOSE);
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
fsp->access_mask = saved_access_mask;
status = set_ea(conn, fsp, fname, ea_list);
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp,ERROR_CLOSE);
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
return ERROR_NT(status);
}
}
- restore_case_semantics(conn, file_attributes);
+ TALLOC_FREE(case_state);
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
Copy a file.
****************************************************************************/
-static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
+static NTSTATUS copy_internals(connection_struct *conn,
+ struct smb_request *req,
+ char *oldname, char *newname, uint32 attrs)
{
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
}
/* Ensure this is within the share. */
- status = reduce_name(conn, oldname);
+ status = check_reduced_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
- status = open_file_ntcreate(conn,oldname,&sbuf1,
+ status = open_file_ntcreate(conn, req, oldname, &sbuf1,
FILE_READ_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
return status;
}
- status = open_file_ntcreate(conn,newname,&sbuf2,
+ status = open_file_ntcreate(conn, req, newname, &sbuf2,
FILE_WRITE_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_CREATE,
BOOL dest_has_wcard = False;
uint32 attrs = SVAL(inbuf,smb_vwv0);
uint16 rename_type = SVAL(inbuf,smb_vwv1);
+ struct smb_request req;
START_PROFILE(SMBntrename);
+ init_smb_request(&req, (uint8 *)inbuf);
+
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), oldname, p,
+ sizeof(oldname), 0, STR_TERMINATE, &status,
+ &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
}
p++;
- p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
+ sizeof(newname), 0, STR_TERMINATE, &status,
+ &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
switch(rename_type) {
case RENAME_FLAG_RENAME:
- status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
+ status = rename_internals(conn, &req, oldname, newname,
+ attrs, False, src_has_wcard,
+ dest_has_wcard);
break;
case RENAME_FLAG_HARD_LINK:
if (src_has_wcard || dest_has_wcard) {
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
- status = copy_internals(conn, oldname, newname, attrs);
+ status = copy_internals(conn, &req, oldname,
+ newname, attrs);
}
break;
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
* here.
*/
- change_notify_reply(inbuf, max_param_count,
- fsp->notify);
+ change_notify_reply(inbuf, fsp->notify);
/*
* change_notify_reply() above has independently sent its
* No changes pending, queue the request
*/
- status = change_notify_add_request(inbuf, max_param_count, filter,
- recursive, fsp);
+ status = change_notify_add_request(inbuf, filter, recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
BOOL replace_if_exists = False;
BOOL dest_has_wcard = False;
NTSTATUS status;
+ struct smb_request req;
+
+ init_smb_request(&req, (uint8 *)inbuf);
if(parameter_count < 5) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
- srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
- STR_TERMINATE, &status, &dest_has_wcard);
+ srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), new_name, params+4,
+ sizeof(new_name), parameter_count - 4,
+ STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- status = rename_internals(conn, fsp->fsp_name,
+ status = rename_internals(conn, &req, fsp->fsp_name,
new_name, 0, replace_if_exists, False, dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {