summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/aio.c66
-rw-r--r--source3/smbd/blocking.c22
-rw-r--r--source3/smbd/change_trust_pw.c2
-rw-r--r--source3/smbd/chgpasswd.c116
-rw-r--r--source3/smbd/close.c552
-rw-r--r--source3/smbd/conn.c96
-rw-r--r--source3/smbd/dir.c630
-rw-r--r--source3/smbd/dosmode.c513
-rw-r--r--source3/smbd/error.c80
-rw-r--r--source3/smbd/fake_file.c49
-rw-r--r--source3/smbd/file_access.c112
-rw-r--r--source3/smbd/fileio.c104
-rw-r--r--source3/smbd/filename.c618
-rw-r--r--source3/smbd/filename_util.c206
-rw-r--r--source3/smbd/files.c96
-rw-r--r--source3/smbd/globals.c55
-rw-r--r--source3/smbd/globals.h412
-rw-r--r--source3/smbd/ipc.c8
-rw-r--r--source3/smbd/lanman.c80
-rw-r--r--source3/smbd/mangle_hash.c20
-rw-r--r--source3/smbd/map_username.c4
-rw-r--r--source3/smbd/message.c10
-rw-r--r--source3/smbd/msdfs.c181
-rw-r--r--source3/smbd/negprot.c95
-rw-r--r--source3/smbd/notify.c142
-rw-r--r--source3/smbd/notify_inotify.c19
-rw-r--r--source3/smbd/notify_internal.c323
-rw-r--r--source3/smbd/nttrans.c743
-rw-r--r--source3/smbd/open.c938
-rw-r--r--source3/smbd/oplock.c61
-rw-r--r--source3/smbd/oplock_irix.c13
-rw-r--r--source3/smbd/oplock_linux.c9
-rw-r--r--source3/smbd/oplock_onefs.c41
-rw-r--r--source3/smbd/password.c244
-rw-r--r--source3/smbd/pipes.c53
-rw-r--r--source3/smbd/posix_acls.c597
-rw-r--r--source3/smbd/process.c364
-rw-r--r--source3/smbd/quotas.c52
-rw-r--r--source3/smbd/reply.c3203
-rw-r--r--source3/smbd/seal.c1
-rw-r--r--source3/smbd/server.c81
-rw-r--r--source3/smbd/service.c74
-rw-r--r--source3/smbd/sesssetup.c192
-rw-r--r--source3/smbd/share_access.c8
-rw-r--r--source3/smbd/signing.c158
-rw-r--r--source3/smbd/smb2_break.c210
-rw-r--r--source3/smbd/smb2_close.c129
-rw-r--r--source3/smbd/smb2_create.c754
-rw-r--r--source3/smbd/smb2_find.c454
-rw-r--r--source3/smbd/smb2_flush.c195
-rw-r--r--source3/smbd/smb2_getinfo.c424
-rw-r--r--source3/smbd/smb2_glue.c52
-rw-r--r--source3/smbd/smb2_ioctl.c461
-rw-r--r--source3/smbd/smb2_keepalive.c55
-rw-r--r--source3/smbd/smb2_lock.c383
-rw-r--r--source3/smbd/smb2_negprot.c181
-rw-r--r--source3/smbd/smb2_notify.c388
-rw-r--r--source3/smbd/smb2_read.c345
-rw-r--r--source3/smbd/smb2_server.c1586
-rw-r--r--source3/smbd/smb2_sesssetup.c407
-rw-r--r--source3/smbd/smb2_setinfo.c330
-rw-r--r--source3/smbd/smb2_signing.c135
-rw-r--r--source3/smbd/smb2_tcon.c284
-rw-r--r--source3/smbd/smb2_write.c344
-rw-r--r--source3/smbd/srvstr.c4
-rw-r--r--source3/smbd/statcache.c9
-rw-r--r--source3/smbd/trans2.c4404
-rw-r--r--source3/smbd/uid.c3
-rw-r--r--source3/smbd/vfs.c1265
69 files changed, 6338 insertions, 17907 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 751fed168f..406ec1b3e3 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -25,6 +25,9 @@
/* The signal we'll use to signify aio done. */
#ifndef RT_SIGNAL_AIO
+#ifndef SIGRTMIN
+#define SIGRTMIN NSIG
+#endif
#define RT_SIGNAL_AIO (SIGRTMIN+3)
#endif
@@ -189,9 +192,10 @@ bool schedule_aio_read_and_X(connection_struct *conn,
DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, "
"offset %.0f, len = %u (mid = %u)\n",
- fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt,
+ fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt,
(unsigned int)aio_ex->req->mid ));
+ srv_defer_sign_response(aio_ex->req->mid);
return True;
}
@@ -241,7 +245,7 @@ bool schedule_aio_write_and_X(connection_struct *conn,
DEBUG(10,("schedule_aio_write_and_X: failed to schedule "
"aio_write for file %s, offset %.0f, len = %u "
"(mid = %u)\n",
- fsp_str_dbg(fsp), (double)startpos,
+ fsp->fsp_name, (double)startpos,
(unsigned int)numtowrite,
(unsigned int)req->mid ));
return False;
@@ -294,20 +298,21 @@ bool schedule_aio_write_and_X(connection_struct *conn,
SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
show_msg(aio_ex->outbuf);
if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
- true, aio_ex->req->seqnum+1,
IS_CONN_ENCRYPTED(fsp->conn),
&aio_ex->req->pcd)) {
exit_server_cleanly("handle_aio_write: srv_send_smb "
"failed.");
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
- "behind for file %s\n", fsp_str_dbg(fsp)));
+ "behind for file %s\n", fsp->fsp_name ));
+ } else {
+ srv_defer_sign_response(aio_ex->req->mid);
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
"%s, offset %.0f, len = %u (mid = %u) "
"outstanding_aio_calls = %d\n",
- fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite,
+ fsp->fsp_name, (double)startpos, (unsigned int)numtowrite,
(unsigned int)aio_ex->req->mid, outstanding_aio_calls ));
return True;
@@ -321,6 +326,7 @@ bool schedule_aio_write_and_X(connection_struct *conn,
static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
{
+ int ret = 0;
int outsize;
char *outbuf = aio_ex->outbuf;
char *data = smb_buf(outbuf);
@@ -332,11 +338,12 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
will return an error. Hopefully this is
true.... JRA. */
- DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d. "
+ DEBUG( 3,( "handle_aio_read_complete: file %s nread == %d "
"Error = %s\n",
- fsp_str_dbg(aio_ex->fsp), (int)nread, strerror(errcode)));
+ aio_ex->fsp->fsp_name, (int)nread, strerror(errcode) ));
- ERROR_NT(map_nt_error_from_unix(errcode));
+ ret = errcode;
+ ERROR_NT(map_nt_error_from_unix( ret));
outsize = srv_set_message(outbuf,0,0,true);
} else {
outsize = srv_set_message(outbuf,12,nread,False);
@@ -351,14 +358,13 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
DEBUG( 3, ( "handle_aio_read_complete file %s max=%d "
"nread=%d\n",
- fsp_str_dbg(aio_ex->fsp),
+ aio_ex->fsp->fsp_name,
(int)aio_ex->acb.aio_nbytes, (int)nread ) );
}
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!srv_send_smb(smbd_server_fd(),outbuf,
- true, aio_ex->req->seqnum+1,
IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
"failed.");
@@ -366,10 +372,10 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed "
"for file %s, offset %.0f, len = %u\n",
- fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset,
+ aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset,
(unsigned int)nread ));
- return errcode;
+ return ret;
}
/****************************************************************************
@@ -379,6 +385,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex, int errcode)
static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
{
+ int ret = 0;
files_struct *fsp = aio_ex->fsp;
char *outbuf = aio_ex->outbuf;
ssize_t numtowrite = aio_ex->acb.aio_nbytes;
@@ -390,20 +397,21 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
DEBUG(5,("handle_aio_write_complete: "
"aio_write_behind failed ! File %s "
"is corrupt ! Error %s\n",
- fsp_str_dbg(fsp), strerror(errcode)));
+ fsp->fsp_name, strerror(errcode) ));
+ ret = errcode;
} else {
DEBUG(0,("handle_aio_write_complete: "
"aio_write_behind failed ! File %s "
"is corrupt ! Wanted %u bytes but "
- "only wrote %d\n", fsp_str_dbg(fsp),
+ "only wrote %d\n", fsp->fsp_name,
(unsigned int)numtowrite,
(int)nwritten ));
- errcode = EIO;
+ ret = EIO;
}
} else {
DEBUG(10,("handle_aio_write_complete: "
"aio_write_behind completed for file %s\n",
- fsp_str_dbg(fsp)));
+ fsp->fsp_name ));
}
/* TODO: should no return 0 in case of an error !!! */
return 0;
@@ -415,10 +423,11 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
if(nwritten == -1) {
DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. "
"nwritten == %d. Error = %s\n",
- fsp_str_dbg(fsp), (unsigned int)numtowrite,
- (int)nwritten, strerror(errcode) ));
+ fsp->fsp_name, (unsigned int)numtowrite,
+ (int)nwritten, strerror(errno) ));
- ERROR_NT(map_nt_error_from_unix(errcode));
+ ret = errcode;
+ ERROR_NT(map_nt_error_from_unix(ret));
srv_set_message(outbuf,0,0,true);
} else {
bool write_through = BITSETW(aio_ex->req->vwv+7,0);
@@ -435,31 +444,29 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex, int errcode)
fsp->fnum, (int)numtowrite, (int)nwritten));
status = sync_file(fsp->conn,fsp, write_through);
if (!NT_STATUS_IS_OK(status)) {
- errcode = errno;
- ERROR_BOTH(map_nt_error_from_unix(errcode),
+ ret = errno;
+ ERROR_BOTH(map_nt_error_from_unix(ret),
ERRHRD, ERRdiskfull);
srv_set_message(outbuf,0,0,true);
DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
}
aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten;
}
show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(),outbuf,
- true, aio_ex->req->seqnum+1,
- IS_CONN_ENCRYPTED(fsp->conn),
+ if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
}
DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed "
"for file %s, offset %.0f, requested %u, written = %u\n",
- fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset,
+ fsp->fsp_name, (double)aio_ex->acb.aio_offset,
(unsigned int)numtowrite, (unsigned int)nwritten ));
- return errcode;
+ return ret;
}
/****************************************************************************
@@ -481,13 +488,14 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr)
if (err == EINPROGRESS) {
DEBUG(10,( "handle_aio_completed: operation mid %u still in "
"process for file %s\n",
- aio_ex->req->mid, fsp_str_dbg(aio_ex->fsp)));
+ aio_ex->req->mid, aio_ex->fsp->fsp_name ));
return False;
} else if (err == ECANCELED) {
/* If error is ECANCELED then don't return anything to the
* client. */
DEBUG(10,( "handle_aio_completed: operation mid %u"
" canceled\n", aio_ex->req->mid));
+ srv_cancel_sign_response(aio_ex->req->mid, false);
return True;
}
@@ -516,6 +524,7 @@ void smbd_aio_complete_mid(unsigned int mid)
if (!aio_ex) {
DEBUG(3,("smbd_aio_complete_mid: Can't find record to "
"match mid %u.\n", mid));
+ srv_cancel_sign_response(mid, false);
return;
}
@@ -525,6 +534,7 @@ void smbd_aio_complete_mid(unsigned int mid)
* ignore. */
DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
"aio outstanding (mid[%u]).\n", mid));
+ srv_cancel_sign_response(mid, false);
return;
}
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index e33c0b6ae5..0eeb0b5221 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -185,7 +185,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
count,
lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
blr->lock_flav,
- True,
+ lock_timeout ? True : False, /* blocking_lock. */
NULL,
blr);
@@ -212,7 +212,10 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
"expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n",
(unsigned int)blr->expire_time.tv_sec,
(unsigned int)blr->expire_time.tv_usec, lock_timeout,
- blr->fsp->fnum, fsp_str_dbg(blr->fsp)));
+ blr->fsp->fnum, blr->fsp->fsp_name ));
+
+ /* Push the MID of this packet on the signing queue. */
+ srv_defer_sign_response(blr->req->mid);
return True;
}
@@ -267,7 +270,6 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT
reply_nterror(blr->req, status);
if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
- true, blr->req->seqnum+1,
blr->req->encrypted, NULL)) {
exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
}
@@ -351,7 +353,6 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
if (!srv_send_smb(smbd_server_fd(),
(char *)blr->req->outbuf,
- true, blr->req->seqnum+1,
IS_CONN_ENCRYPTED(blr->fsp->conn),
NULL)) {
exit_server_cleanly("blocking_lock_reply_error: "
@@ -428,9 +429,8 @@ static bool process_lockingX(struct blocking_lock_record *blr)
* Success - we got all the locks.
*/
- DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d "
- "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum,
- (unsigned int)locktype, num_locks));
+ DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n",
+ fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) );
reply_lockingX_success(blr);
return True;
@@ -453,7 +453,7 @@ static bool process_lockingX(struct blocking_lock_record *blr)
DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \
Waiting....\n",
- blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum));
+ blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum));
return False;
}
@@ -544,7 +544,7 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo
DEBUG(10, ("remove_pending_lock_requests_by_fid - removing "
"request type %d for file %s fnum = %d\n",
- blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum));
+ blr->req->cmd, fsp->fsp_name, fsp->fnum));
blr_cancelled = blocking_lock_cancel(fsp,
blr->lock_pid,
@@ -594,7 +594,7 @@ void remove_pending_lock_requests_by_mid(int mid)
if (br_lck) {
DEBUG(10, ("remove_pending_lock_requests_by_mid - "
"removing request type %d for file %s fnum "
- "= %d\n", blr->req->cmd, fsp_str_dbg(fsp),
+ "= %d\n", blr->req->cmd, fsp->fsp_name,
fsp->fnum ));
brl_lock_cancel(br_lck,
@@ -720,7 +720,7 @@ void process_blocking_lock_queue(void)
DEBUG(5,("process_blocking_lock_queue: "
"pending lock fnum = %d for file %s "
"timed out.\n", blr->fsp->fnum,
- fsp_str_dbg(blr->fsp)));
+ blr->fsp->fsp_name ));
brl_lock_cancel(br_lck,
blr->lock_pid,
diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c
index ec3046e0d2..72a72a78b5 100644
--- a/source3/smbd/change_trust_pw.c
+++ b/source3/smbd/change_trust_pw.c
@@ -92,7 +92,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
failed:
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n",
- current_timestring(talloc_tos(), False), domain));
+ current_timestring(debug_ctx(), False), domain));
}
else
DEBUG(5,("change_trust_account_password: sucess!\n"));
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index 074c51ddf2..61c3afb0dc 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -46,7 +46,6 @@
*/
#include "includes.h"
-#include "../libcli/auth/libcli_auth.h"
static NTSTATUS check_oem_password(const char *user,
uchar password_encrypted_with_lm_hash[516],
@@ -850,7 +849,7 @@ static NTSTATUS check_oem_password(const char *user,
const uint8 *encryption_key;
const uint8 *lanman_pw, *nt_pw;
uint32 acct_ctrl;
- size_t new_pw_len;
+ uint32 new_pw_len;
uchar new_nt_hash[16];
uchar new_lm_hash[16];
uchar verifier[16];
@@ -919,13 +918,13 @@ static NTSTATUS check_oem_password(const char *user,
/*
* Decrypt the password with the key
*/
- arcfour_crypt( password_encrypted, encryption_key, 516);
+ SamOEMhash( password_encrypted, encryption_key, 516);
if (!decode_pw_buffer(talloc_tos(),
password_encrypted,
pp_new_passwd,
&new_pw_len,
- nt_pass_set ? CH_UTF16 : CH_DOS)) {
+ nt_pass_set ? STR_UNICODE : STR_ASCII)) {
return NT_STATUS_WRONG_PASSWORD;
}
@@ -1008,59 +1007,6 @@ static NTSTATUS check_oem_password(const char *user,
return NT_STATUS_WRONG_PASSWORD;
}
-bool password_in_history(uint8_t nt_pw[NT_HASH_LEN],
- uint32_t pw_history_len,
- const uint8_t *pw_history)
-{
- static const uint8_t zero_md5_nt_pw[SALTED_MD5_HASH_LEN] = { 0, };
- int i;
-
- dump_data(100, nt_pw, NT_HASH_LEN);
- dump_data(100, pw_history, PW_HISTORY_ENTRY_LEN * pw_history_len);
-
- for (i=0; i<pw_history_len; i++) {
- uint8_t new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN];
- const uint8_t *current_salt;
- const uint8_t *old_nt_pw_salted_md5_hash;
-
- current_salt = &pw_history[i*PW_HISTORY_ENTRY_LEN];
- old_nt_pw_salted_md5_hash = current_salt + PW_HISTORY_SALT_LEN;
-
- if (memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash,
- SALTED_MD5_HASH_LEN) == 0) {
- /* Ignore zero valued entries. */
- continue;
- }
-
- if (memcmp(zero_md5_nt_pw, current_salt,
- PW_HISTORY_SALT_LEN) == 0)
- {
- /*
- * New format: zero salt and then plain nt hash.
- * Directly compare the hashes.
- */
- if (memcmp(nt_pw, old_nt_pw_salted_md5_hash,
- SALTED_MD5_HASH_LEN) == 0)
- {
- return true;
- }
- } else {
- /*
- * Old format: md5sum of salted nt hash.
- * Create salted version of new pw to compare.
- */
- E_md5hash(current_salt, nt_pw, new_nt_pw_salted_md5_hash);
-
- if (memcmp(new_nt_pw_salted_md5_hash,
- old_nt_pw_salted_md5_hash,
- SALTED_MD5_HASH_LEN) == 0) {
- return true;
- }
- }
- }
- return false;
-}
-
/***********************************************************
This routine takes the given password and checks it against
the password history. Returns True if this password has been
@@ -1070,11 +1016,14 @@ bool password_in_history(uint8_t nt_pw[NT_HASH_LEN],
static bool check_passwd_history(struct samu *sampass, const char *plaintext)
{
uchar new_nt_p16[NT_HASH_LEN];
+ uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN];
const uint8 *nt_pw;
const uint8 *pwhistory;
+ bool found = False;
+ int i;
uint32 pwHisLen, curr_pwHisLen;
- pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHisLen);
+ pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen);
if (pwHisLen == 0) {
return False;
}
@@ -1098,13 +1047,30 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext)
return True;
}
- if (password_in_history(new_nt_p16, pwHisLen, pwhistory)) {
- DEBUG(1,("check_passwd_history: proposed new password for "
- "user %s found in history list !\n",
- pdb_get_username(sampass) ));
- return true;
+ dump_data(100, new_nt_p16, NT_HASH_LEN);
+ dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen);
+
+ memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN);
+ for (i=0; i<pwHisLen; i++) {
+ uchar new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN];
+ const uchar *current_salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
+ const uchar *old_nt_pw_salted_md5_hash = &pwhistory[(i*PW_HISTORY_ENTRY_LEN)+
+ PW_HISTORY_SALT_LEN];
+ if (!memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
+ /* Ignore zero valued entries. */
+ continue;
+ }
+ /* Create salted versions of new to compare. */
+ E_md5hash(current_salt, new_nt_p16, new_nt_pw_salted_md5_hash);
+
+ if (!memcmp(new_nt_pw_salted_md5_hash, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) {
+ DEBUG(1,("check_passwd_history: proposed new password for user %s found in history list !\n",
+ pdb_get_username(sampass) ));
+ found = True;
+ break;
+ }
}
- return false;
+ return found;
}
/***********************************************************
@@ -1118,7 +1084,6 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
{
uint32 min_len;
uint32 refuse;
- TALLOC_CTX *tosctx = talloc_tos();
struct passwd *pass = NULL;
const char *username = pdb_get_username(hnd);
time_t can_change_time = pdb_get_pass_can_change_time(hnd);
@@ -1140,7 +1105,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
* denies machines to change the password. *
* Should we deny also SRVTRUST and/or DOMSTRUST ? .SSS. */
if (pdb_get_acct_ctrl(hnd) & ACB_WSTRUST) {
- if (pdb_get_account_policy(PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) {
+ if (pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) {
DEBUG(1, ("Machine %s cannot change password now, "
"denied by Refuse Machine Password Change policy\n",
username));
@@ -1151,19 +1116,19 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
}
}
- /* removed calculation here, because passdb now calculates
+ /* removed calculation here, becuase passdb now calculates
based on policy. jmcd */
if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
DEBUG(1, ("user %s cannot change password now, must "
"wait until %s\n", username,
- http_timestring(tosctx, can_change_time)));
+ http_timestring(talloc_tos(), can_change_time)));
if (samr_reject_reason) {
*samr_reject_reason = SAMR_REJECT_OTHER;
}
return NT_STATUS_ACCOUNT_RESTRICTION;
}
- if (pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
+ if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
DEBUG(1, ("user %s cannot change password - password too short\n",
username));
DEBUGADD(1, (" account policy min password len = %d\n", min_len));
@@ -1181,7 +1146,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
return NT_STATUS_PASSWORD_RESTRICTION;
}
- pass = Get_Pwnam_alloc(tosctx, username);
+ pass = Get_Pwnam_alloc(talloc_tos(), username);
if (!pass) {
DEBUG(1, ("change_oem_password: Username %s does not exist in system !?!\n", username));
return NT_STATUS_ACCESS_DENIED;
@@ -1190,16 +1155,9 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
/* Use external script to check password complexity */
if (lp_check_password_script() && *(lp_check_password_script())) {
int check_ret;
- char *cmd;
-
- cmd = talloc_string_sub(tosctx, lp_check_password_script(), "%u", username);
- if (!cmd) {
- return NT_STATUS_PASSWORD_RESTRICTION;
- }
- check_ret = smbrunsecret(cmd, new_passwd);
- DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", cmd, check_ret));
- TALLOC_FREE(cmd);
+ check_ret = smbrunsecret(lp_check_password_script(), new_passwd);
+ DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret));
if (check_ret != 0) {
DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index ca1ac47fa0..d23b509af2 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -27,7 +27,7 @@ extern struct current_user current_user;
Run a file if it is a magic script.
****************************************************************************/
-static NTSTATUS check_magic(struct files_struct *fsp)
+static void check_magic(struct files_struct *fsp)
{
int ret;
const char *magic_output = NULL;
@@ -36,99 +36,77 @@ static NTSTATUS check_magic(struct files_struct *fsp)
TALLOC_CTX *ctx = NULL;
const char *p;
struct connection_struct *conn = fsp->conn;
- char *fname = NULL;
- NTSTATUS status;
if (!*lp_magicscript(SNUM(conn))) {
- return NT_STATUS_OK;
+ return;
}
- DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp)));
-
- ctx = talloc_stackframe();
-
- fname = fsp->fsp_name->base_name;
+ DEBUG(5,("checking magic for %s\n",fsp->fsp_name));
- if (!(p = strrchr_m(fname,'/'))) {
- p = fname;
+ if (!(p = strrchr_m(fsp->fsp_name,'/'))) {
+ p = fsp->fsp_name;
} else {
p++;
}
if (!strequal(lp_magicscript(SNUM(conn)),p)) {
- status = NT_STATUS_OK;
- goto out;
+ return;
}
+ ctx = talloc_stackframe();
+
if (*lp_magicoutput(SNUM(conn))) {
magic_output = lp_magicoutput(SNUM(conn));
} else {
magic_output = talloc_asprintf(ctx,
"%s.out",
- fname);
+ fsp->fsp_name);
}
if (!magic_output) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ TALLOC_FREE(ctx);
+ return;
}
/* Ensure we don't depend on user's PATH. */
- p = talloc_asprintf(ctx, "./%s", fname);
+ p = talloc_asprintf(ctx, "./%s", fsp->fsp_name);
if (!p) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ TALLOC_FREE(ctx);
+ return;
}
- if (chmod(fname, 0755) == -1) {
- status = map_nt_error_from_unix(errno);
- goto out;
+ if (chmod(fsp->fsp_name,0755) == -1) {
+ TALLOC_FREE(ctx);
+ return;
}
ret = smbrun(p,&tmp_fd);
DEBUG(3,("Invoking magic command %s gave %d\n",
p,ret));
- unlink(fname);
+ unlink(fsp->fsp_name);
if (ret != 0 || tmp_fd == -1) {
if (tmp_fd != -1) {
close(tmp_fd);
}
- status = NT_STATUS_UNSUCCESSFUL;
- goto out;
+ TALLOC_FREE(ctx);
+ return;
}
outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600);
if (outfd == -1) {
- int err = errno;
close(tmp_fd);
- status = map_nt_error_from_unix(err);
- goto out;
+ TALLOC_FREE(ctx);
+ return;
}
- if (sys_fstat(tmp_fd, &st, false) == -1) {
- int err = errno;
+ if (sys_fstat(tmp_fd,&st) == -1) {
close(tmp_fd);
close(outfd);
- status = map_nt_error_from_unix(err);
- goto out;
+ return;
}
- if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) {
- int err = errno;
- close(tmp_fd);
- close(outfd);
- status = map_nt_error_from_unix(err);
- goto out;
- }
+ transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_size);
close(tmp_fd);
- if (close(outfd) == -1) {
- status = map_nt_error_from_unix(errno);
- goto out;
- }
-
- status = NT_STATUS_OK;
-
- out:
+ close(outfd);
TALLOC_FREE(ctx);
- return status;
}
/****************************************************************************
@@ -226,32 +204,31 @@ NTSTATUS delete_all_streams(connection_struct *conn, const char *fname)
for (i=0; i<num_streams; i++) {
int res;
- struct smb_filename *smb_fname_stream = NULL;
+ char *streamname;
if (strequal(stream_info[i].name, "::$DATA")) {
continue;
}
- status = create_synthetic_smb_fname(talloc_tos(), fname,
- stream_info[i].name, NULL,
- &smb_fname_stream);
+ streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
+ stream_info[i].name);
- if (!NT_STATUS_IS_OK(status)) {
+ if (streamname == NULL) {
DEBUG(0, ("talloc_aprintf failed\n"));
+ status = NT_STATUS_NO_MEMORY;
goto fail;
}
- res = SMB_VFS_UNLINK(conn, smb_fname_stream);
+ res = SMB_VFS_UNLINK(conn, streamname);
+
+ TALLOC_FREE(streamname);
if (res == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(10, ("Could not delete stream %s: %s\n",
- smb_fname_str_dbg(smb_fname_stream),
- strerror(errno)));
- TALLOC_FREE(smb_fname_stream);
+ streamname, strerror(errno)));
break;
}
- TALLOC_FREE(smb_fname_stream);
}
fail:
@@ -269,19 +246,12 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
connection_struct *conn = fsp->conn;
bool delete_file = false;
bool changed_user = false;
- struct share_mode_lock *lck = NULL;
+ struct share_mode_lock *lck;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status = NT_STATUS_OK;
- NTSTATUS tmp_status;
+ int ret;
struct file_id id;
- /* Ensure any pending write time updates are done. */
- if (fsp->update_write_time_event) {
- update_write_time_handler(smbd_event_context(),
- fsp->update_write_time_event,
- timeval_current(),
- (void *)fsp);
- }
-
/*
* Lock the share entries, and determine if we should delete
* on close. If so delete whilst the lock is still in effect.
@@ -293,37 +263,17 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
if (lck == NULL) {
DEBUG(0, ("close_remove_share_mode: Could not get share mode "
- "lock for file %s\n", fsp_str_dbg(fsp)));
- status = NT_STATUS_INVALID_PARAMETER;
- goto done;
+ "lock for file %s\n", fsp->fsp_name));
+ return NT_STATUS_INVALID_PARAMETER;
}
if (fsp->write_time_forced) {
- DEBUG(10,("close_remove_share_mode: write time forced "
- "for file %s\n",
- fsp_str_dbg(fsp)));
set_close_write_time(fsp, lck->changed_write_time);
- } else if (fsp->update_write_time_on_close) {
- /* Someone had a pending write. */
- if (null_timespec(fsp->close_write_time)) {
- DEBUG(10,("close_remove_share_mode: update to current time "
- "for file %s\n",
- fsp_str_dbg(fsp)));
- /* Update to current time due to "normal" write. */
- set_close_write_time(fsp, timespec_current());
- } else {
- DEBUG(10,("close_remove_share_mode: write time pending "
- "for file %s\n",
- fsp_str_dbg(fsp)));
- /* Update to time set on close call. */
- set_close_write_time(fsp, fsp->close_write_time);
- }
}
if (!del_share_mode(lck, fsp)) {
DEBUG(0, ("close_remove_share_mode: Could not delete share "
- "entry for file %s\n",
- fsp_str_dbg(fsp)));
+ "entry for file %s\n", fsp->fsp_name));
}
if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) {
@@ -336,7 +286,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
become_user(conn, fsp->vuid);
became_user = True;
}
- fsp->delete_on_close = true;
set_delete_on_close_lck(lck, True, &current_user.ut);
if (became_user) {
unbecome_user();
@@ -382,7 +331,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
*/
DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
- "- deleting file.\n", fsp_str_dbg(fsp)));
+ "- deleting file.\n", fsp->fsp_name));
/*
* Don't try to update the write time when we delete the file
@@ -394,7 +343,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
DEBUG(5,("close_remove_share_mode: file %s. "
"Change user to uid %u\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
(unsigned int)lck->delete_token->uid));
if (!push_sec_ctx()) {
@@ -414,26 +363,31 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
/* We can only delete the file if the name we have is still valid and
hasn't been renamed. */
- tmp_status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(tmp_status)) {
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+ }
+
+ if (ret != 0) {
DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
"was set and stat failed with error %s\n",
- fsp_str_dbg(fsp), nt_errstr(tmp_status)));
+ fsp->fsp_name, strerror(errno) ));
/*
* Don't save the errno here, we ignore this error
*/
goto done;
}
- id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
+ id = vfs_file_id_from_sbuf(conn, &sbuf);
if (!file_id_equal(&fsp->file_id, &id)) {
DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
"was set and dev and/or inode does not match\n",
- fsp_str_dbg(fsp)));
+ fsp->fsp_name ));
DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
"stat file_id %s\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
file_id_string_tos(&fsp->file_id),
file_id_string_tos(&id)));
/*
@@ -443,9 +397,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
}
if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {
+ && !is_ntfs_stream_name(fsp->fsp_name)) {
- status = delete_all_streams(conn, fsp->fsp_name->base_name);
+ status = delete_all_streams(conn, fsp->fsp_name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("delete_all_streams failed: %s\n",
@@ -455,7 +409,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
}
- if (SMB_VFS_UNLINK(conn, fsp->fsp_name) != 0) {
+ if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) {
/*
* This call can potentially fail as another smbd may
* have had the file open with delete on close set and
@@ -466,14 +420,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
"was set and unlink failed with error %s\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ fsp->fsp_name, strerror(errno) ));
status = map_nt_error_from_unix(errno);
}
notify_fname(conn, NOTIFY_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_FILE_NAME,
- fsp->fsp_name->base_name);
+ fsp->fsp_name);
/* As we now have POSIX opens which can unlink
* with other open files we may have taken
@@ -482,7 +436,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
* the delete on close flag. JRA.
*/
- fsp->delete_on_close = false;
set_delete_on_close_lck(lck, False, NULL);
done:
@@ -503,17 +456,24 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts)
if (null_timespec(ts)) {
return;
}
+ /*
+ * if the write time on close is explict set, then don't
+ * need to fix it up to the value in the locking db
+ */
fsp->write_time_forced = false;
+
fsp->update_write_time_on_close = true;
fsp->close_write_time = ts;
}
static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
{
+ SMB_STRUCT_STAT sbuf;
struct smb_file_time ft;
NTSTATUS status;
- struct share_mode_lock *lck = NULL;
+ int ret = -1;
+ ZERO_STRUCT(sbuf);
ZERO_STRUCT(ft);
if (!fsp->update_write_time_on_close) {
@@ -525,45 +485,33 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
}
/* Ensure we have a valid stat struct for the source. */
- status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (fsp->fh->fd != -1) {
+ ret = SMB_VFS_FSTAT(fsp, &sbuf);
+ } else {
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf);
+ }
}
- if (!VALID_STAT(fsp->fsp_name->st)) {
- /* if it doesn't seem to be a real file */
- return NT_STATUS_OK;
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
}
- /* On close if we're changing the real file time we
- * must update it in the open file db too. */
- (void)set_write_time(fsp->file_id, fsp->close_write_time);
-
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL);
- if (lck) {
- /* Close write times overwrite sticky write times
- so we must replace any sticky write time here. */
- if (!null_timespec(lck->changed_write_time)) {
- (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
- }
- TALLOC_FREE(lck);
+ if (!VALID_STAT(sbuf)) {
+ /* if it doesn't seem to be a real file */
+ return NT_STATUS_OK;
}
ft.mtime = fsp->close_write_time;
- status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
+ status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name,
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return status;
-}
-
-static NTSTATUS ntstatus_keeperror(NTSTATUS s1, NTSTATUS s2)
-{
- if (!NT_STATUS_IS_OK(s1)) {
- return s1;
- }
- return s2;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -578,7 +526,10 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
enum file_close_type close_type)
{
NTSTATUS status = NT_STATUS_OK;
- NTSTATUS tmp;
+ NTSTATUS saved_status1 = NT_STATUS_OK;
+ NTSTATUS saved_status2 = NT_STATUS_OK;
+ NTSTATUS saved_status3 = NT_STATUS_OK;
+ NTSTATUS saved_status4 = NT_STATUS_OK;
connection_struct *conn = fsp->conn;
if (fsp->aio_write_behind) {
@@ -588,8 +539,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
*/
int ret = wait_for_aio_completion(fsp);
if (ret) {
- status = ntstatus_keeperror(
- status, map_nt_error_from_unix(ret));
+ saved_status1 = map_nt_error_from_unix(ret);
}
} else {
cancel_aio_by_fsp(fsp);
@@ -600,8 +550,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
* error here, we must remember this.
*/
- tmp = close_filestruct(fsp);
- status = ntstatus_keeperror(status, tmp);
+ saved_status2 = close_filestruct(fsp);
if (fsp->print_file) {
print_fsp_end(fsp, close_type);
@@ -620,301 +569,51 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp,
if (fsp->fh->ref_count == 1) {
/* Should we return on error here... ? */
- tmp = close_remove_share_mode(fsp, close_type);
- status = ntstatus_keeperror(status, tmp);
+ saved_status3 = close_remove_share_mode(fsp, close_type);
}
locking_close_file(smbd_messaging_context(), fsp);
- tmp = fd_close(fsp);
- status = ntstatus_keeperror(status, tmp);
+ status = fd_close(fsp);
/* check for magic scripts */
if (close_type == NORMAL_CLOSE) {
- tmp = check_magic(fsp);
- status = ntstatus_keeperror(status, tmp);
+ check_magic(fsp);
}
/*
* Ensure pending modtime is set after close.
*/
- tmp = update_write_time_on_close(fsp);
- if (NT_STATUS_EQUAL(tmp, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ saved_status4 = update_write_time_on_close(fsp);
+ if (NT_STATUS_EQUAL(saved_status4, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
/* Someone renamed the file or a parent directory containing
* this file. We can't do anything about this, we don't have
* an "update timestamp by fd" call in POSIX. Eat the error. */
- tmp = NT_STATUS_OK;
+ saved_status4 = NT_STATUS_OK;
}
- status = ntstatus_keeperror(status, tmp);
+ if (NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(saved_status1)) {
+ status = saved_status1;
+ } else if (!NT_STATUS_IS_OK(saved_status2)) {
+ status = saved_status2;
+ } else if (!NT_STATUS_IS_OK(saved_status3)) {
+ status = saved_status3;
+ } else if (!NT_STATUS_IS_OK(saved_status4)) {
+ status = saved_status4;
+ }
+ }
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
- conn->server_info->unix_name, fsp_str_dbg(fsp),
+ conn->server_info->unix_name,fsp->fsp_name,
conn->num_files_open - 1,
nt_errstr(status) ));
file_free(req, fsp);
return status;
}
-/****************************************************************************
- Static function used by reply_rmdir to delete an entire directory
- tree recursively. Return True on ok, False on fail.
-****************************************************************************/
-
-static bool recursive_rmdir(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct smb_filename *smb_dname)
-{
- const char *dname = NULL;
- char *talloced = NULL;
- bool ret = True;
- long offset = 0;
- SMB_STRUCT_STAT st;
- struct smb_Dir *dir_hnd;
-
- SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
-
- dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
- if(dir_hnd == NULL)
- return False;
-
- while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
- struct smb_filename *smb_dname_full = NULL;
- char *fullname = NULL;
- bool do_break = true;
- NTSTATUS status;
-
- if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(talloced);
- continue;
- }
-
- if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
- false)) {
- TALLOC_FREE(talloced);
- continue;
- }
-
- /* Construct the full name. */
- fullname = talloc_asprintf(ctx,
- "%s/%s",
- smb_dname->base_name,
- dname);
- if (!fullname) {
- errno = ENOMEM;
- goto err_break;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(), fullname,
- NULL, NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
- goto err_break;
- }
-
- if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
- if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
- goto err_break;
- }
- if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
- goto err_break;
- }
- } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- /* Successful iteration. */
- do_break = false;
-
- err_break:
- TALLOC_FREE(smb_dname_full);
- TALLOC_FREE(fullname);
- TALLOC_FREE(talloced);
- if (do_break) {
- ret = false;
- break;
- }
- }
- TALLOC_FREE(dir_hnd);
- return ret;
-}
-
-/****************************************************************************
- The internals of the rmdir code - called elsewhere.
-****************************************************************************/
-
-static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
-{
- connection_struct *conn = fsp->conn;
- struct smb_filename *smb_dname = fsp->fsp_name;
- int ret;
-
- SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
-
- /* Might be a symlink. */
- if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
- return map_nt_error_from_unix(errno);
- }
-
- if (S_ISLNK(smb_dname->st.st_ex_mode)) {
- /* Is what it points to a directory ? */
- if(SMB_VFS_STAT(conn, smb_dname) != 0) {
- return map_nt_error_from_unix(errno);
- }
- if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
- return NT_STATUS_NOT_A_DIRECTORY;
- }
- ret = SMB_VFS_UNLINK(conn, smb_dname);
- } else {
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
- }
- if (ret == 0) {
- notify_fname(conn, NOTIFY_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
- return NT_STATUS_OK;
- }
-
- if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
- /*
- * Check to see if the only thing in this directory are
- * vetoed files/directories. If so then delete them and
- * retry. If we fail to delete any of them (and we *don't*
- * do a recursive delete) then fail the rmdir.
- */
- SMB_STRUCT_STAT st;
- const char *dname = NULL;
- char *talloced = NULL;
- long dirpos = 0;
- struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
- smb_dname->base_name, NULL,
- 0);
-
- if(dir_hnd == NULL) {
- errno = ENOTEMPTY;
- goto err;
- }
-
- while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
- &talloced)) != NULL) {
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
- TALLOC_FREE(talloced);
- continue;
- }
- if (!is_visible_file(conn, smb_dname->base_name, dname,
- &st, false)) {
- TALLOC_FREE(talloced);
- continue;
- }
- if(!IS_VETO_PATH(conn, dname)) {
- TALLOC_FREE(dir_hnd);
- TALLOC_FREE(talloced);
- errno = ENOTEMPTY;
- goto err;
- }
- TALLOC_FREE(talloced);
- }
-
- /* We only have veto files/directories.
- * Are we allowed to delete them ? */
-
- if(!lp_recursive_veto_delete(SNUM(conn))) {
- TALLOC_FREE(dir_hnd);
- errno = ENOTEMPTY;
- goto err;
- }
-
- /* Do a recursive delete. */
- RewindDir(dir_hnd,&dirpos);
- while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
- &talloced)) != NULL) {
- struct smb_filename *smb_dname_full = NULL;
- char *fullname = NULL;
- bool do_break = true;
- NTSTATUS status;
-
- if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(talloced);
- continue;
- }
- if (!is_visible_file(conn, smb_dname->base_name, dname,
- &st, false)) {
- TALLOC_FREE(talloced);
- continue;
- }
-
- fullname = talloc_asprintf(ctx,
- "%s/%s",
- smb_dname->base_name,
- dname);
-
- if(!fullname) {
- errno = ENOMEM;
- goto err_break;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(),
- fullname, NULL,
- NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto err_break;
- }
-
- if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
- goto err_break;
- }
- if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
- if(!recursive_rmdir(ctx, conn,
- smb_dname_full)) {
- goto err_break;
- }
- if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
- goto err_break;
- }
- } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- /* Successful iteration. */
- do_break = false;
-
- err_break:
- TALLOC_FREE(fullname);
- TALLOC_FREE(smb_dname_full);
- TALLOC_FREE(talloced);
- if (do_break)
- break;
- }
- TALLOC_FREE(dir_hnd);
- /* Retry the rmdir */
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
- }
-
- err:
-
- if (ret != 0) {
- DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
- "%s\n", smb_fname_str_dbg(smb_dname),
- strerror(errno)));
- return map_nt_error_from_unix(errno);
- }
-
- notify_fname(conn, NOTIFY_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
-
- return NT_STATUS_OK;
-}
/****************************************************************************
Close a directory opened by an NT SMB call.
@@ -923,10 +622,9 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
enum file_close_type close_type)
{
- struct share_mode_lock *lck = NULL;
+ struct share_mode_lock *lck = 0;
bool delete_dir = False;
NTSTATUS status = NT_STATUS_OK;
- NTSTATUS status1 = NT_STATUS_OK;
/*
* NT can set delete_on_close of the last open
@@ -937,15 +635,12 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
NULL);
if (lck == NULL) {
- DEBUG(0, ("close_directory: Could not get share mode lock for "
- "%s\n", fsp_str_dbg(fsp)));
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
+ DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
+ return NT_STATUS_INVALID_PARAMETER;
}
if (!del_share_mode(lck, fsp)) {
- DEBUG(0, ("close_directory: Could not delete share entry for "
- "%s\n", fsp_str_dbg(fsp)));
+ DEBUG(0, ("close_directory: Could not delete share entry for %s\n", fsp->fsp_name));
}
if (fsp->initial_delete_on_close) {
@@ -959,9 +654,8 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
become_user(fsp->conn, fsp->vuid);
became_user = True;
}
- send_stat_cache_delete_message(fsp->fsp_name->base_name);
+ send_stat_cache_delete_message(fsp->fsp_name);
set_delete_on_close_lck(lck, True, &current_user.ut);
- fsp->delete_on_close = true;
if (became_user) {
unbecome_user();
}
@@ -1003,11 +697,12 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
TALLOC_FREE(lck);
- status = rmdir_internals(talloc_tos(), fsp);
+ status = rmdir_internals(talloc_tos(),
+ fsp->conn, fsp->fsp_name);
DEBUG(5,("close_directory: %s. Delete on close was set - "
"deleting directory returned %s.\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status)));
/* unbecome user. */
pop_sec_ctx();
@@ -1026,16 +721,11 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
fsp, NT_STATUS_OK);
}
- status1 = fd_close(fsp);
+ status = fd_close(fsp);
- if (!NT_STATUS_IS_OK(status1)) {
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n",
- fsp_str_dbg(fsp), fsp->fh->fd, errno,
- strerror(errno)));
- }
-
- if (fsp->dptr) {
- dptr_CloseDir(fsp->dptr);
+ fsp->fsp_name, fsp->fh->fd, errno, strerror(errno)));
}
/*
@@ -1043,12 +733,6 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp,
*/
close_filestruct(fsp);
file_free(req, fsp);
-
- out:
- TALLOC_FREE(lck);
- if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(status1)) {
- status = status1;
- }
return status;
}
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index 959fcd7754..a52f2d2e96 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -30,19 +30,17 @@
/****************************************************************************
init the conn structures
****************************************************************************/
-void conn_init(struct smbd_server_connection *sconn)
+void conn_init(void)
{
- sconn->smb1.tcons.Connections = NULL;
- sconn->smb1.tcons.num_open = 0;
- sconn->smb1.tcons.bmap = bitmap_allocate(BITMAP_BLOCK_SZ);
+ bmap = bitmap_allocate(BITMAP_BLOCK_SZ);
}
/****************************************************************************
return the number of open connections
****************************************************************************/
-int conn_num_open(struct smbd_server_connection *sconn)
+int conn_num_open(void)
{
- return sconn->smb1.tcons.num_open;
+ return num_open;
}
@@ -51,9 +49,8 @@ check if a snum is in use
****************************************************************************/
bool conn_snum_used(int snum)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
connection_struct *conn;
- for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next) {
+ for (conn=Connections;conn;conn=conn->next) {
if (conn->params->service == snum) {
return(True);
}
@@ -65,16 +62,15 @@ bool conn_snum_used(int snum)
Find a conn given a cnum.
****************************************************************************/
-connection_struct *conn_find(struct smbd_server_connection *sconn,unsigned cnum)
+connection_struct *conn_find(unsigned cnum)
{
int count=0;
connection_struct *conn;
- for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next,count++) {
+ for (conn=Connections;conn;conn=conn->next,count++) {
if (conn->cnum == cnum) {
if (count > 10) {
- DLIST_PROMOTE(sconn->smb1.tcons.Connections,
- conn);
+ DLIST_PROMOTE(Connections, conn);
}
return conn;
}
@@ -88,31 +84,19 @@ connection_struct *conn_find(struct smbd_server_connection *sconn,unsigned cnum)
The randomisation stops problems with the server dieing and clients
thinking the server is still available.
****************************************************************************/
-connection_struct *conn_new(struct smbd_server_connection *sconn)
+connection_struct *conn_new(void)
{
connection_struct *conn;
int i;
int find_offset = 1;
- if (sconn->allow_smb2) {
- if (!(conn=TALLOC_ZERO_P(NULL, connection_struct)) ||
- !(conn->params = TALLOC_P(conn, struct share_params))) {
- DEBUG(0,("TALLOC_ZERO() failed!\n"));
- TALLOC_FREE(conn);
- return NULL;
- }
- conn->sconn = sconn;
- return conn;
- }
-
find_again:
- i = bitmap_find(sconn->smb1.tcons.bmap, find_offset);
+ i = bitmap_find(bmap, find_offset);
if (i == -1) {
/* Expand the connections bitmap. */
- int oldsz = sconn->smb1.tcons.bmap->n;
- int newsz = sconn->smb1.tcons.bmap->n +
- BITMAP_BLOCK_SZ;
+ int oldsz = bmap->n;
+ int newsz = bmap->n + BITMAP_BLOCK_SZ;
struct bitmap * nbmap;
if (newsz <= oldsz) {
@@ -130,10 +114,10 @@ find_again:
return NULL;
}
- bitmap_copy(nbmap, sconn->smb1.tcons.bmap);
- bitmap_free(sconn->smb1.tcons.bmap);
+ bitmap_copy(nbmap, bmap);
+ bitmap_free(bmap);
- sconn->smb1.tcons.bmap = nbmap;
+ bmap = nbmap;
find_offset = oldsz; /* Start next search in the new portion. */
goto find_again;
@@ -155,18 +139,18 @@ find_again:
TALLOC_FREE(conn);
return NULL;
}
- conn->sconn = sconn;
conn->cnum = i;
conn->force_group_gid = (gid_t)-1;
- bitmap_set(sconn->smb1.tcons.bmap, i);
+ bitmap_set(bmap, i);
- sconn->smb1.tcons.num_open++;
+ num_open++;
+ string_set(&conn->dirpath,"");
string_set(&conn->connectpath,"");
string_set(&conn->origpath,"");
- DLIST_ADD(sconn->smb1.tcons.Connections, conn);
+ DLIST_ADD(Connections, conn);
return conn;
}
@@ -175,11 +159,11 @@ find_again:
Close all conn structures.
return true if any were closed
****************************************************************************/
-bool conn_close_all(struct smbd_server_connection *sconn)
+bool conn_close_all(void)
{
connection_struct *conn, *next;
bool ret = false;
- for (conn=sconn->smb1.tcons.Connections;conn;conn=next) {
+ for (conn=Connections;conn;conn=next) {
next=conn->next;
set_current_service(conn, 0, True);
close_cnum(conn, conn->vuid);
@@ -192,7 +176,7 @@ bool conn_close_all(struct smbd_server_connection *sconn)
Idle inactive connections.
****************************************************************************/
-bool conn_idle_all(struct smbd_server_connection *sconn,time_t t)
+bool conn_idle_all(time_t t)
{
int deadtime = lp_deadtime()*60;
pipes_struct *plist = NULL;
@@ -201,7 +185,7 @@ bool conn_idle_all(struct smbd_server_connection *sconn,time_t t)
if (deadtime <= 0)
deadtime = DEFAULT_SMBD_TIMEOUT;
- for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next) {
+ for (conn=Connections;conn;conn=conn->next) {
time_t age = t - conn->lastused;
@@ -228,7 +212,7 @@ bool conn_idle_all(struct smbd_server_connection *sconn,time_t t)
for (plist = get_first_internal_pipe(); plist;
plist = get_next_internal_pipe(plist)) {
- if (num_pipe_handles(plist->pipe_handles) != 0) {
+ if (plist->pipe_handles && plist->pipe_handles->count) {
return False;
}
}
@@ -240,11 +224,11 @@ bool conn_idle_all(struct smbd_server_connection *sconn,time_t t)
Clear a vuid out of the validity cache, and as the 'owner' of a connection.
****************************************************************************/
-void conn_clear_vuid_caches(struct smbd_server_connection *sconn,uint16_t vuid)
+void conn_clear_vuid_caches(uint16_t vuid)
{
connection_struct *conn;
- for (conn=sconn->smb1.tcons.Connections;conn;conn=conn->next) {
+ for (conn=Connections;conn;conn=conn->next) {
if (conn->vuid == vuid) {
conn->vuid = UID_FIELD_INVALID;
}
@@ -256,9 +240,9 @@ void conn_clear_vuid_caches(struct smbd_server_connection *sconn,uint16_t vuid)
Free a conn structure - internal part.
****************************************************************************/
-static void conn_free_internal(connection_struct *conn)
+void conn_free_internal(connection_struct *conn)
{
- vfs_handle_struct *handle = NULL, *thandle = NULL;
+ vfs_handle_struct *handle = NULL, *thandle = NULL;
struct trans_state *state = NULL;
/* Free vfs_connection_struct */
@@ -283,6 +267,7 @@ static void conn_free_internal(connection_struct *conn)
free_namearray(conn->veto_oplock_list);
free_namearray(conn->aio_write_behind_list);
+ string_free(&conn->dirpath);
string_free(&conn->connectpath);
string_free(&conn->origpath);
@@ -296,22 +281,12 @@ static void conn_free_internal(connection_struct *conn)
void conn_free(connection_struct *conn)
{
- if (conn->sconn == NULL) {
- conn_free_internal(conn);
- return;
- }
-
- if (conn->sconn->allow_smb2) {
- conn_free_internal(conn);
- return;
- }
-
- DLIST_REMOVE(conn->sconn->smb1.tcons.Connections, conn);
+ DLIST_REMOVE(Connections, conn);
- bitmap_clear(conn->sconn->smb1.tcons.bmap, conn->cnum);
+ bitmap_clear(bmap, conn->cnum);
- SMB_ASSERT(conn->sconn->smb1.tcons.num_open > 0);
- conn->sconn->smb1.tcons.num_open--;
+ SMB_ASSERT(num_open > 0);
+ num_open--;
conn_free_internal(conn);
}
@@ -328,7 +303,6 @@ void msg_force_tdis(struct messaging_context *msg,
struct server_id server_id,
DATA_BLOB *data)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
connection_struct *conn, *next;
fstring sharename;
@@ -336,11 +310,11 @@ void msg_force_tdis(struct messaging_context *msg,
if (strcmp(sharename, "*") == 0) {
DEBUG(1,("Forcing close of all shares\n"));
- conn_close_all(sconn);
+ conn_close_all();
return;
}
- for (conn=sconn->smb1.tcons.Connections;conn;conn=next) {
+ for (conn=Connections;conn;conn=next) {
next=conn->next;
if (strequal(lp_servicename(SNUM(conn)), sharename)) {
DEBUG(1,("Forcing close of share %s cnum=%d\n",
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 5ce4a7b099..ab4a0d27e3 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -115,19 +115,15 @@ bool make_dir_struct(TALLOC_CTX *ctx,
Initialise the dir bitmap.
****************************************************************************/
-bool init_dptrs(struct smbd_server_connection *sconn)
+void init_dptrs(void)
{
- if (sconn->smb1.searches.dptr_bmap) {
- return true;
- }
-
- sconn->smb1.searches.dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
+ if (dptr_bmap)
+ return;
- if (sconn->smb1.searches.dptr_bmap == NULL) {
- return false;
- }
+ dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
- return true;
+ if (!dptr_bmap)
+ exit_server("out of memory in init_dptrs");
}
/****************************************************************************
@@ -146,14 +142,14 @@ static void dptr_idle(struct dptr_struct *dptr)
Idle the oldest dptr.
****************************************************************************/
-static void dptr_idleoldest(struct smbd_server_connection *sconn)
+static void dptr_idleoldest(void)
{
struct dptr_struct *dptr;
/*
* Go to the end of the list.
*/
- for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
+ for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
;
if(!dptr) {
@@ -177,16 +173,15 @@ static void dptr_idleoldest(struct smbd_server_connection *sconn)
Get the struct dptr_struct for a dir index.
****************************************************************************/
-static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
- int key, bool forclose)
+static struct dptr_struct *dptr_get(int key, bool forclose)
{
struct dptr_struct *dptr;
- for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) {
+ for(dptr = dirptrs; dptr; dptr = dptr->next) {
if(dptr->dnum == key) {
if (!forclose && !dptr->dir_hnd) {
- if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
- dptr_idleoldest(sconn);
+ if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
+ dptr_idleoldest();
DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
if (!(dptr->dir_hnd = OpenDir(
NULL, dptr->conn, dptr->path,
@@ -196,7 +191,7 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
return False;
}
}
- DLIST_PROMOTE(sconn->smb1.searches.dirptrs,dptr);
+ DLIST_PROMOTE(dirptrs,dptr);
return dptr;
}
}
@@ -207,9 +202,9 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
Get the dir path for a dir index.
****************************************************************************/
-char *dptr_path(struct smbd_server_connection *sconn, int key)
+char *dptr_path(int key)
{
- struct dptr_struct *dptr = dptr_get(sconn, key, false);
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->path);
return(NULL);
@@ -219,9 +214,9 @@ char *dptr_path(struct smbd_server_connection *sconn, int key)
Get the dir wcard for a dir index.
****************************************************************************/
-char *dptr_wcard(struct smbd_server_connection *sconn, int key)
+char *dptr_wcard(int key)
{
- struct dptr_struct *dptr = dptr_get(sconn, key, false);
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->wcard);
return(NULL);
@@ -231,9 +226,9 @@ char *dptr_wcard(struct smbd_server_connection *sconn, int key)
Get the dir attrib for a dir index.
****************************************************************************/
-uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
+uint16 dptr_attr(int key)
{
- struct dptr_struct *dptr = dptr_get(sconn, key, false);
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->attr);
return(0);
@@ -245,29 +240,22 @@ uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
static void dptr_close_internal(struct dptr_struct *dptr)
{
- struct smbd_server_connection *sconn = dptr->conn->sconn;
-
DEBUG(4,("closing dptr key %d\n",dptr->dnum));
- if (sconn == NULL) {
- goto done;
- }
-
- DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr);
+ DLIST_REMOVE(dirptrs, dptr);
/*
* Free the dnum in the bitmap. Remember the dnum value is always
* biased by one with respect to the bitmap.
*/
- if(bitmap_query(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1) != true) {
+ if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
dptr->dnum ));
}
- bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1);
+ bitmap_clear(dptr_bmap, dptr->dnum - 1);
-done:
TALLOC_FREE(dptr->dir_hnd);
/* Lanman 2 specific code */
@@ -280,7 +268,7 @@ done:
Close a dptr given a key.
****************************************************************************/
-void dptr_close(struct smbd_server_connection *sconn, int *key)
+void dptr_close(int *key)
{
struct dptr_struct *dptr;
@@ -290,7 +278,7 @@ void dptr_close(struct smbd_server_connection *sconn, int *key)
/* OS/2 seems to use -1 to indicate "close all directories" */
if (*key == -1) {
struct dptr_struct *next;
- for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) {
+ for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
dptr_close_internal(dptr);
}
@@ -298,7 +286,7 @@ void dptr_close(struct smbd_server_connection *sconn, int *key)
return;
}
- dptr = dptr_get(sconn, *key, true);
+ dptr = dptr_get(*key, True);
if (!dptr) {
DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
@@ -317,17 +305,10 @@ void dptr_close(struct smbd_server_connection *sconn, int *key)
void dptr_closecnum(connection_struct *conn)
{
struct dptr_struct *dptr, *next;
- struct smbd_server_connection *sconn = conn->sconn;
-
- if (sconn == NULL) {
- return;
- }
-
- for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) {
+ for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
- if (dptr->conn == conn) {
+ if (dptr->conn == conn)
dptr_close_internal(dptr);
- }
}
}
@@ -338,16 +319,9 @@ void dptr_closecnum(connection_struct *conn)
void dptr_idlecnum(connection_struct *conn)
{
struct dptr_struct *dptr;
- struct smbd_server_connection *sconn = conn->sconn;
-
- if (sconn == NULL) {
- return;
- }
-
- for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = dptr->next) {
- if (dptr->conn == conn && dptr->dir_hnd) {
+ for(dptr = dirptrs; dptr; dptr = dptr->next) {
+ if (dptr->conn == conn && dptr->dir_hnd)
dptr_idle(dptr);
- }
}
}
@@ -355,11 +329,10 @@ void dptr_idlecnum(connection_struct *conn)
Close a dptr that matches a given path, only if it matches the spid also.
****************************************************************************/
-void dptr_closepath(struct smbd_server_connection *sconn,
- char *path,uint16 spid)
+void dptr_closepath(char *path,uint16 spid)
{
struct dptr_struct *dptr, *next;
- for(dptr = sconn->smb1.searches.dirptrs; dptr; dptr = next) {
+ for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
if (spid == dptr->spid && strequal(dptr->path,path))
dptr_close_internal(dptr);
@@ -372,15 +345,14 @@ void dptr_closepath(struct smbd_server_connection *sconn,
finished with that one.
****************************************************************************/
-static void dptr_close_oldest(struct smbd_server_connection *sconn,
- bool old)
+static void dptr_close_oldest(bool old)
{
struct dptr_struct *dptr;
/*
* Go to the end of the list.
*/
- for(dptr = sconn->smb1.searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
+ for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
;
if(!dptr) {
@@ -415,18 +387,12 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn,
NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid,
const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
{
- struct smbd_server_connection *sconn = conn->sconn;
struct dptr_struct *dptr = NULL;
struct smb_Dir *dir_hnd;
NTSTATUS status;
DEBUG(5,("dptr_create dir=%s\n", path));
- if (sconn == NULL) {
- DEBUG(0,("dptr_create: called with fake connection_struct\n"));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
if (!wcard) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -441,8 +407,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
return map_nt_error_from_unix(errno);
}
- if (sconn->smb1.searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
- dptr_idleoldest(sconn);
+ string_set(&conn->dirpath,path);
+
+ if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
+ dptr_idleoldest();
}
dptr = SMB_MALLOC_P(struct dptr_struct);
@@ -461,7 +429,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
* value we return will fit in the range 1-255.
*/
- dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0);
+ dptr->dnum = bitmap_find(dptr_bmap, 0);
if(dptr->dnum == -1 || dptr->dnum > 254) {
@@ -471,10 +439,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
* finished with that one.
*/
- dptr_close_oldest(sconn, true);
+ dptr_close_oldest(True);
/* Now try again... */
- dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 0);
+ dptr->dnum = bitmap_find(dptr_bmap, 0);
if(dptr->dnum == -1 || dptr->dnum > 254) {
DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
@@ -489,7 +457,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
* a range that will return 256 - MAX_DIRECTORY_HANDLES.
*/
- dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255);
+ dptr->dnum = bitmap_find(dptr_bmap, 255);
if(dptr->dnum == -1 || dptr->dnum < 255) {
@@ -500,10 +468,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
* directory handles.
*/
- dptr_close_oldest(sconn, false);
+ dptr_close_oldest(False);
/* Now try again... */
- dptr->dnum = bitmap_find(sconn->smb1.searches.dptr_bmap, 255);
+ dptr->dnum = bitmap_find(dptr_bmap, 255);
if(dptr->dnum == -1 || dptr->dnum < 255) {
DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
@@ -514,7 +482,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
}
}
- bitmap_set(sconn->smb1.searches.dptr_bmap, dptr->dnum);
+ bitmap_set(dptr_bmap, dptr->dnum);
dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
@@ -525,7 +493,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
dptr->expect_close = expect_close;
dptr->wcard = SMB_STRDUP(wcard);
if (!dptr->wcard) {
- bitmap_clear(sconn->smb1.searches.dptr_bmap, dptr->dnum - 1);
+ bitmap_clear(dptr_bmap, dptr->dnum - 1);
SAFE_FREE(dptr);
TALLOC_FREE(dir_hnd);
return NT_STATUS_NO_MEMORY;
@@ -538,7 +506,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
dptr->attr = attr;
- DLIST_ADD(sconn->smb1.searches.dirptrs, dptr);
+ DLIST_ADD(dirptrs, dptr);
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
dptr->dnum,path,expect_close));
@@ -555,8 +523,7 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
int dptr_CloseDir(struct dptr_struct *dptr)
{
- struct smbd_server_connection *sconn = dptr->conn->sconn;
- DLIST_REMOVE(sconn->smb1.searches.dirptrs, dptr);
+ DLIST_REMOVE(dirptrs, dptr);
TALLOC_FREE(dptr->dir_hnd);
return 0;
}
@@ -586,20 +553,14 @@ int dptr_dnum(struct dptr_struct *dptr)
****************************************************************************/
static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
- long *poffset, SMB_STRUCT_STAT *pst,
- char **ptalloced)
+ long *poffset, SMB_STRUCT_STAT *pst)
{
/* Normal search for the next file. */
const char *name;
- char *talloced = NULL;
-
- while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
- != NULL) {
+ while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) {
if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
- *ptalloced = talloced;
return name;
}
- TALLOC_FREE(talloced);
}
return NULL;
}
@@ -613,26 +574,18 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
long *poffset,
SMB_STRUCT_STAT *pst)
{
- struct smb_filename smb_fname_base;
char *name = NULL;
- const char *name_temp = NULL;
- char *talloced = NULL;
char *pathreal = NULL;
char *found_name = NULL;
int ret;
+ const char *name_temp = NULL;
SET_STAT_INVALID(*pst);
if (dptr->has_wild || dptr->did_stat) {
- name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
- &talloced);
- if (name_temp == NULL) {
- return NULL;
- }
- if (talloced != NULL) {
- return talloc_move(ctx, &talloced);
- }
- return talloc_strdup(ctx, name_temp);
+ name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
+ name = talloc_strdup(ctx, name_temp);
+ return name;
}
/* If poffset is -1 then we know we returned this name before and we
@@ -671,12 +624,7 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
if (!pathreal)
return NULL;
- /* Create an smb_filename with stream_name == NULL. */
- ZERO_STRUCT(smb_fname_base);
- smb_fname_base.base_name = pathreal;
-
- if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
- *pst = smb_fname_base.st;
+ if (SMB_VFS_STAT(dptr->conn, pathreal, pst) == 0) {
name = talloc_strdup(ctx, dptr->wcard);
goto clean;
} else {
@@ -714,14 +662,9 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx,
TALLOC_FREE(pathreal);
- name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
- if (name_temp == NULL) {
- return NULL;
- }
- if (talloced != NULL) {
- return talloc_move(ctx, &talloced);
- }
- return talloc_strdup(ctx, name_temp);
+ name_temp = dptr_normal_ReadDirName(dptr, poffset, pst);
+ name = talloc_strdup(ctx, name_temp);
+ return name;
clean:
TALLOC_FREE(pathreal);
@@ -771,11 +714,10 @@ void dptr_init_search_op(struct dptr_struct *dptr)
Fill the 5 byte server reserved dptr field.
****************************************************************************/
-bool dptr_fill(struct smbd_server_connection *sconn,
- char *buf1,unsigned int key)
+bool dptr_fill(char *buf1,unsigned int key)
{
unsigned char *buf = (unsigned char *)buf1;
- struct dptr_struct *dptr = dptr_get(sconn, key, false);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
if (!dptr) {
DEBUG(1,("filling null dirptr %d\n",key));
@@ -793,11 +735,10 @@ bool dptr_fill(struct smbd_server_connection *sconn,
Fetch the dir ptr and seek it given the 5 byte server field.
****************************************************************************/
-struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
- char *buf, int *num)
+struct dptr_struct *dptr_fetch(char *buf,int *num)
{
unsigned int key = *(unsigned char *)buf;
- struct dptr_struct *dptr = dptr_get(sconn, key, false);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
long seekoff;
@@ -814,7 +755,7 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
}
SeekDir(dptr->dir_hnd,seekoff);
DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
- key, dptr->path, (int)seekoff));
+ key,dptr_path(key),(int)seekoff));
return(dptr);
}
@@ -822,16 +763,15 @@ struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
Fetch the dir ptr.
****************************************************************************/
-struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
- int dptr_num)
+struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
{
- struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false);
+ struct dptr_struct *dptr = dptr_get(dptr_num, False);
if (!dptr) {
DEBUG(3,("fetched null dirptr %d\n",dptr_num));
return(NULL);
}
- DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
+ DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
return(dptr);
}
@@ -873,249 +813,138 @@ static bool mangle_mask_match(connection_struct *conn,
return mask_match_search(mname,mask,False);
}
-bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
- struct dptr_struct *dirptr,
- const char *mask,
- uint32_t dirtype,
- bool dont_descend,
- bool ask_sharemode,
- bool (*match_fn)(TALLOC_CTX *ctx,
- void *private_data,
- const char *dname,
- const char *mask,
- char **_fname),
- bool (*mode_fn)(TALLOC_CTX *ctx,
- void *private_data,
- struct smb_filename *smb_fname,
- uint32_t *_mode),
- void *private_data,
- char **_fname,
- struct smb_filename **_smb_fname,
- uint32_t *_mode,
- long *_prev_offset)
+/****************************************************************************
+ Get an 8.3 directory entry.
+****************************************************************************/
+
+bool get_dir_entry(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ const char *mask,
+ uint32 dirtype,
+ char **pp_fname_out,
+ SMB_OFF_T *size,
+ uint32 *mode,
+ time_t *date,
+ bool check_descend,
+ bool ask_sharemode)
{
- connection_struct *conn = dirptr->conn;
+ char *dname = NULL;
+ bool found = False;
+ SMB_STRUCT_STAT sbuf;
+ char *pathreal = NULL;
+ char *filename = NULL;
bool needslash;
- *_smb_fname = NULL;
- *_mode = 0;
+ *pp_fname_out = NULL;
- needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
+ needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
- while (true) {
- long cur_offset;
- long prev_offset;
- SMB_STRUCT_STAT sbuf;
- char *dname = NULL;
- bool isdots;
- char *fname = NULL;
- char *pathreal = NULL;
- struct smb_filename smb_fname;
- uint32_t mode = 0;
- bool ok;
- NTSTATUS status;
+ if (!conn->dirptr) {
+ return(False);
+ }
- cur_offset = dptr_TellDir(dirptr);
- prev_offset = cur_offset;
- dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
+ while (!found) {
+ long curoff = dptr_TellDir(conn->dirptr);
+ dname = dptr_ReadDirName(ctx, conn->dirptr, &curoff, &sbuf);
- DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
- (long)dirptr, cur_offset));
+ DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
+ (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
if (dname == NULL) {
- return false;
- }
-
- isdots = (ISDOT(dname) || ISDOTDOT(dname));
- if (dont_descend && !isdots) {
- TALLOC_FREE(dname);
- continue;
- }
-
- /*
- * fname may get mangled, dname is never mangled.
- * Whenever we're accessing the filesystem we use
- * pathreal which is composed from dname.
- */
-
- ok = match_fn(ctx, private_data, dname, mask, &fname);
- if (!ok) {
- TALLOC_FREE(dname);
- continue;
- }
-
- pathreal = talloc_asprintf(ctx, "%s%s%s",
- dirptr->path,
- needslash?"/":"",
- dname);
- if (!pathreal) {
- TALLOC_FREE(dname);
- TALLOC_FREE(fname);
- return false;
- }
-
- /* Create smb_fname with NULL stream_name. */
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = pathreal;
- smb_fname.st = sbuf;
-
- ok = mode_fn(ctx, private_data, &smb_fname, &mode);
- if (!ok) {
- TALLOC_FREE(dname);
- TALLOC_FREE(fname);
- TALLOC_FREE(pathreal);
- continue;
+ return(False);
}
- if (!dir_check_ftype(conn, mode, dirtype)) {
- DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
- fname, (unsigned int)mode, (unsigned int)dirtype));
- TALLOC_FREE(dname);
- TALLOC_FREE(fname);
- TALLOC_FREE(pathreal);
- continue;
- }
-
- if (ask_sharemode) {
- struct timespec write_time_ts;
- struct file_id fileid;
-
- fileid = vfs_file_id_from_sbuf(conn,
- &smb_fname.st);
- get_file_infos(fileid, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&smb_fname.st,
- write_time_ts);
+ filename = dname;
+
+ /* notice the special *.* handling. This appears to be the only difference
+ between the wildcard handling in this routine and in the trans2 routines.
+ see masktest for a demo
+ */
+ if ((strcmp(mask,"*.*") == 0) ||
+ mask_match_search(filename,mask,False) ||
+ mangle_mask_match(conn,filename,mask)) {
+ char mname[13];
+
+ if (!mangle_is_8_3(filename, False, conn->params)) {
+ if (!name_to_8_3(filename,mname,False,
+ conn->params)) {
+ TALLOC_FREE(filename);
+ continue;
+ }
+ filename = talloc_strdup(ctx, mname);
+ if (!filename) {
+ return False;
+ }
}
- }
- DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
- "fname=%s (%s)\n",
- mask, smb_fname_str_dbg(&smb_fname),
- dname, fname));
+ if (needslash) {
+ pathreal = talloc_asprintf(ctx,
+ "%s/%s",
+ conn->dirpath,
+ dname);
+ } else {
+ pathreal = talloc_asprintf(ctx,
+ "%s%s",
+ conn->dirpath,
+ dname);
+ }
+ if (!pathreal) {
+ TALLOC_FREE(filename);
+ return False;
+ }
- DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
+ DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",
+ pathreal, strerror(errno) ));
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(filename);
+ continue;
+ }
- TALLOC_FREE(dname);
+ *mode = dos_mode(conn,pathreal,&sbuf);
- status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
- TALLOC_FREE(pathreal);
- if (!NT_STATUS_IS_OK(status)) {
- return false;
- }
- *_fname = fname;
- *_mode = mode;
- *_prev_offset = prev_offset;
+ if (!dir_check_ftype(conn,*mode,dirtype)) {
+ DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(filename);
+ continue;
+ }
- return true;
- }
+ *size = sbuf.st_size;
+ *date = sbuf.st_mtime;
- return false;
-}
-
-/****************************************************************************
- Get an 8.3 directory entry.
-****************************************************************************/
+ if (ask_sharemode) {
+ struct timespec write_time_ts;
+ struct file_id fileid;
-static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
- void *private_data,
- const char *dname,
- const char *mask,
- char **_fname)
-{
- connection_struct *conn = (connection_struct *)private_data;
-
- if ((strcmp(mask,"*.*") == 0) ||
- mask_match_search(dname, mask, false) ||
- mangle_mask_match(conn, dname, mask)) {
- char mname[13];
- const char *fname;
-
- if (!mangle_is_8_3(dname, false, conn->params)) {
- bool ok = name_to_8_3(dname, mname, false,
- conn->params);
- if (!ok) {
- return false;
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ get_file_infos(fileid, NULL, &write_time_ts);
+ if (!null_timespec(write_time_ts)) {
+ *date = convert_timespec_to_time_t(write_time_ts);
+ }
}
- fname = mname;
- } else {
- fname = dname;
- }
- *_fname = talloc_strdup(ctx, fname);
- if (*_fname == NULL) {
- return false;
- }
+ DEBUG(3,("get_dir_entry mask=[%s] found %s "
+ "fname=%s (%s)\n",
+ mask,
+ pathreal,
+ dname,
+ filename));
- return true;
- }
+ found = True;
- return false;
-}
+ SMB_ASSERT(filename != NULL);
+ *pp_fname_out = filename;
-static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
- void *private_data,
- struct smb_filename *smb_fname,
- uint32_t *_mode)
-{
- connection_struct *conn = (connection_struct *)private_data;
-
- if (!VALID_STAT(smb_fname->st)) {
- if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
- DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
- "Couldn't stat [%s]. Error "
- "= %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- return false;
+ DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
+ TALLOC_FREE(pathreal);
}
- }
- *_mode = dos_mode(conn, smb_fname);
- return true;
-}
-
-bool get_dir_entry(TALLOC_CTX *ctx,
- struct dptr_struct *dirptr,
- const char *mask,
- uint32_t dirtype,
- char **_fname,
- SMB_OFF_T *_size,
- uint32_t *_mode,
- struct timespec *_date,
- bool check_descend,
- bool ask_sharemode)
-{
- connection_struct *conn = dirptr->conn;
- char *fname = NULL;
- struct smb_filename *smb_fname = NULL;
- uint32_t mode = 0;
- long prev_offset;
- bool ok;
-
- ok = smbd_dirptr_get_entry(ctx,
- dirptr,
- mask,
- dirtype,
- check_descend,
- ask_sharemode,
- smbd_dirptr_8_3_match_fn,
- smbd_dirptr_8_3_mode_fn,
- conn,
- &fname,
- &smb_fname,
- &mode,
- &prev_offset);
- if (!ok) {
- return false;
+ if (!found)
+ TALLOC_FREE(filename);
}
- *_fname = talloc_move(ctx, &fname);
- *_size = smb_fname->st.st_ex_size;
- *_mode = mode;
- *_date = smb_fname->st.st_ex_mtime;
- TALLOC_FREE(smb_fname);
- return true;
+ return(found);
}
/*******************************************************************
@@ -1124,8 +953,7 @@ bool get_dir_entry(TALLOC_CTX *ctx,
use it for anything security sensitive.
********************************************************************/
-static bool user_can_read_file(connection_struct *conn,
- struct smb_filename *smb_fname)
+static bool user_can_read_file(connection_struct *conn, char *name)
{
/*
* If user is a member of the Admin group
@@ -1136,7 +964,7 @@ static bool user_can_read_file(connection_struct *conn,
return True;
}
- return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
+ return can_access_file_acl(conn, name, FILE_READ_DATA);
}
/*******************************************************************
@@ -1146,8 +974,7 @@ static bool user_can_read_file(connection_struct *conn,
use it for anything security sensitive.
********************************************************************/
-static bool user_can_write_file(connection_struct *conn,
- const struct smb_filename *smb_fname)
+static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
{
/*
* If user is a member of the Admin group
@@ -1158,23 +985,22 @@ static bool user_can_write_file(connection_struct *conn,
return True;
}
- SMB_ASSERT(VALID_STAT(smb_fname->st));
+ SMB_ASSERT(VALID_STAT(*pst));
/* Pseudo-open the file */
- if(S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if(S_ISDIR(pst->st_mode)) {
return True;
}
- return can_write_to_file(conn, smb_fname);
+ return can_write_to_file(conn, name, pst);
}
/*******************************************************************
Is a file a "special" type ?
********************************************************************/
-static bool file_is_special(connection_struct *conn,
- const struct smb_filename *smb_fname)
+static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
{
/*
* If user is a member of the Admin group
@@ -1184,11 +1010,9 @@ static bool file_is_special(connection_struct *conn,
if (conn->admin_user)
return False;
- SMB_ASSERT(VALID_STAT(smb_fname->st));
+ SMB_ASSERT(VALID_STAT(*pst));
- if (S_ISREG(smb_fname->st.st_ex_mode) ||
- S_ISDIR(smb_fname->st.st_ex_mode) ||
- S_ISLNK(smb_fname->st.st_ex_mode))
+ if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
return False;
return True;
@@ -1205,10 +1029,6 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
bool hide_unreadable = lp_hideunreadable(SNUM(conn));
bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
bool hide_special = lp_hide_special_files(SNUM(conn));
- char *entry = NULL;
- struct smb_filename *smb_fname_base = NULL;
- NTSTATUS status;
- bool ret = false;
if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
return True; /* . and .. are always visible. */
@@ -1221,71 +1041,54 @@ bool is_visible_file(connection_struct *conn, const char *dir_path,
}
if (hide_unreadable || hide_unwriteable || hide_special) {
- entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
- if (!entry) {
- ret = false;
- goto out;
+ char *entry = NULL;
+
+ if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
+ return False;
}
/* If it's a dfs symlink, ignore _hide xxxx_ options */
if (lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
is_msdfs_link(conn, entry, NULL)) {
- ret = true;
- goto out;
- }
-
- /* Create an smb_filename with stream_name == NULL. */
- status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
- pst, &smb_fname_base);
- if (!NT_STATUS_IS_OK(status)) {
- ret = false;
- goto out;
+ SAFE_FREE(entry);
+ return True;
}
/* If the file name does not exist, there's no point checking
* the configuration options. We succeed, on the basis that the
* checks *might* have passed if the file was present.
*/
- if (!VALID_STAT(*pst)) {
- if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
- ret = true;
- goto out;
- } else {
- *pst = smb_fname_base->st;
- }
+ if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, entry, pst) != 0))
+ {
+ SAFE_FREE(entry);
+ return True;
}
/* Honour _hide unreadable_ option */
- if (hide_unreadable &&
- !user_can_read_file(conn, smb_fname_base)) {
+ if (hide_unreadable && !user_can_read_file(conn, entry)) {
DEBUG(10,("is_visible_file: file %s is unreadable.\n",
entry ));
- ret = false;
- goto out;
+ SAFE_FREE(entry);
+ return False;
}
/* Honour _hide unwriteable_ option */
- if (hide_unwriteable && !user_can_write_file(conn,
- smb_fname_base)) {
+ if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is unwritable.\n",
entry ));
- ret = false;
- goto out;
+ SAFE_FREE(entry);
+ return False;
}
/* Honour _hide_special_ option */
- if (hide_special && file_is_special(conn, smb_fname_base)) {
+ if (hide_special && file_is_special(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is special.\n",
entry ));
- ret = false;
- goto out;
+ SAFE_FREE(entry);
+ return False;
}
+ SAFE_FREE(entry);
}
-
- ret = true;
- out:
- TALLOC_FREE(smb_fname_base);
- TALLOC_FREE(entry);
- return ret;
+ return True;
}
static int smb_Dir_destructor(struct smb_Dir *dirp)
@@ -1293,9 +1096,7 @@ static int smb_Dir_destructor(struct smb_Dir *dirp)
if (dirp->dir) {
SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
}
- if (dirp->conn->sconn) {
- dirp->conn->sconn->smb1.searches.dirhandles_open--;
- }
+ dirhandles_open--;
return 0;
}
@@ -1307,7 +1108,6 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
const char *name, const char *mask, uint32 attr)
{
struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
- struct smbd_server_connection *sconn = conn->sconn;
if (!dirp) {
return NULL;
@@ -1322,9 +1122,7 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
goto fail;
}
- if (sconn) {
- sconn->smb1.searches.dirhandles_open++;
- }
+ dirhandles_open++;
talloc_set_destructor(dirp, smb_Dir_destructor);
dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
@@ -1348,10 +1146,9 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
********************************************************************/
const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
- SMB_STRUCT_STAT *sbuf, char **ptalloced)
+ SMB_STRUCT_STAT *sbuf)
{
const char *n;
- char *talloced = NULL;
connection_struct *conn = dirp->conn;
/* Cheat to allow . and .. to be the first entries returned. */
@@ -1362,11 +1159,10 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
n = ".";
*poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
} else {
- n = "..";
*poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
+ n = "..";
}
dirp->file_number++;
- *ptalloced = NULL;
return n;
} else if (*poffset == END_OF_DIRECTORY_OFFSET) {
*poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
@@ -1376,21 +1172,18 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
SeekDir(dirp, *poffset);
}
- while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
+ while ((n = vfs_readdirname(conn, dirp->dir, sbuf))) {
/* Ignore . and .. - we've already returned them. */
if (*n == '.') {
if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
- TALLOC_FREE(talloced);
continue;
}
}
*poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
- *ptalloced = talloced;
dirp->file_number++;
return n;
}
*poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
- *ptalloced = NULL;
return NULL;
}
@@ -1485,8 +1278,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
{
int i;
- const char *entry = NULL;
- char *talloced = NULL;
+ const char *entry;
connection_struct *conn = dirp->conn;
/* Search back in the name cache. */
@@ -1513,12 +1305,10 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
SMB_VFS_REWINDDIR(conn, dirp->dir);
dirp->file_number = 0;
*poffset = START_OF_DIRECTORY_OFFSET;
- while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
+ while ((entry = ReadDirName(dirp, poffset, NULL))) {
if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
- TALLOC_FREE(talloced);
return True;
}
- TALLOC_FREE(talloced);
}
return False;
}
@@ -1532,8 +1322,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
{
NTSTATUS status = NT_STATUS_OK;
long dirpos = 0;
- const char *dname = NULL;
- char *talloced = NULL;
+ const char *dname;
SMB_STRUCT_STAT st;
struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname,
NULL, 0);
@@ -1542,17 +1331,15 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
return map_nt_error_from_unix(errno);
}
- while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
+ while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
/* Quick check for "." and ".." */
if (dname[0] == '.') {
if (!dname[1] || (dname[1] == '.' && !dname[2])) {
- TALLOC_FREE(talloced);
continue;
}
}
if (!is_visible_file(conn, dirname, dname, &st, True)) {
- TALLOC_FREE(talloced);
continue;
}
@@ -1561,7 +1348,6 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
status = NT_STATUS_DIRECTORY_NOT_EMPTY;
break;
}
- TALLOC_FREE(talloced);
TALLOC_FREE(dir_hnd);
return status;
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index c061b21822..7b47fe6236 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -3,27 +3,28 @@
dos mode handling functions
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) James Peach 2006
-
+
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 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
-#include "librpc/gen_ndr/ndr_xattr.h"
+
+extern enum protocol_types Protocol;
static uint32_t filter_mode_by_protocol(uint32_t mode)
{
- if (get_Protocol() <= PROTOCOL_LANMAN2) {
+ if (Protocol <= PROTOCOL_LANMAN2) {
DEBUG(10,("filter_mode_by_protocol: "
"filtering result 0x%x to 0x%x\n",
(unsigned int)mode,
@@ -36,7 +37,7 @@ static uint32_t filter_mode_by_protocol(uint32_t mode)
static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
{
#if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
- if (sbuf->st_ex_size > sbuf->st_ex_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
+ if (sbuf->st_size > sbuf->st_blocks * (SMB_OFF_T)STAT_ST_BLOCKSIZE) {
return FILE_ATTRIBUTE_SPARSE;
}
#endif
@@ -77,8 +78,7 @@ static int set_link_read_only_flag(const SMB_STRUCT_STAT *const sbuf)
}
****************************************************************************/
-mode_t unix_mode(connection_struct *conn, int dosmode,
- const struct smb_filename *smb_fname,
+mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
const char *inherit_from_dir)
{
mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
@@ -89,39 +89,23 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
- if ((inherit_from_dir != NULL) && lp_inherit_perms(SNUM(conn))) {
- struct smb_filename *smb_fname_parent = NULL;
- NTSTATUS status;
+ if (fname && (inherit_from_dir != NULL)
+ && lp_inherit_perms(SNUM(conn))) {
+ SMB_STRUCT_STAT sbuf;
- DEBUG(2, ("unix_mode(%s) inheriting from %s\n",
- smb_fname_str_dbg(smb_fname),
+ DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
inherit_from_dir));
-
- status = create_synthetic_smb_fname(talloc_tos(),
- inherit_from_dir, NULL,
- NULL, &smb_fname_parent);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("unix_mode(%s) failed, [dir %s]: %s\n",
- smb_fname_str_dbg(smb_fname),
- inherit_from_dir, nt_errstr(status)));
- return(0);
- }
-
- if (SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
- DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",
- smb_fname_str_dbg(smb_fname),
+ if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
+ DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
inherit_from_dir, strerror(errno)));
- TALLOC_FREE(smb_fname_parent);
return(0); /* *** shouldn't happen! *** */
}
/* Save for later - but explicitly remove setuid bit for safety. */
- dir_mode = smb_fname_parent->st.st_ex_mode & ~S_ISUID;
- DEBUG(2,("unix_mode(%s) inherit mode %o\n",
- smb_fname_str_dbg(smb_fname), (int)dir_mode));
+ dir_mode = sbuf.st_mode & ~S_ISUID;
+ DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
/* Clear "result" */
result = 0;
- TALLOC_FREE(smb_fname_parent);
}
if (IS_DOS_DIR(dosmode)) {
@@ -147,7 +131,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
result |= S_IXGRP;
-
+
if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
result |= S_IXOTH;
@@ -162,8 +146,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
}
}
- DEBUG(3,("unix_mode(%s) returning 0%o\n", smb_fname_str_dbg(smb_fname),
- (int)result));
+ DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
return(result);
}
@@ -171,38 +154,37 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
Change a unix mode to a dos mode.
****************************************************************************/
-static uint32 dos_mode_from_sbuf(connection_struct *conn,
- const struct smb_filename *smb_fname)
+static 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 (ro_opts == MAP_READONLY_YES) {
/* Original Samba method - map inverse of user "w" bit. */
- if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) {
+ 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, smb_fname)) {
+ if (!can_write_to_file(conn, path, sbuf)) {
result |= aRONLY;
}
} /* Else never set the readonly bit. */
- if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0))
+ if (MAP_ARCHIVE(conn) && ((sbuf->st_mode & S_IXUSR) != 0))
result |= aARCH;
- if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0))
+ if (MAP_SYSTEM(conn) && ((sbuf->st_mode & S_IXGRP) != 0))
result |= aSYSTEM;
-
- if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0))
+
+ if (MAP_HIDDEN(conn) && ((sbuf->st_mode & S_IXOTH) != 0))
result |= aHIDDEN;
-
- if (S_ISDIR(smb_fname->st.st_ex_mode))
+
+ if (S_ISDIR(sbuf->st_mode))
result = aDIR | (result & aRONLY);
- result |= set_sparse_flag(&smb_fname->st);
- result |= set_link_read_only_flag(&smb_fname->st);
+ result |= set_sparse_flag(sbuf);
+ result |= set_link_read_only_flag(sbuf);
DEBUG(8,("dos_mode_from_sbuf returning "));
@@ -211,26 +193,20 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn,
if (result & aSYSTEM) DEBUG(8, ("s"));
if (result & aDIR ) DEBUG(8, ("d"));
if (result & aARCH ) DEBUG(8, ("a"));
-
+
DEBUG(8,("\n"));
return result;
}
/****************************************************************************
Get DOS attributes from an EA.
- This can also pull the create time into the stat struct inside smb_fname.
****************************************************************************/
-static bool get_ea_dos_attribute(connection_struct *conn,
- struct smb_filename *smb_fname,
- uint32 *pattr)
+static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
{
- struct xattr_DOSATTRIB dosattrib;
- enum ndr_err_code ndr_err;
- DATA_BLOB blob;
ssize_t sizeret;
fstring attrstr;
- uint32_t dosattr;
+ unsigned int dosattr;
if (!lp_store_dos_attributes(SNUM(conn))) {
return False;
@@ -239,9 +215,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
/* Don't reset pattr to zero as we may already have filename-based attributes we
need to preserve. */
- sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name,
- SAMBA_XATTR_DOS_ATTRIB, attrstr,
- sizeof(attrstr));
+ sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
if (sizeret == -1) {
if (errno == ENOSYS
#if defined(ENOTSUP)
@@ -249,75 +223,23 @@ static bool get_ea_dos_attribute(connection_struct *conn,
#else
) {
#endif
- DEBUG(1,("get_ea_dos_attributes: Cannot get attribute "
- "from EA on file %s: Error = %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
+ DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
+ path, strerror(errno) ));
set_store_dos_attributes(SNUM(conn), False);
}
return False;
}
+ /* Null terminate string. */
+ attrstr[sizeret] = 0;
+ DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
- blob.data = (uint8_t *)attrstr;
- blob.length = sizeret;
-
- ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &dosattrib,
- (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
-
- DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
- smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex));
-
- switch (dosattrib.version) {
- case 0xFFFF:
- dosattr = dosattrib.info.compatinfoFFFF.attrib;
- break;
- case 1:
- dosattr = dosattrib.info.info1.attrib;
- if (!null_nttime(dosattrib.info.info1.create_time)) {
- struct timespec create_time =
- nt_time_to_unix_timespec(
- &dosattrib.info.info1.create_time);
-
- update_stat_ex_create_time(&smb_fname->st,
- create_time);
-
- DEBUG(10,("get_ea_dos_attributes: file %s case 1 "
- "set btime %s\n",
- smb_fname_str_dbg(smb_fname),
- time_to_asc(convert_timespec_to_time_t(
- create_time)) ));
- }
- break;
- case 2:
- dosattr = dosattrib.info.oldinfo2.attrib;
- /* Don't know what flags to check for this case. */
- break;
- case 3:
- dosattr = dosattrib.info.info3.attrib;
- if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
- !null_nttime(dosattrib.info.info3.create_time)) {
- struct timespec create_time =
- nt_time_to_unix_timespec(
- &dosattrib.info.info3.create_time);
-
- update_stat_ex_create_time(&smb_fname->st,
- create_time);
-
- DEBUG(10,("get_ea_dos_attributes: file %s case 3 "
- "set btime %s\n",
- smb_fname_str_dbg(smb_fname),
- time_to_asc(convert_timespec_to_time_t(
- create_time)) ));
- }
- break;
- default:
- DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
- "file %s - %s\n", smb_fname_str_dbg(smb_fname),
- attrstr));
- return false;
- }
+ if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
+ sscanf(attrstr, "%x", &dosattr) != 1) {
+ DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
+ return False;
+ }
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (S_ISDIR(sbuf->st_mode)) {
dosattr |= aDIR;
}
*pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
@@ -329,7 +251,7 @@ static bool get_ea_dos_attribute(connection_struct *conn,
if (dosattr & aSYSTEM) DEBUG(8, ("s"));
if (dosattr & aDIR ) DEBUG(8, ("d"));
if (dosattr & aARCH ) DEBUG(8, ("a"));
-
+
DEBUG(8,("\n"));
return True;
@@ -337,50 +259,20 @@ static bool get_ea_dos_attribute(connection_struct *conn,
/****************************************************************************
Set DOS attributes in an EA.
- Also sets the create time.
****************************************************************************/
-static bool set_ea_dos_attribute(connection_struct *conn,
- struct smb_filename *smb_fname,
- uint32 dosmode)
+static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
{
- struct xattr_DOSATTRIB dosattrib;
- enum ndr_err_code ndr_err;
- DATA_BLOB blob;
+ fstring attrstr;
files_struct *fsp = NULL;
- bool ret = false;
+ bool ret = False;
if (!lp_store_dos_attributes(SNUM(conn))) {
return False;
}
- ZERO_STRUCT(dosattrib);
- ZERO_STRUCT(blob);
-
- dosattrib.version = 3;
- dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB|
- XATTR_DOSINFO_CREATE_TIME;
- dosattrib.info.info3.attrib = dosmode;
- unix_timespec_to_nt_time(&dosattrib.info.info3.create_time,
- smb_fname->st.st_ex_btime);
-
- ndr_err = ndr_push_struct_blob(
- &blob, talloc_tos(), NULL, &dosattrib,
- (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB);
-
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n",
- ndr_errstr(ndr_err)));
- return false;
- }
-
- if (blob.data == NULL || blob.length == 0) {
- return false;
- }
-
- if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
- SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
- 0) == -1) {
+ snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
if((errno != EPERM) && (errno != EACCES)) {
if (errno == ENOSYS
#if defined(ENOTSUP)
@@ -388,13 +280,11 @@ static bool set_ea_dos_attribute(connection_struct *conn,
#else
) {
#endif
- DEBUG(1,("set_ea_dos_attributes: Cannot set "
- "attribute EA on file %s: Error = %s\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
+ DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n",
+ path, strerror(errno) ));
set_store_dos_attributes(SNUM(conn), False);
}
- return false;
+ return False;
}
/* We want DOS semantics, ie allow non owner with write permission to change the
@@ -403,7 +293,7 @@ static bool set_ea_dos_attribute(connection_struct *conn,
/* Check if we have write access. */
if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
- return false;
+ return False;
/*
* We need to open the file with write access whilst
@@ -411,48 +301,43 @@ static bool set_ea_dos_attribute(connection_struct *conn,
* are not violating security in doing the setxattr.
*/
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
+ if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, path, sbuf,
&fsp)))
return ret;
become_root();
- if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
- SAMBA_XATTR_DOS_ATTRIB, blob.data,
- blob.length, 0) == 0) {
- ret = true;
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
+ ret = True;
}
unbecome_root();
close_file_fchmod(NULL, fsp);
return ret;
}
- DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n",
- (unsigned int)dosmode,
- smb_fname_str_dbg(smb_fname)));
- return true;
+ DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
+ return True;
}
/****************************************************************************
Change a unix mode to a dos mode for an ms dfs link.
****************************************************************************/
-uint32 dos_mode_msdfs(connection_struct *conn,
- const struct smb_filename *smb_fname)
+uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
{
uint32 result = 0;
- DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname)));
+ DEBUG(8,("dos_mode_msdfs: %s\n", path));
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*sbuf)) {
return 0;
}
/* First do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(conn))) {
- const char *p = strrchr_m(smb_fname->base_name, '/');
+ const char *p = strrchr_m(path,'/');
if (p) {
p++;
} else {
- p = smb_fname->base_name;
+ p = path;
}
/* Only . and .. are not hidden. */
@@ -461,13 +346,12 @@ uint32 dos_mode_msdfs(connection_struct *conn,
result |= aHIDDEN;
}
}
-
- result |= dos_mode_from_sbuf(conn, smb_fname);
+
+ result |= dos_mode_from_sbuf(conn, path, sbuf);
/* Optimization : Only call is_hidden_path if it's not already
hidden. */
- if (!(result & aHIDDEN) &&
- IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
+ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
result |= aHIDDEN;
}
@@ -485,7 +369,7 @@ uint32 dos_mode_msdfs(connection_struct *conn,
if (result & aDIR ) DEBUG(8, ("d"));
if (result & aARCH ) DEBUG(8, ("a"));
if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
-
+
DEBUG(8,("\n"));
return(result);
@@ -515,55 +399,56 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode)
}
/****************************************************************************
- Gets DOS attributes, accessed via st_ex_flags in the stat struct.
+ Gets DOS attributes, accessed via st_flags in the stat struct.
****************************************************************************/
static bool get_stat_dos_flags(connection_struct *conn,
- const struct smb_filename *smb_fname,
+ const char *fname,
+ const SMB_STRUCT_STAT *sbuf,
uint32_t *dosmode)
{
- SMB_ASSERT(VALID_STAT(smb_fname->st));
+ SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
SMB_ASSERT(dosmode);
if (!lp_store_dos_attributes(SNUM(conn))) {
return false;
}
- DEBUG(5, ("Getting stat dos attributes for %s.\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(5, ("Getting stat dos attributes for %s.\n", fname));
- if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE)
+ if (sbuf->st_flags & UF_DOS_ARCHIVE)
*dosmode |= aARCH;
- if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN)
+ if (sbuf->st_flags & UF_DOS_HIDDEN)
*dosmode |= aHIDDEN;
- if (smb_fname->st.st_ex_flags & UF_DOS_RO)
+ if (sbuf->st_flags & UF_DOS_RO)
*dosmode |= aRONLY;
- if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM)
+ if (sbuf->st_flags & UF_DOS_SYSTEM)
*dosmode |= aSYSTEM;
- if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX)
+ if (sbuf->st_flags & UF_DOS_NOINDEX)
*dosmode |= FILE_ATTRIBUTE_NONINDEXED;
- if (S_ISDIR(smb_fname->st.st_ex_mode))
+ if (S_ISDIR(sbuf->st_mode))
*dosmode |= aDIR;
- *dosmode |= set_sparse_flag(&smb_fname->st);
- *dosmode |= set_link_read_only_flag(&smb_fname->st);
+ *dosmode |= set_sparse_flag(sbuf);
+ *dosmode |= set_link_read_only_flag(sbuf);
return true;
}
/****************************************************************************
- Sets DOS attributes, stored in st_ex_flags of the inode.
+ Sets DOS attributes, stored in st_flags of the inode.
****************************************************************************/
static bool set_stat_dos_flags(connection_struct *conn,
- const struct smb_filename *smb_fname,
- uint32_t dosmode,
- bool *attributes_changed)
+ const char *fname,
+ SMB_STRUCT_STAT *sbuf,
+ uint32_t dosmode,
+ bool *attributes_changed)
{
uint32_t new_flags = 0;
int error = 0;
- SMB_ASSERT(VALID_STAT(smb_fname->st));
+ SMB_ASSERT(sbuf && VALID_STAT(*sbuf));
SMB_ASSERT(attributes_changed);
*attributes_changed = false;
@@ -572,25 +457,23 @@ static bool set_stat_dos_flags(connection_struct *conn,
return false;
}
- DEBUG(5, ("Setting stat dos attributes for %s.\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(5, ("Setting stat dos attributes for %s.\n", fname));
- new_flags = (smb_fname->st.st_ex_flags & ~UF_DOS_FLAGS) |
+ new_flags = (sbuf->st_flags & ~UF_DOS_FLAGS) |
dos_attributes_to_stat_dos_flags(dosmode);
/* Return early if no flags changed. */
- if (new_flags == smb_fname->st.st_ex_flags)
+ if (new_flags == sbuf->st_flags)
return true;
DEBUG(5, ("Setting stat dos attributes=0x%x, prev=0x%x\n", new_flags,
- smb_fname->st.st_ex_flags));
+ sbuf->st_flags));
/* Set new flags with chflags. */
- error = SMB_VFS_CHFLAGS(conn, smb_fname->base_name, new_flags);
+ error = SMB_VFS_CHFLAGS(conn, fname, new_flags);
if (error) {
DEBUG(0, ("Failed setting new stat dos attributes (0x%x) on "
- "file %s! errno=%d\n", new_flags,
- smb_fname_str_dbg(smb_fname), errno));
+ "file %s! errno=%d\n", new_flags, fname, errno));
return false;
}
@@ -601,29 +484,27 @@ static bool set_stat_dos_flags(connection_struct *conn,
/****************************************************************************
Change a unix mode to a dos mode.
- May also read the create timespec into the stat struct in smb_fname
- if "store dos attributes" is true.
****************************************************************************/
-uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
+uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
{
uint32 result = 0;
bool offline, used_stat_dos_flags = false;
- DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname)));
+ DEBUG(8,("dos_mode: %s\n", path));
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*sbuf)) {
return 0;
}
/* First do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(conn))) {
- const char *p = strrchr_m(smb_fname->base_name,'/');
+ const char *p = strrchr_m(path,'/');
if (p) {
p++;
} else {
- p = smb_fname->base_name;
+ p = path;
}
/* Only . and .. are not hidden. */
@@ -632,28 +513,28 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
result |= aHIDDEN;
}
}
-
+
#ifdef HAVE_STAT_DOS_FLAGS
- used_stat_dos_flags = get_stat_dos_flags(conn, smb_fname, &result);
+ used_stat_dos_flags = get_stat_dos_flags(conn, path, sbuf, &result);
#endif
if (!used_stat_dos_flags) {
/* Get the DOS attributes from an EA by preference. */
- if (get_ea_dos_attribute(conn, smb_fname, &result)) {
- result |= set_sparse_flag(&smb_fname->st);
+ if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
+ result |= set_sparse_flag(sbuf);
} else {
- result |= dos_mode_from_sbuf(conn, smb_fname);
+ result |= dos_mode_from_sbuf(conn, path, sbuf);
}
}
- offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &smb_fname->st);
- if (S_ISREG(smb_fname->st.st_ex_mode) && offline) {
+
+ offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf);
+ if (S_ISREG(sbuf->st_mode) && offline) {
result |= FILE_ATTRIBUTE_OFFLINE;
}
/* Optimization : Only call is_hidden_path if it's not already
hidden. */
- if (!(result & aHIDDEN) &&
- IS_HIDDEN_PATH(conn, smb_fname->base_name)) {
+ if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) {
result |= aHIDDEN;
}
@@ -671,7 +552,7 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
if (result & aDIR ) DEBUG(8, ("d"));
if (result & aARCH ) DEBUG(8, ("a"));
if (result & FILE_ATTRIBUTE_SPARSE ) DEBUG(8, ("[sparse]"));
-
+
DEBUG(8,("\n"));
return(result);
@@ -679,51 +560,54 @@ uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
/*******************************************************************
chmod a file - but preserve some bits.
- If "store dos attributes" is also set it will store the create time
- from the stat struct in smb_fname (in NTTIME format) in the EA
- attribute also.
********************************************************************/
-int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
- uint32 dosmode, const char *parent_dir, bool newfile)
+int file_set_dosmode(connection_struct *conn, const char *fname,
+ uint32 dosmode, SMB_STRUCT_STAT *st,
+ const char *parent_dir,
+ bool newfile)
{
+ SMB_STRUCT_STAT st1;
int mask=0;
mode_t tmp;
mode_t unixmode;
int ret = -1, lret = -1;
uint32_t old_mode;
- struct timespec new_create_timespec;
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
- DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n",
- dosmode, smb_fname_str_dbg(smb_fname)));
+ DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
- unixmode = smb_fname->st.st_ex_mode;
+ if (st == NULL) {
+ SET_STAT_INVALID(st1);
+ st = &st1;
+ }
+
+ if (!VALID_STAT(*st)) {
+ if (SMB_VFS_STAT(conn,fname,st))
+ return(-1);
+ }
- get_acl_group_bits(conn, smb_fname->base_name,
- &smb_fname->st.st_ex_mode);
+ unixmode = st->st_mode;
- if (S_ISDIR(smb_fname->st.st_ex_mode))
+ get_acl_group_bits(conn, fname, &st->st_mode);
+
+ if (S_ISDIR(st->st_mode))
dosmode |= aDIR;
else
dosmode &= ~aDIR;
- new_create_timespec = smb_fname->st.st_ex_btime;
-
- old_mode = dos_mode(conn, smb_fname);
-
+ old_mode = dos_mode(conn,fname,st);
+
if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) {
- lret = SMB_VFS_SET_OFFLINE(conn, smb_fname->base_name);
+ lret = SMB_VFS_SET_OFFLINE(conn, fname);
if (lret == -1) {
- DEBUG(0, ("set_dos_mode: client has asked to "
- "set FILE_ATTRIBUTE_OFFLINE to "
- "%s/%s but there was an error while "
- "setting it or it is not "
- "supported.\n", parent_dir,
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(0, ("set_dos_mode: client has asked to set "
+ "FILE_ATTRIBUTE_OFFLINE to %s/%s but there was "
+ "an error while setting it or it is not supported.\n",
+ parent_dir, fname));
}
}
}
@@ -731,37 +615,39 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
- smb_fname->st.st_ex_btime = new_create_timespec;
+ if (old_mode == dosmode) {
+ st->st_mode = unixmode;
+ return(0);
+ }
#ifdef HAVE_STAT_DOS_FLAGS
{
bool attributes_changed;
- if (set_stat_dos_flags(conn, smb_fname, dosmode,
+ if (set_stat_dos_flags(conn, fname, st, dosmode,
&attributes_changed))
{
if (!newfile && attributes_changed) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES,
- smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- smb_fname->st.st_ex_mode = unixmode;
+ st->st_mode = unixmode;
return 0;
}
}
#endif
+
/* Store the DOS attributes in an EA by preference. */
- if (set_ea_dos_attribute(conn, smb_fname, dosmode)) {
+ if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
if (!newfile) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES,
- smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- smb_fname->st.st_ex_mode = unixmode;
+ st->st_mode = unixmode;
return 0;
}
- unixmode = unix_mode(conn, dosmode, smb_fname, parent_dir);
+ unixmode = unix_mode(conn,dosmode,fname, parent_dir);
/* preserve the s bits */
mask |= (S_ISUID | S_ISGID);
@@ -779,10 +665,10 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
if (!MAP_HIDDEN(conn))
mask |= S_IXOTH;
- unixmode |= (smb_fname->st.st_ex_mode & mask);
+ unixmode |= (st->st_mode & mask);
/* if we previously had any r bits set then leave them alone */
- if ((tmp = smb_fname->st.st_ex_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
+ if ((tmp = st->st_mode & (S_IRUSR|S_IRGRP|S_IROTH))) {
unixmode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
unixmode |= tmp;
}
@@ -790,17 +676,16 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
/* if we previously had any w bits set then leave them alone
whilst adding in the new w bits, if the new mode is not rdonly */
if (!IS_DOS_READONLY(dosmode)) {
- unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
+ unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH));
}
- ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
+ ret = SMB_VFS_CHMOD(conn, fname, unixmode);
if (ret == 0) {
if(!newfile || (lret != -1)) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES,
- smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
- smb_fname->st.st_ex_mode = unixmode;
+ st->st_mode = unixmode;
return 0;
}
@@ -825,8 +710,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
* break batch oplocks open by others. JRA.
*/
files_struct *fsp;
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname,
- &fsp)))
+ if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, st,
+ &fsp)))
return -1;
become_root();
ret = SMB_VFS_FCHMOD(fsp, unixmode);
@@ -834,11 +719,10 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
close_file_fchmod(NULL, fsp);
if (!newfile) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES,
- smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_ATTRIBUTES, fname);
}
if (ret == 0) {
- smb_fname->st.st_ex_mode = unixmode;
+ st->st_mode = unixmode;
}
}
@@ -850,19 +734,19 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
than POSIX.
*******************************************************************/
-int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
+int file_ntimes(connection_struct *conn, const char *fname,
struct smb_file_time *ft)
{
+ SMB_STRUCT_STAT sbuf;
int ret = -1;
errno = 0;
+ ZERO_STRUCT(sbuf);
DEBUG(6, ("file_ntime: actime: %s",
time_to_asc(convert_timespec_to_time_t(ft->atime))));
DEBUG(6, ("file_ntime: modtime: %s",
time_to_asc(convert_timespec_to_time_t(ft->mtime))));
- DEBUG(6, ("file_ntime: ctime: %s",
- time_to_asc(convert_timespec_to_time_t(ft->ctime))));
DEBUG(6, ("file_ntime: createtime: %s",
time_to_asc(convert_timespec_to_time_t(ft->create_time))));
@@ -877,7 +761,7 @@ int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
return 0;
}
- if(SMB_VFS_NTIMES(conn, smb_fname, ft) == 0) {
+ if(SMB_VFS_NTIMES(conn, fname, ft) == 0) {
return 0;
}
@@ -896,10 +780,10 @@ int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
*/
/* Check if we have write access. */
- if (can_write_to_file(conn, smb_fname)) {
+ if (can_write_to_file(conn, fname, &sbuf)) {
/* We are allowed to become root and change the filetime. */
become_root();
- ret = SMB_VFS_NTIMES(conn, smb_fname, ft);
+ ret = SMB_VFS_NTIMES(conn, fname, ft);
unbecome_root();
}
@@ -911,7 +795,8 @@ int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
returned on all future write time queries and set on close.
******************************************************************/
-bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime)
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime)
{
if (null_timespec(mtime)) {
return true;
@@ -929,77 +814,27 @@ bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime)
returned on all future write time queries and set on close.
******************************************************************/
-bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
{
- if (null_timespec(mtime)) {
- return true;
- }
-
fsp->write_time_forced = true;
TALLOC_FREE(fsp->update_write_time_event);
- return set_sticky_write_time_path(fsp->file_id, mtime);
+ return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
+ fsp->file_id, mtime);
}
/******************************************************************
- Set a create time EA.
+ Update a write time immediately, without the 2 second delay.
******************************************************************/
-NTSTATUS set_create_timespec_ea(connection_struct *conn,
- const struct smb_filename *psmb_fname,
- struct timespec create_time)
+bool update_write_time(struct files_struct *fsp)
{
- NTSTATUS status;
- struct smb_filename *smb_fname = NULL;
- uint32_t dosmode;
- int ret;
-
- if (!lp_store_dos_attributes(SNUM(conn))) {
- return NT_STATUS_OK;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(),
- psmb_fname->base_name,
- NULL, &psmb_fname->st,
- &smb_fname);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- dosmode = dos_mode(conn, smb_fname);
-
- smb_fname->st.st_ex_btime = create_time;
-
- ret = file_set_dosmode(conn, smb_fname, dosmode, NULL, false);
- if (ret == -1) {
- map_nt_error_from_unix(errno);
+ if (!set_write_time(fsp->file_id, timespec_current())) {
+ return false;
}
- DEBUG(10,("set_create_timespec_ea: wrote create time EA for file %s\n",
- smb_fname_str_dbg(smb_fname)));
-
- return NT_STATUS_OK;
-}
-
-/******************************************************************
- Return a create time.
-******************************************************************/
-
-struct timespec get_create_timespec(connection_struct *conn,
- struct files_struct *fsp,
- const struct smb_filename *smb_fname)
-{
- return smb_fname->st.st_ex_btime;
-}
+ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
-/******************************************************************
- Return a change time (may look at EA in future).
-******************************************************************/
-
-struct timespec get_change_timespec(connection_struct *conn,
- struct files_struct *fsp,
- const struct smb_filename *smb_fname)
-{
- return smb_fname->st.st_ex_mtime;
+ return true;
}
diff --git a/source3/smbd/error.c b/source3/smbd/error.c
index 252eb77416..ce22f86414 100644
--- a/source3/smbd/error.c
+++ b/source3/smbd/error.c
@@ -30,29 +30,9 @@ bool use_nt_status(void)
/****************************************************************************
Create an error packet. Normally called using the ERROR() macro.
-
- Setting eclass and ecode to zero and status to a valid NT error will
- reply with an NT error if the client supports CAP_STATUS32, otherwise
- it maps to and returns a DOS error if the client doesn't support CAP_STATUS32.
- This is the normal mode of calling this function via reply_nterror(req, status).
-
- Setting eclass and ecode to non-zero and status to NT_STATUS_OK (0) will map
- from a DOS error to an NT error and reply with an NT error if the client
- supports CAP_STATUS32, otherwise it replies with the given DOS error.
- This mode is currently not used in the server.
-
- Setting both eclass, ecode and status to non-zero values allows a non-default
- mapping from NT error codes to DOS error codes, and will return one or the
- other depending on the client supporting CAP_STATUS32 or not. This is the
- path taken by calling reply_botherror(req, eclass, ecode, status);
-
- Setting status to NT_STATUS_DOS(eclass, ecode) forces DOS errors even if the
- client supports CAP_STATUS32. This is the path taken to force a DOS error
- reply by calling reply_force_doserror(req, eclass, ecode).
-
- Setting status only and eclass to -1 forces NT errors even if the client
- doesn't support CAP_STATUS32. This mode is currently never used in the
- server.
+ Setting eclass and ecode only and status to NT_STATUS_OK forces DOS errors.
+ Setting status only and eclass and ecode to zero forces NT errors.
+ If the override errors are set they take precedence over any passed in values.
****************************************************************************/
void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
@@ -115,20 +95,21 @@ void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus,
error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file);
}
-/****************************************************************************
- Forces a DOS error on the wire.
-****************************************************************************/
+void reply_force_nt_error(struct smb_request *req, NTSTATUS ntstatus,
+ int line, const char *file)
+{
+ TALLOC_FREE(req->outbuf);
+ reply_outbuf(req, 0, 0);
+ error_packet_set((char *)req->outbuf, -1, -1, ntstatus, line, file);
+}
-void reply_force_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode,
+void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode,
int line, const char *file)
{
TALLOC_FREE(req->outbuf);
reply_outbuf(req, 0, 0);
- error_packet_set((char *)req->outbuf,
- eclass, ecode,
- NT_STATUS_DOS(eclass, ecode),
- line,
- file);
+ error_packet_set((char *)req->outbuf, eclass, ecode, NT_STATUS_OK, line,
+ file);
}
void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode,
@@ -151,12 +132,37 @@ void reply_openerror(struct smb_request *req, NTSTATUS status)
*/
reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
ERRDOS, ERRfilexists);
- } else if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) {
- /* EMFILE always seems to be returned as a DOS error.
- * See bug 6837. NOTE this forces a DOS error on the wire
- * even though it's calling reply_nterror(). */
- reply_force_doserror(req, ERRDOS, ERRnofids);
} else {
reply_nterror(req, status);
}
}
+
+void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode,
+ NTSTATUS defstatus, int line, const char *file)
+{
+ int eclass=defclass;
+ int ecode=defcode;
+ NTSTATUS ntstatus = defstatus;
+ int i=0;
+
+ TALLOC_FREE(req->outbuf);
+ reply_outbuf(req, 0, 0);
+
+ if (errno != 0) {
+ DEBUG(3,("unix_error_packet: error string = %s\n",
+ strerror(errno)));
+
+ while (unix_dos_nt_errmap[i].dos_class != 0) {
+ if (unix_dos_nt_errmap[i].unix_error == errno) {
+ eclass = unix_dos_nt_errmap[i].dos_class;
+ ecode = unix_dos_nt_errmap[i].dos_code;
+ ntstatus = unix_dos_nt_errmap[i].nt_error;
+ break;
+ }
+ i++;
+ }
+ }
+
+ error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus,
+ line, file);
+}
diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c
index 6898793d29..ef54398bc4 100644
--- a/source3/smbd/fake_file.c
+++ b/source3/smbd/fake_file.c
@@ -71,45 +71,28 @@ static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type)
Does this name match a fake filename ?
****************************************************************************/
-enum FAKE_FILE_TYPE is_fake_file_path(const char *path)
+enum FAKE_FILE_TYPE is_fake_file(const char *fname)
{
+#ifdef HAVE_SYS_QUOTAS
int i;
+#endif
- if (!path) {
+ if (!fname) {
return FAKE_FILE_TYPE_NONE;
}
+#ifdef HAVE_SYS_QUOTAS
for (i=0;fake_files[i].name!=NULL;i++) {
- if (strncmp(path,fake_files[i].name,strlen(fake_files[i].name))==0) {
- DEBUG(5,("is_fake_file: [%s] is a fake file\n",path));
+ if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) {
+ DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname));
return fake_files[i].type;
}
}
+#endif
return FAKE_FILE_TYPE_NONE;
}
-enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname)
-{
- char *fname = NULL;
- NTSTATUS status;
- enum FAKE_FILE_TYPE ret;
-
- if (!smb_fname) {
- return FAKE_FILE_TYPE_NONE;
- }
-
- status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- return FAKE_FILE_TYPE_NONE;
- }
-
- ret = is_fake_file_path(fname);
-
- TALLOC_FREE(fname);
-
- return ret;
-}
/****************************************************************************
Open a fake quota file with a share mode.
@@ -118,7 +101,7 @@ enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname)
NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
uint16_t current_vuid,
enum FAKE_FILE_TYPE fake_file_type,
- const struct smb_filename *smb_fname,
+ const char *fname,
uint32 access_mask,
files_struct **result)
{
@@ -129,8 +112,7 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
if (conn->server_info->utok.uid != 0) {
DEBUG(3, ("open_fake_file_shared: access_denied to "
"service[%s] file[%s] user[%s]\n",
- lp_servicename(SNUM(conn)),
- smb_fname_str_dbg(smb_fname),
+ lp_servicename(SNUM(conn)), fname,
conn->server_info->unix_name));
return NT_STATUS_ACCESS_DENIED;
@@ -142,8 +124,7 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
}
DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n",
- smb_fname_str_dbg(smb_fname), fsp->fnum,
- (unsigned int)access_mask));
+ fname, fsp->fnum, (unsigned int)access_mask));
fsp->conn = conn;
fsp->fh->fd = -1;
@@ -151,12 +132,8 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
fsp->fh->pos = -1;
fsp->can_lock = False; /* Should this be true ? - No, JRA */
fsp->access_mask = access_mask;
- status = fsp_set_smb_fname(fsp, smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- file_free(req, fsp);
- return NT_STATUS_NO_MEMORY;
- }
-
+ string_set(&fsp->fsp_name,fname);
+
fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
if (fsp->fake_file_handle==NULL) {
diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c
index 7d0a552956..1c0124ecbc 100644
--- a/source3/smbd/file_access.c
+++ b/source3/smbd/file_access.c
@@ -27,36 +27,32 @@
* Security descriptor / NT Token level access check function.
*/
bool can_access_file_acl(struct connection_struct *conn,
- const struct smb_filename *smb_fname,
- uint32_t access_mask)
+ const char * fname,
+ uint32_t access_mask)
{
NTSTATUS status;
uint32_t access_granted;
struct security_descriptor *secdesc = NULL;
- bool ret;
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return true;
}
- status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
+ status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION),
&secdesc);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
- ret = false;
- goto out;
+ return false;
}
status = se_access_check(secdesc, conn->server_info->ptok,
access_mask, &access_granted);
- ret = NT_STATUS_IS_OK(status);
- out:
TALLOC_FREE(secdesc);
- return ret;
+ return NT_STATUS_IS_OK(status);
}
/****************************************************************************
@@ -64,67 +60,50 @@ bool can_access_file_acl(struct connection_struct *conn,
this to successfully return ACCESS_DENIED on a file open for delete access.
****************************************************************************/
-bool can_delete_file_in_directory(connection_struct *conn,
- struct smb_filename *smb_fname)
+bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
{
+ SMB_STRUCT_STAT sbuf;
TALLOC_CTX *ctx = talloc_tos();
char *dname = NULL;
- struct smb_filename *smb_fname_parent = NULL;
- NTSTATUS status;
- bool ret;
if (!CAN_WRITE(conn)) {
return False;
}
/* Get the parent directory permission mask and owners. */
- if (!parent_dirname(ctx, smb_fname->base_name, &dname, NULL)) {
+ if (!parent_dirname(ctx, fname, &dname, NULL)) {
return False;
}
-
- status = create_synthetic_smb_fname(ctx, dname, NULL, NULL,
- &smb_fname_parent);
- if (!NT_STATUS_IS_OK(status)) {
- ret = false;
- goto out;
- }
-
- if(SMB_VFS_STAT(conn, smb_fname_parent) != 0) {
- ret = false;
- goto out;
+ if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
+ return False;
}
/* fast paths first */
- if (!S_ISDIR(smb_fname_parent->st.st_ex_mode)) {
- ret = false;
- goto out;
+ if (!S_ISDIR(sbuf.st_mode)) {
+ return False;
}
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
- ret = true;
- goto out;
+ return True;
}
#ifdef S_ISVTX
/* sticky bit means delete only by owner of file or by root or
* by owner of directory. */
- if (smb_fname_parent->st.st_ex_mode & S_ISVTX) {
- if(SMB_VFS_STAT(conn, smb_fname) != 0) {
+ if (sbuf.st_mode & S_ISVTX) {
+ SMB_STRUCT_STAT sbuf_file;
+ if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
if (errno == ENOENT) {
/* If the file doesn't already exist then
* yes we'll be able to delete it. */
- ret = true;
- goto out;
+ return True;
}
DEBUG(10,("can_delete_file_in_directory: can't "
- "stat file %s (%s)",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
- ret = false;
- goto out;
+ "stat file %s (%s)",
+ fname, strerror(errno) ));
+ return False;
}
-
/*
* Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
* for bug #3348. Don't assume owning sticky bit
@@ -133,15 +112,12 @@ bool can_delete_file_in_directory(connection_struct *conn,
* or the owner of the directory as we have no possible
* chance of deleting. Otherwise, go on and check the ACL.
*/
- if ((conn->server_info->utok.uid !=
- smb_fname_parent->st.st_ex_uid) &&
- (conn->server_info->utok.uid != smb_fname->st.st_ex_uid)) {
+ if ((conn->server_info->utok.uid != sbuf.st_uid) &&
+ (conn->server_info->utok.uid != sbuf_file.st_uid)) {
DEBUG(10,("can_delete_file_in_directory: not "
- "owner of file %s or directory %s",
- smb_fname_str_dbg(smb_fname),
- smb_fname_str_dbg(smb_fname_parent)));
- ret = false;
- goto out;
+ "owner of file %s or directory %s",
+ fname, dname));
+ return False;
}
}
#endif
@@ -157,11 +133,7 @@ bool can_delete_file_in_directory(connection_struct *conn,
* check the file DELETE permission separately.
*/
- ret = can_access_file_acl(conn, smb_fname_parent, FILE_DELETE_CHILD);
- out:
- TALLOC_FREE(dname);
- TALLOC_FREE(smb_fname_parent);
- return ret;
+ return can_access_file_acl(conn, dname, FILE_DELETE_CHILD);
}
/****************************************************************************
@@ -170,9 +142,7 @@ bool can_delete_file_in_directory(connection_struct *conn,
Note this doesn't take into account share write permissions.
****************************************************************************/
-bool can_access_file_data(connection_struct *conn,
- const struct smb_filename *smb_fname,
- uint32 access_mask)
+bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
{
if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
return False;
@@ -182,31 +152,32 @@ bool can_access_file_data(connection_struct *conn,
/* some fast paths first */
DEBUG(10,("can_access_file_data: requesting 0x%x on file %s\n",
- (unsigned int)access_mask, smb_fname_str_dbg(smb_fname)));
+ (unsigned int)access_mask, fname ));
if (conn->server_info->utok.uid == 0 || conn->admin_user) {
/* I'm sorry sir, I didn't know you were root... */
return True;
}
- SMB_ASSERT(VALID_STAT(smb_fname->st));
+ if (!VALID_STAT(*psbuf)) {
+ /* Get the file permission mask and owners. */
+ if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ return False;
+ }
+ }
/* Check primary owner access. */
- if (conn->server_info->utok.uid == smb_fname->st.st_ex_uid) {
+ if (conn->server_info->utok.uid == psbuf->st_uid) {
switch (access_mask) {
case FILE_READ_DATA:
- return (smb_fname->st.st_ex_mode & S_IRUSR) ?
- True : False;
+ return (psbuf->st_mode & S_IRUSR) ? True : False;
case FILE_WRITE_DATA:
- return (smb_fname->st.st_ex_mode & S_IWUSR) ?
- True : False;
+ return (psbuf->st_mode & S_IWUSR) ? True : False;
default: /* FILE_READ_DATA|FILE_WRITE_DATA */
- if ((smb_fname->st.st_ex_mode &
- (S_IWUSR|S_IRUSR)) ==
- (S_IWUSR|S_IRUSR)) {
+ if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
return True;
} else {
return False;
@@ -216,7 +187,7 @@ bool can_access_file_data(connection_struct *conn,
/* now for ACL checks */
- return can_access_file_acl(conn, smb_fname, access_mask);
+ return can_access_file_acl(conn, fname, access_mask);
}
/****************************************************************************
@@ -224,10 +195,9 @@ bool can_access_file_data(connection_struct *conn,
Note this doesn't take into account share write permissions.
****************************************************************************/
-bool can_write_to_file(connection_struct *conn,
- const struct smb_filename *smb_fname)
+bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
{
- return can_access_file_data(conn, smb_fname, FILE_WRITE_DATA);
+ return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA);
}
/****************************************************************************
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 1c27fef09b..adf664b396 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -57,7 +57,6 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n)
/* you can't read from print files */
if (fsp->print_file) {
- errno = EBADF;
return -1;
}
@@ -103,7 +102,7 @@ tryagain:
}
DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n",
- fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
+ fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
fsp->fh->pos += ret;
fsp->fh->position_information = fsp->fh->pos;
@@ -136,7 +135,7 @@ static ssize_t real_write_file(struct smb_request *req,
}
DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n",
- fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret));
+ fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret ));
if (ret != -1) {
fsp->fh->pos += ret;
@@ -164,31 +163,25 @@ static int wcp_file_size_change(files_struct *fsp)
wcp->file_size = wcp->offset + wcp->data_size;
ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size);
if (ret == -1) {
- DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f "
- "error %s\n", fsp_str_dbg(fsp),
- (double)wcp->file_size, strerror(errno)));
+ DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n",
+ fsp->fsp_name, (double)wcp->file_size, strerror(errno) ));
}
return ret;
}
-void update_write_time_handler(struct event_context *ctx,
+static void update_write_time_handler(struct event_context *ctx,
struct timed_event *te,
struct timeval now,
void *private_data)
{
files_struct *fsp = (files_struct *)private_data;
- DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp)));
-
- /* change the write time in the open file db. */
- (void)set_write_time(fsp->file_id, timespec_current());
-
- /* And notify. */
- notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name);
-
/* Remove the timed event handler. */
TALLOC_FREE(fsp->update_write_time_event);
+ DEBUG(5, ("Update write time on %s\n", fsp->fsp_name));
+
+ /* change the write time if not already changed by someone else */
+ update_write_time(fsp);
}
/*********************************************************
@@ -200,11 +193,6 @@ void trigger_write_time_update(struct files_struct *fsp)
{
int delay;
- if (fsp->posix_open) {
- /* Don't use delayed writes on POSIX files. */
- return;
- }
-
if (fsp->write_time_forced) {
/* No point - "sticky" write times
* in effect.
@@ -212,16 +200,11 @@ void trigger_write_time_update(struct files_struct *fsp)
return;
}
- /* We need to remember someone did a write
- * and update to current time on close. */
-
- fsp->update_write_time_on_close = true;
-
if (fsp->update_write_time_triggered) {
/*
- * We only update the write time after 2 seconds
- * on the first normal write. After that
- * no other writes affect this until close.
+ * We only update the write time
+ * on the first write. After that
+ * no other writes affect this.
*/
return;
}
@@ -231,10 +214,8 @@ void trigger_write_time_update(struct files_struct *fsp)
"smbd", "writetimeupdatedelay",
WRITE_TIME_UPDATE_USEC_DELAY);
- DEBUG(5, ("Update write time %d usec later on %s\n",
- delay, fsp_str_dbg(fsp)));
-
/* trigger the update 2 seconds later */
+ fsp->update_write_time_on_close = true;
fsp->update_write_time_event =
event_add_timed(smbd_event_context(), NULL,
timeval_current_ofs(0, delay),
@@ -243,13 +224,6 @@ void trigger_write_time_update(struct files_struct *fsp)
void trigger_write_time_update_immediate(struct files_struct *fsp)
{
- struct smb_file_time ft;
-
- if (fsp->posix_open) {
- /* Don't use delayed writes on POSIX files. */
- return;
- }
-
if (fsp->write_time_forced) {
/*
* No point - "sticky" write times
@@ -259,21 +233,12 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
}
TALLOC_FREE(fsp->update_write_time_event);
- DEBUG(5, ("Update write time immediate on %s\n",
- fsp_str_dbg(fsp)));
+ DEBUG(5, ("Update write time immediate on %s\n", fsp->fsp_name));
- /* After an immediate update, reset the trigger. */
fsp->update_write_time_triggered = true;
- fsp->update_write_time_on_close = false;
- ZERO_STRUCT(ft);
- ft.mtime = timespec_current();
-
- /* Update the time in the open file db. */
- (void)set_write_time(fsp->file_id, ft.mtime);
-
- /* Now set on disk - takes care of notify. */
- (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false);
+ fsp->update_write_time_on_close = false;
+ update_write_time(fsp);
}
/****************************************************************************
@@ -309,17 +274,20 @@ ssize_t write_file(struct smb_request *req,
}
if (!fsp->modified) {
+ SMB_STRUCT_STAT st;
fsp->modified = True;
- if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == 0) {
+ if (SMB_VFS_FSTAT(fsp, &st) == 0) {
int dosmode;
trigger_write_time_update(fsp);
- dosmode = dos_mode(fsp->conn, fsp->fsp_name);
+ dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
if ((lp_store_dos_attributes(SNUM(fsp->conn)) ||
MAP_ARCHIVE(fsp->conn)) &&
!IS_DOS_ARCHIVE(dosmode)) {
- file_set_dosmode(fsp->conn, fsp->fsp_name,
- dosmode | aARCH, NULL, false);
+ file_set_dosmode(fsp->conn,fsp->fsp_name,
+ dosmode | aARCH,&st,
+ NULL,
+ false);
}
/*
@@ -328,8 +296,7 @@ ssize_t write_file(struct smb_request *req,
*/
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) {
- setup_write_cache(fsp,
- fsp->fsp_name->st.st_ex_size);
+ setup_write_cache(fsp, st.st_size);
wcp = fsp->wcp;
}
}
@@ -394,10 +361,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
return total_written;
}
- DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f "
- "wcp->data_size=%u\n", fsp_str_dbg(fsp), fsp->fh->fd,
- (double)pos, (unsigned int)n, (double)wcp->offset,
- (unsigned int)wcp->data_size));
+ DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n",
+ fsp->fsp_name, fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size));
fsp->fh->pos = pos + n;
@@ -842,8 +807,7 @@ void delete_write_cache(files_struct *fsp)
SAFE_FREE(wcp->data);
SAFE_FREE(fsp->wcp);
- DEBUG(10,("delete_write_cache: File %s deleted write cache\n",
- fsp_str_dbg(fsp)));
+ DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name ));
}
/****************************************************************************
@@ -886,7 +850,7 @@ static bool setup_write_cache(files_struct *fsp, SMB_OFF_T file_size)
allocated_write_caches++;
DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n",
- fsp_str_dbg(fsp), (unsigned long)wcp->alloc_size));
+ fsp->fsp_name, (unsigned long)wcp->alloc_size ));
return True;
}
@@ -903,7 +867,7 @@ void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size)
char *msg;
if (asprintf(&msg, "set_filelen_write_cache: size change "
"on file %s with write cache size = %lu\n",
- fsp->fsp_name->base_name,
+ fsp->fsp_name,
(unsigned long)fsp->wcp->data_size) != -1) {
smb_panic(msg);
} else {
@@ -982,15 +946,11 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug
Perform a stat whether a valid fd or not.
************************************************************/
-int fsp_stat(files_struct *fsp)
+int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst)
{
if (fsp->fh->fd == -1) {
- if (fsp->posix_open) {
- return SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
- } else {
- return SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
- }
+ return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst);
} else {
- return SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
+ return SMB_VFS_FSTAT(fsp, pst);
}
}
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index ab79dfd926..e3acfc8483 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -29,7 +29,10 @@
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *orig_path,
- struct smb_filename *smb_fname);
+ const char *basepath,
+ const char *streamname,
+ SMB_STRUCT_STAT *pst,
+ char **path);
/****************************************************************************
Mangle the 2nd name and check if it is then equal to the first name.
@@ -80,28 +83,10 @@ static NTSTATUS determine_path_error(const char *name,
}
}
-static NTSTATUS check_for_dot_component(const struct smb_filename *smb_fname)
-{
- /* Ensure we catch all names with in "/."
- this is disallowed under Windows and
- in POSIX they've already been removed. */
- const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/
- if (p) {
- if (p[2] == '/') {
- /* Error code within a pathname. */
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- } else if (p[2] == '\0') {
- /* Error code at the end of a pathname. */
- return NT_STATUS_OBJECT_NAME_INVALID;
- }
- }
- return NT_STATUS_OK;
-}
-
/****************************************************************************
This routine is called to convert names from the dos namespace to unix
-namespace. It needs to handle any case conversions, mangling, format changes,
-streams etc.
+namespace. It needs to handle any case conversions, mangling, format
+changes etc.
We assume that we have already done a chdir() to the right "root" directory
for this service.
@@ -109,61 +94,55 @@ for this service.
The function will return an NTSTATUS error if some part of the name except for
the last part cannot be resolved, else NT_STATUS_OK.
-Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we
-didn't get any fatal errors that should immediately terminate the calling SMB
-processing whilst resolving.
+Note NT_STATUS_OK doesn't mean the name exists or is valid, just that we didn't
+get any fatal errors that should immediately terminate the calling
+SMB processing whilst resolving.
-If the UCF_SAVE_LCOMP flag is passed in, then the unmodified last component
-of the pathname is set in smb_filename->original_lcomp.
+If the saved_last_component != 0, then the unmodified last component
+of the pathname is returned there. If saved_last_component == 0 then nothing
+is returned there.
-If UCF_ALWAYS_ALLOW_WCARD_LCOMP is passed in, then a MS wildcard was detected
-and should be allowed in the last component of the path only.
+If last_component_wcard is true then a MS wildcard was detected and
+should be allowed in the last component of the path only.
-If the orig_path was a stream, smb_filename->base_name will point to the base
-filename, and smb_filename->stream_name will point to the stream name. If
-orig_path was not a stream, then smb_filename->stream_name will be NULL.
-
-On exit from unix_convert, the smb_filename->st stat struct will be populated
-if the file exists and was found, if not this stat struct will be filled with
-zeros (and this can be detected by checking for nlinks = 0, which can never be
-true for any file).
+On exit from unix_convert, if *pst was not null, then the file stat
+struct will be returned if the file exists and was found, if not this
+stat struct will be filled with zeros (and this can be detected by checking
+for nlinks = 0, which can never be true for any file).
****************************************************************************/
NTSTATUS unix_convert(TALLOC_CTX *ctx,
- connection_struct *conn,
- const char *orig_path,
- struct smb_filename **smb_fname_out,
- uint32_t ucf_flags)
+ connection_struct *conn,
+ const char *orig_path,
+ bool allow_wcard_last_component,
+ char **pp_conv_path,
+ char **pp_saved_last_component,
+ SMB_STRUCT_STAT *pst)
{
- struct smb_filename *smb_fname = NULL;
+ SMB_STRUCT_STAT st;
char *start, *end;
char *dirpath = NULL;
+ char *name = NULL;
char *stream = NULL;
bool component_was_mangled = False;
bool name_has_wildcard = False;
bool posix_pathnames = false;
- bool allow_wcard_last_component =
- (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
- bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
- NTSTATUS status;
+ NTSTATUS result;
int ret = -1;
- *smb_fname_out = NULL;
-
- smb_fname = talloc_zero(ctx, struct smb_filename);
- if (smb_fname == NULL) {
- return NT_STATUS_NO_MEMORY;
+ SET_STAT_INVALID(*pst);
+ *pp_conv_path = NULL;
+ if(pp_saved_last_component) {
+ *pp_saved_last_component = NULL;
}
if (conn->printer) {
/* we don't ever use the filenames on a printer share as a
filename - so don't convert them */
- if (!(smb_fname->base_name = talloc_strdup(smb_fname,
- orig_path))) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
+ return NT_STATUS_NO_MEMORY;
}
- goto done;
+ return NT_STATUS_OK;
}
DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));
@@ -191,16 +170,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (!*orig_path) {
- if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ if (!(name = talloc_strdup(ctx,"."))) {
+ return NT_STATUS_NO_MEMORY;
}
- if (SMB_VFS_STAT(conn, smb_fname) != 0) {
- status = map_nt_error_from_unix(errno);
- goto err;
+ if (SMB_VFS_STAT(conn,name,&st) == 0) {
+ *pst = st;
+ } else {
+ return map_nt_error_from_unix(errno);
}
- DEBUG(5, ("conversion finished \"\" -> %s\n",
- smb_fname->base_name));
+ DEBUG(5,("conversion finished \"\" -> %s\n",name));
goto done;
}
@@ -208,19 +186,17 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
orig_path[1] == '\0')) {
/* Start of pathname can't be "." only. */
if (orig_path[1] == '\0' || orig_path[2] == '\0') {
- status = NT_STATUS_OBJECT_NAME_INVALID;
+ result = NT_STATUS_OBJECT_NAME_INVALID;
} else {
- status =determine_path_error(&orig_path[2],
- allow_wcard_last_component);
+ result =determine_path_error(
+ &orig_path[2], allow_wcard_last_component);
}
- goto err;
+ return result;
}
- /* Start with the full orig_path as given by the caller. */
- if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) {
+ if (!(name = talloc_strdup(ctx, orig_path))) {
DEBUG(0, ("talloc_strdup failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
/*
@@ -234,69 +210,50 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if (conn->case_sensitive && !conn->case_preserve &&
!conn->short_case_preserve) {
- strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)));
+ strnorm(name, lp_defaultcase(SNUM(conn)));
}
/*
* Ensure saved_last_component is valid even if file exists.
*/
- if(save_last_component) {
- end = strrchr_m(smb_fname->base_name, '/');
+ if(pp_saved_last_component) {
+ end = strrchr_m(name, '/');
if (end) {
- smb_fname->original_lcomp = talloc_strdup(smb_fname,
- end + 1);
+ *pp_saved_last_component = talloc_strdup(ctx, end + 1);
} else {
- smb_fname->original_lcomp =
- talloc_strdup(smb_fname, smb_fname->base_name);
- }
- if (smb_fname->original_lcomp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ *pp_saved_last_component = talloc_strdup(ctx,
+ name);
}
}
- posix_pathnames = (lp_posix_pathnames() ||
- (ucf_flags & UCF_POSIX_PATHNAMES));
+ posix_pathnames = lp_posix_pathnames();
- /*
- * Strip off the stream, and add it back when we're done with the
- * base_name.
- */
if (!posix_pathnames) {
- stream = strchr_m(smb_fname->base_name, ':');
+ stream = strchr_m(name, ':');
if (stream != NULL) {
- char *tmp = talloc_strdup(smb_fname, stream);
+ char *tmp = talloc_strdup(ctx, stream);
if (tmp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ TALLOC_FREE(name);
+ return NT_STATUS_NO_MEMORY;
}
- /*
- * Since this is actually pointing into
- * smb_fname->base_name this truncates base_name.
- */
*stream = '\0';
stream = tmp;
}
}
- start = smb_fname->base_name;
+ start = name;
- /*
- * If we're providing case insentive semantics or
+ /* If we're providing case insentive semantics or
* the underlying filesystem is case insensitive,
* then a case-normalized hit in the stat-cache is
* authoratitive. JRA.
- *
- * Note: We're only checking base_name. The stream_name will be
- * added and verified in build_stream_path().
*/
- if((!conn->case_sensitive || !(conn->fs_capabilities &
- FILE_CASE_SENSITIVE_SEARCH)) &&
- stat_cache_lookup(conn, &smb_fname->base_name, &dirpath, &start,
- &smb_fname->st)) {
+ if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
+ stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
+ *pst = st;
goto done;
}
@@ -307,108 +264,53 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
DEBUG(0, ("talloc_strdup failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ TALLOC_FREE(name);
+ return NT_STATUS_NO_MEMORY;
}
/*
- * If we have a wildcard we must walk the path to
- * find where the error is, even if case sensitive
- * is true.
+ * stat the name - if it exists then we are all done!
*/
- name_has_wildcard = ms_has_wild(smb_fname->base_name);
- if (name_has_wildcard && !allow_wcard_last_component) {
- /* Wildcard not valid anywhere. */
- status = NT_STATUS_OBJECT_NAME_INVALID;
- goto fail;
+ if (posix_pathnames) {
+ ret = SMB_VFS_LSTAT(conn,name,&st);
+ } else {
+ ret = SMB_VFS_STAT(conn,name,&st);
}
- DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
- smb_fname->base_name, dirpath, start));
-
- if (!name_has_wildcard) {
- /*
- * stat the name - if it exists then we can add the stream back (if
- * there was one) and be done!
- */
-
- if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_STAT(conn, smb_fname);
- }
-
- if (ret == 0) {
- status = check_for_dot_component(smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
+ if (ret == 0) {
+ /* Ensure we catch all names with in "/."
+ this is disallowed under Windows. */
+ const char *p = strstr(name, "/."); /* mb safe. */
+ if (p) {
+ if (p[2] == '/') {
+ /* Error code within a pathname. */
+ result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ goto fail;
+ } else if (p[2] == '\0') {
+ /* Error code at the end of a pathname. */
+ result = NT_STATUS_OBJECT_NAME_INVALID;
goto fail;
}
- /* Add the path (not including the stream) to the cache. */
- stat_cache_add(orig_path, smb_fname->base_name,
- conn->case_sensitive);
- DEBUG(5,("conversion of base_name finished %s -> %s\n",
- orig_path, smb_fname->base_name));
- goto done;
}
+ stat_cache_add(orig_path, name, conn->case_sensitive);
+ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
+ *pst = st;
+ goto done;
+ }
- /*
- * A special case - if we don't have any wildcards or mangling chars and are case
- * sensitive or the underlying filesystem is case insentive then searching
- * won't help.
- */
-
- if ((conn->case_sensitive || !(conn->fs_capabilities &
- FILE_CASE_SENSITIVE_SEARCH)) &&
- !mangle_is_mangled(smb_fname->base_name, conn->params)) {
-
- status = check_for_dot_component(smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
+ DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
+ name, dirpath, start));
- /*
- * The stat failed. Could be ok as it could be
- * a new file.
- */
+ /*
+ * A special case - if we don't have any mangling chars and are case
+ * sensitive or the underlying filesystem is case insentive then searching
+ * won't help.
+ */
- if (errno == ENOTDIR || errno == ELOOP) {
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- goto fail;
- } else if (errno == ENOENT) {
- /*
- * Was it a missing last component ?
- * or a missing intermediate component ?
- */
- struct smb_filename parent_fname;
- ZERO_STRUCT(parent_fname);
- if (!parent_dirname(ctx, smb_fname->base_name,
- &parent_fname.base_name,
- NULL)) {
- status = NT_STATUS_NO_MEMORY;
- goto fail;
- }
- if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn, &parent_fname);
- } else {
- ret = SMB_VFS_STAT(conn, &parent_fname);
- }
- if (ret == -1) {
- if (errno == ENOTDIR ||
- errno == ENOENT ||
- errno == ELOOP) {
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- goto fail;
- }
- }
- /*
- * Missing last component is ok - new file.
- * Also deal with permission denied elsewhere.
- * Just drop out to done.
- */
- goto done;
- }
- }
+ if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
+ !mangle_is_mangled(name, conn->params)) {
+ goto done;
}
/*
@@ -444,14 +346,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*end = 0;
}
- if (save_last_component) {
- TALLOC_FREE(smb_fname->original_lcomp);
- smb_fname->original_lcomp = talloc_strdup(smb_fname,
+ if (pp_saved_last_component) {
+ TALLOC_FREE(*pp_saved_last_component);
+ *pp_saved_last_component = talloc_strdup(ctx,
end ? end + 1 : start);
- if (!smb_fname->original_lcomp) {
+ if (!*pp_saved_last_component) {
DEBUG(0, ("talloc failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
}
@@ -460,9 +361,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if (ISDOT(start)) {
if (!end) {
/* Error code at the end of a pathname. */
- status = NT_STATUS_OBJECT_NAME_INVALID;
+ result = NT_STATUS_OBJECT_NAME_INVALID;
} else {
- status = determine_path_error(end+1,
+ result = determine_path_error(end+1,
allow_wcard_last_component);
}
goto fail;
@@ -473,9 +374,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
name_has_wildcard = ms_has_wild(start);
+ /* Wildcard not valid anywhere. */
+ if (name_has_wildcard && !allow_wcard_last_component) {
+ result = NT_STATUS_OBJECT_NAME_INVALID;
+ goto fail;
+ }
+
/* Wildcards never valid within a pathname. */
if (name_has_wildcard && end) {
- status = NT_STATUS_OBJECT_NAME_INVALID;
+ result = NT_STATUS_OBJECT_NAME_INVALID;
goto fail;
}
@@ -484,9 +391,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ ret = SMB_VFS_LSTAT(conn,name, &st);
} else {
- ret = SMB_VFS_STAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn,name, &st);
}
if (ret == 0) {
@@ -494,7 +401,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* It exists. it must either be a directory or this must
* be the last part of the path for it to be OK.
*/
- if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (end && !(st.st_mode & S_IFDIR)) {
/*
* An intermediate part of the name isn't
* a directory.
@@ -509,15 +416,25 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* applications depend on the difference between
* these two errors.
*/
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
goto fail;
}
+ if (!end) {
+ /*
+ * We just scanned for, and found the end of
+ * the path. We must return the valid stat
+ * struct. JRA.
+ */
+
+ *pst = st;
+ }
+
} else {
char *found_name = NULL;
/* Stat failed - ensure we don't use it. */
- SET_STAT_INVALID(smb_fname->st);
+ SET_STAT_INVALID(st);
/*
* Reset errno so we can detect
@@ -563,11 +480,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
if (errno == ENOENT ||
errno == ENOTDIR ||
errno == ELOOP) {
- status =
+ result =
NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
else {
- status =
+ result =
map_nt_error_from_unix(errno);
}
goto fail;
@@ -588,10 +505,10 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (errno == ENOTDIR ||
errno == ELOOP) {
- status =
+ result =
NT_STATUS_OBJECT_PATH_NOT_FOUND;
} else {
- status =
+ result =
map_nt_error_from_unix(errno);
}
goto fail;
@@ -623,13 +540,12 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
&unmangled,
conn->params)) {
char *tmp;
- size_t start_ofs =
- start - smb_fname->base_name;
+ size_t start_ofs = start - name;
if (*dirpath != '\0') {
- tmp = talloc_asprintf(
- smb_fname, "%s/%s",
- dirpath, unmangled);
+ tmp = talloc_asprintf(ctx,
+ "%s/%s", dirpath,
+ unmangled);
TALLOC_FREE(unmangled);
}
else {
@@ -637,13 +553,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
}
if (tmp == NULL) {
DEBUG(0, ("talloc failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = tmp;
- start =
- smb_fname->base_name + start_ofs;
+ TALLOC_FREE(name);
+ name = tmp;
+ start = name + start_ofs;
end = start + strlen(start);
}
@@ -658,50 +572,46 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (end) {
char *tmp;
- size_t start_ofs =
- start - smb_fname->base_name;
+ size_t start_ofs = start - name;
if (*dirpath != '\0') {
- tmp = talloc_asprintf(smb_fname,
+ tmp = talloc_asprintf(ctx,
"%s/%s/%s", dirpath,
found_name, end+1);
}
else {
- tmp = talloc_asprintf(smb_fname,
+ tmp = talloc_asprintf(ctx,
"%s/%s", found_name,
end+1);
}
if (tmp == NULL) {
DEBUG(0, ("talloc_asprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = tmp;
- start = smb_fname->base_name + start_ofs;
+ TALLOC_FREE(name);
+ name = tmp;
+ start = name + start_ofs;
end = start + strlen(found_name);
*end = '\0';
} else {
char *tmp;
- size_t start_ofs =
- start - smb_fname->base_name;
+ size_t start_ofs = start - name;
if (*dirpath != '\0') {
- tmp = talloc_asprintf(smb_fname,
+ tmp = talloc_asprintf(ctx,
"%s/%s", dirpath,
found_name);
} else {
- tmp = talloc_strdup(smb_fname,
+ tmp = talloc_strdup(ctx,
found_name);
}
if (tmp == NULL) {
DEBUG(0, ("talloc failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = tmp;
- start = smb_fname->base_name + start_ofs;
+ TALLOC_FREE(name);
+ name = tmp;
+ start = name + start_ofs;
/*
* We just scanned for, and found the end of
@@ -710,13 +620,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
*/
if (posix_pathnames) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ ret = SMB_VFS_LSTAT(conn,name, &st);
} else {
- ret = SMB_VFS_STAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn,name, &st);
}
- if (ret != 0) {
- SET_STAT_INVALID(smb_fname->st);
+ if (ret == 0) {
+ *pst = st;
+ } else {
+ SET_STAT_INVALID(st);
}
}
@@ -729,13 +641,12 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
* We should never provide different behaviors
* depending on DEVELOPER!!!
*/
- if (VALID_STAT(smb_fname->st)) {
+ if (VALID_STAT(st)) {
bool delete_pending;
- get_file_infos(vfs_file_id_from_sbuf(conn,
- &smb_fname->st),
+ get_file_infos(vfs_file_id_from_sbuf(conn, &st),
&delete_pending, NULL);
if (delete_pending) {
- status = NT_STATUS_DELETE_PENDING;
+ result = NT_STATUS_DELETE_PENDING;
goto fail;
}
}
@@ -750,8 +661,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
"%s/%s", dirpath, start);
if (!tmp) {
DEBUG(0, ("talloc_asprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
TALLOC_FREE(dirpath);
dirpath = tmp;
@@ -760,15 +670,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
TALLOC_FREE(dirpath);
if (!(dirpath = talloc_strdup(ctx,start))) {
DEBUG(0, ("talloc_strdup failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
}
/*
- * Cache the dirpath thus far. Don't cache a name with mangled
- * or wildcard components as this can change the size.
+ * Don't cache a name with mangled or wildcard components
+ * as this can change the size.
*/
+
if(!component_was_mangled && !name_has_wildcard) {
stat_cache_add(orig_path, dirpath,
conn->case_sensitive);
@@ -783,56 +693,53 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
}
/*
- * Cache the full path. Don't cache a name with mangled or wildcard
- * components as this can change the size.
+ * Don't cache a name with mangled or wildcard components
+ * as this can change the size.
*/
if(!component_was_mangled && !name_has_wildcard) {
- stat_cache_add(orig_path, smb_fname->base_name,
- conn->case_sensitive);
+ stat_cache_add(orig_path, name, conn->case_sensitive);
}
/*
* The name has been resolved.
*/
- DEBUG(5,("conversion finished %s -> %s\n", orig_path,
- smb_fname->base_name));
+ DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
done:
- /* Add back the stream if one was stripped off originally. */
if (stream != NULL) {
- smb_fname->stream_name = stream;
+ char *tmp = NULL;
- /* Check path now that the base_name has been converted. */
- status = build_stream_path(ctx, conn, orig_path, smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
+ result = build_stream_path(ctx, conn, orig_path, name, stream,
+ pst, &tmp);
+ if (!NT_STATUS_IS_OK(result)) {
goto fail;
}
+
+ DEBUG(10, ("build_stream_path returned %s\n", tmp));
+
+ TALLOC_FREE(name);
+ name = tmp;
}
+ *pp_conv_path = name;
TALLOC_FREE(dirpath);
- *smb_fname_out = smb_fname;
return NT_STATUS_OK;
fail:
DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
if (*dirpath != '\0') {
- smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
- dirpath, start);
+ *pp_conv_path = talloc_asprintf(ctx,
+ "%s/%s", dirpath, start);
} else {
- smb_fname->base_name = talloc_strdup(smb_fname, start);
+ *pp_conv_path = talloc_strdup(ctx, start);
}
- if (!smb_fname->base_name) {
+ if (!*pp_conv_path) {
DEBUG(0, ("talloc_asprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- goto err;
+ return NT_STATUS_NO_MEMORY;
}
-
- *smb_fname_out = smb_fname;
+ TALLOC_FREE(name);
TALLOC_FREE(dirpath);
- return status;
- err:
- TALLOC_FREE(smb_fname);
- return status;
+ return result;
}
/****************************************************************************
@@ -893,8 +800,7 @@ static int get_real_filename_full_scan(connection_struct *conn,
TALLOC_CTX *mem_ctx, char **found_name)
{
struct smb_Dir *cur_dir;
- const char *dname = NULL;
- char *talloced = NULL;
+ const char *dname;
char *unmangled_name = NULL;
long curpos;
@@ -946,11 +852,10 @@ static int get_real_filename_full_scan(connection_struct *conn,
/* now scan for matching names */
curpos = 0;
- while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {
+ while ((dname = ReadDirName(cur_dir, &curpos, NULL))) {
/* Is it dot or dot dot. */
if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(talloced);
continue;
}
@@ -973,13 +878,10 @@ static int get_real_filename_full_scan(connection_struct *conn,
TALLOC_FREE(cur_dir);
if (!*found_name) {
errno = ENOMEM;
- TALLOC_FREE(talloced);
return -1;
}
- TALLOC_FREE(talloced);
return 0;
}
- TALLOC_FREE(talloced);
}
TALLOC_FREE(unmangled_name);
@@ -1026,29 +928,40 @@ int get_real_filename(connection_struct *conn, const char *path,
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *orig_path,
- struct smb_filename *smb_fname)
+ const char *basepath,
+ const char *streamname,
+ SMB_STRUCT_STAT *pst,
+ char **path)
{
+ SMB_STRUCT_STAT st;
+ char *result = NULL;
NTSTATUS status;
unsigned int i, num_streams;
struct stream_struct *streams = NULL;
- if (SMB_VFS_STAT(conn, smb_fname) == 0) {
- DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
+ result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
+ if (result == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (SMB_VFS_STAT(conn, result, &st) == 0) {
+ *pst = st;
+ *path = result;
return NT_STATUS_OK;
}
if (errno != ENOENT) {
- DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
status = map_nt_error_from_unix(errno);
+ DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
goto fail;
}
- /* Fall back to a case-insensitive scan of all streams on the file. */
- status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, mem_ctx,
+ status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
&num_streams, &streams);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
- SET_STAT_INVALID(smb_fname->st);
+ SET_STAT_INVALID(*pst);
+ *path = result;
return NT_STATUS_OK;
}
@@ -1059,8 +972,8 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
for (i=0; i<num_streams; i++) {
DEBUG(10, ("comparing [%s] and [%s]: ",
- smb_fname->stream_name, streams[i].name));
- if (fname_equal(smb_fname->stream_name, streams[i].name,
+ streamname, streams[i].name));
+ if (fname_equal(streamname, streams[i].name,
conn->case_sensitive)) {
DEBUGADD(10, ("equal\n"));
break;
@@ -1068,118 +981,33 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
DEBUGADD(10, ("not equal\n"));
}
- /* Couldn't find the stream. */
if (i == num_streams) {
- SET_STAT_INVALID(smb_fname->st);
+ SET_STAT_INVALID(*pst);
+ *path = result;
TALLOC_FREE(streams);
return NT_STATUS_OK;
}
- DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
- smb_fname->stream_name, streams[i].name));
+ TALLOC_FREE(result);
-
- TALLOC_FREE(smb_fname->stream_name);
- smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
- if (smb_fname->stream_name == NULL) {
+ result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
+ if (result == NULL) {
status = NT_STATUS_NO_MEMORY;
goto fail;
}
- SET_STAT_INVALID(smb_fname->st);
-
- if (SMB_VFS_STAT(conn, smb_fname) == 0) {
- DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
- }
- status = NT_STATUS_OK;
- fail:
- TALLOC_FREE(streams);
- return status;
-}
-
-/**
- * Go through all the steps to validate a filename.
- *
- * @param ctx talloc_ctx to allocate memory with.
- * @param conn connection struct for vfs calls.
- * @param dfs_path Whether this path requires dfs resolution.
- * @param name_in The unconverted name.
- * @param ucf_flags flags to pass through to unix_convert().
- * UCF_ALWAYS_ALLOW_WCARD_LCOMP will be OR'd in if
- * p_cont_wcard != NULL and is true and
- * UCF_COND_ALLOW_WCARD_LCOMP.
- * @param p_cont_wcard If not NULL, will be set to true if the dfs path
- * resolution detects a wildcard.
- * @param pp_smb_fname The final converted name will be allocated if the
- * return is NT_STATUS_OK.
- *
- * @return NT_STATUS_OK if all operations completed succesfully, appropriate
- * error otherwise.
- */
-NTSTATUS filename_convert(TALLOC_CTX *ctx,
- connection_struct *conn,
- bool dfs_path,
- const char *name_in,
- uint32_t ucf_flags,
- bool *ppath_contains_wcard,
- struct smb_filename **pp_smb_fname)
-{
- NTSTATUS status;
- char *fname = NULL;
-
- *pp_smb_fname = NULL;
-
- status = resolve_dfspath_wcard(ctx, conn,
- dfs_path,
- name_in,
- &fname,
- ppath_contains_wcard);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("filename_convert: resolve_dfspath failed "
- "for name %s with %s\n",
- name_in,
- nt_errstr(status) ));
- return status;
- }
-
- if (is_fake_file_path(name_in)) {
- SMB_STRUCT_STAT st;
- ZERO_STRUCT(st);
- st.st_ex_nlink = 1;
- status = create_synthetic_smb_fname_split(ctx,
- name_in,
- &st,
- pp_smb_fname);
- return status;
- }
+ SET_STAT_INVALID(*pst);
- /*
- * If the caller conditionally allows wildcard lookups, only add the
- * always allow if the path actually does contain a wildcard.
- */
- if (ucf_flags & UCF_COND_ALLOW_WCARD_LCOMP &&
- ppath_contains_wcard != NULL && *ppath_contains_wcard) {
- ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
+ if (SMB_VFS_STAT(conn, result, pst) == 0) {
+ stat_cache_add(orig_path, result, conn->case_sensitive);
}
- status = unix_convert(ctx, conn, fname, pp_smb_fname, ucf_flags);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10,("filename_convert: unix_convert failed "
- "for name %s with %s\n",
- fname,
- nt_errstr(status) ));
- return status;
- }
-
- status = check_name(conn, (*pp_smb_fname)->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("filename_convert: check_name failed "
- "for name %s with %s\n",
- smb_fname_str_dbg(*pp_smb_fname),
- nt_errstr(status) ));
- TALLOC_FREE(*pp_smb_fname);
- return status;
- }
+ *path = result;
+ TALLOC_FREE(streams);
+ return NT_STATUS_OK;
+ fail:
+ TALLOC_FREE(result);
+ TALLOC_FREE(streams);
return status;
}
diff --git a/source3/smbd/filename_util.c b/source3/smbd/filename_util.c
deleted file mode 100644
index aad8a08e2b..0000000000
--- a/source3/smbd/filename_util.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Filename utility functions.
- Copyright (C) Tim Prouty 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include "includes.h"
-
-/**
- * XXX: This is temporary and there should be no callers of this outside of
- * this file once smb_filename is plumbed through all path based operations.
- * The one legitimate caller currently is smb_fname_str_dbg(), which this
- * could be made static for.
- */
-NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
- const struct smb_filename *smb_fname,
- char **full_name)
-{
- if (smb_fname->stream_name) {
- /* stream_name must always be NULL if there is no stream. */
- SMB_ASSERT(smb_fname->stream_name[0] != '\0');
-
- *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
- smb_fname->stream_name);
- } else {
- *full_name = talloc_strdup(ctx, smb_fname->base_name);
- }
-
- if (!*full_name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-/**
- * There are actually legitimate callers of this such as functions that
- * enumerate streams using the SMB_VFS_STREAMINFO interface and then want to
- * operate on each stream.
- */
-NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
- const char *stream_name,
- const SMB_STRUCT_STAT *psbuf,
- struct smb_filename **smb_fname_out)
-{
- struct smb_filename smb_fname_loc;
-
- ZERO_STRUCT(smb_fname_loc);
-
- /* Setup the base_name/stream_name. */
- smb_fname_loc.base_name = CONST_DISCARD(char *, base_name);
- smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name);
-
- /* Copy the psbuf if one was given. */
- if (psbuf)
- smb_fname_loc.st = *psbuf;
-
- /* Let copy_smb_filename() do the heavy lifting. */
- return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out);
-}
-
-/**
- * XXX: This is temporary and there should be no callers of this once
- * smb_filename is plumbed through all path based operations.
- */
-NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
- const char *fname,
- const SMB_STRUCT_STAT *psbuf,
- struct smb_filename **smb_fname_out)
-{
- NTSTATUS status;
- const char *stream_name = NULL;
- char *base_name = NULL;
-
- if (!lp_posix_pathnames()) {
- stream_name = strchr_m(fname, ':');
- }
-
- /* Setup the base_name/stream_name. */
- if (stream_name) {
- base_name = talloc_strndup(ctx, fname,
- PTR_DIFF(stream_name, fname));
- } else {
- base_name = talloc_strdup(ctx, fname);
- }
-
- if (!base_name) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf,
- smb_fname_out);
- TALLOC_FREE(base_name);
- return status;
-}
-
-/**
- * Return a string using the talloc_tos()
- */
-const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
-{
- char *fname = NULL;
- NTSTATUS status;
-
- if (smb_fname == NULL) {
- return "";
- }
- status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
- if (!NT_STATUS_IS_OK(status)) {
- return "";
- }
- return fname;
-}
-
-/**
- * Return a debug string using the talloc_tos(). This can only be called from
- * DEBUG() macros due to the debut_ctx().
- */
-const char *fsp_str_dbg(const struct files_struct *fsp)
-{
- return smb_fname_str_dbg(fsp->fsp_name);
-}
-
-NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
- const struct smb_filename *smb_fname_in,
- struct smb_filename **smb_fname_out)
-{
- /* stream_name must always be NULL if there is no stream. */
- if (smb_fname_in->stream_name) {
- SMB_ASSERT(smb_fname_in->stream_name[0] != '\0');
- }
-
- *smb_fname_out = talloc_zero(ctx, struct smb_filename);
- if (*smb_fname_out == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (smb_fname_in->base_name) {
- (*smb_fname_out)->base_name =
- talloc_strdup(*smb_fname_out, smb_fname_in->base_name);
- if (!(*smb_fname_out)->base_name)
- goto no_mem_err;
- }
-
- if (smb_fname_in->stream_name) {
- (*smb_fname_out)->stream_name =
- talloc_strdup(*smb_fname_out, smb_fname_in->stream_name);
- if (!(*smb_fname_out)->stream_name)
- goto no_mem_err;
- }
-
- if (smb_fname_in->original_lcomp) {
- (*smb_fname_out)->original_lcomp =
- talloc_strdup(*smb_fname_out, smb_fname_in->original_lcomp);
- if (!(*smb_fname_out)->original_lcomp)
- goto no_mem_err;
- }
-
- (*smb_fname_out)->st = smb_fname_in->st;
- return NT_STATUS_OK;
-
- no_mem_err:
- TALLOC_FREE(*smb_fname_out);
- return NT_STATUS_NO_MEMORY;
-}
-
-/****************************************************************************
- Simple check to determine if the filename is a stream.
- ***************************************************************************/
-bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
-{
- /* stream_name must always be NULL if there is no stream. */
- if (smb_fname->stream_name) {
- SMB_ASSERT(smb_fname->stream_name[0] != '\0');
- }
-
- if (lp_posix_pathnames()) {
- return false;
- }
-
- return smb_fname->stream_name != NULL;
-}
-
-/****************************************************************************
- Returns true if the filename's stream == "::$DATA"
- ***************************************************************************/
-bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
-{
- if (!is_ntfs_stream_smb_fname(smb_fname)) {
- return false;
- }
-
- return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0;
-}
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 455666f8df..03d2f58271 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -44,7 +44,6 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
{
int i;
files_struct *fsp;
- NTSTATUS status;
/* we want to give out file handles differently on each new
connection because of a common bug in MS clients where they try to
@@ -66,26 +65,21 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
return NT_STATUS_TOO_MANY_OPENED_FILES;
}
- /*
- * Make a child of the connection_struct as an fsp can't exist
- * indepenedent of a connection.
- */
- fsp = talloc_zero(conn, struct files_struct);
+ fsp = SMB_MALLOC_P(files_struct);
if (!fsp) {
return NT_STATUS_NO_MEMORY;
}
- /*
- * This can't be a child of fsp because the file_handle can be ref'd
- * when doing a dos/fcb open, which will then share the file_handle
- * across multiple fsps.
- */
- fsp->fh = talloc_zero(conn, struct fd_handle);
+ ZERO_STRUCTP(fsp);
+
+ fsp->fh = SMB_MALLOC_P(struct fd_handle);
if (!fsp->fh) {
- TALLOC_FREE(fsp);
+ SAFE_FREE(fsp);
return NT_STATUS_NO_MEMORY;
}
+ ZERO_STRUCTP(fsp->fh);
+
fsp->fh->ref_count = 1;
fsp->fh->fd = -1;
@@ -101,18 +95,8 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
fsp->fnum = i + FILE_HANDLE_OFFSET;
SMB_ASSERT(fsp->fnum < 65536);
- /*
- * Create an smb_filename with "" for the base_name. There are very
- * few NULL checks, so make sure it's initialized with something. to
- * be safe until an audit can be done.
- */
- status = create_synthetic_smb_fname(fsp, "", NULL, NULL,
- &fsp->fsp_name);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(fsp);
- TALLOC_FREE(fsp->fh);
- }
-
+ string_set(&fsp->fsp_name,"");
+
DLIST_ADD(Files, fsp);
DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
@@ -250,9 +234,8 @@ void file_dump_open_table(void)
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next,count++) {
- DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, "
- "fileid=%s\n", count, fsp->fnum, fsp_str_dbg(fsp),
- fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
+ DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n",
+ count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
file_id_string_tos(&fsp->file_id)));
}
}
@@ -298,10 +281,8 @@ files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
if ((fsp->fh->fd == -1) &&
(fsp->oplock_type != NO_OPLOCK) &&
(fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
- DEBUG(0,("file_find_dif: file %s file_id = "
- "%s, gen = %u oplock_type = %u is a "
- "stat open with oplock type !\n",
- fsp_str_dbg(fsp),
+ DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \
+oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name,
file_id_string_tos(&fsp->file_id),
(unsigned int)fsp->fh->gen_id,
(unsigned int)fsp->oplock_type ));
@@ -402,12 +383,10 @@ bool file_find_subpath(files_struct *dir_fsp)
{
files_struct *fsp;
size_t dlen;
- char *d_fullname = NULL;
-
- d_fullname = talloc_asprintf(talloc_tos(), "%s/%s",
- dir_fsp->conn->connectpath,
- dir_fsp->fsp_name->base_name);
-
+ char *d_fullname = talloc_asprintf(talloc_tos(),
+ "%s/%s",
+ dir_fsp->conn->connectpath,
+ dir_fsp->fsp_name);
if (!d_fullname) {
return false;
}
@@ -424,9 +403,9 @@ bool file_find_subpath(files_struct *dir_fsp)
d1_fullname = talloc_asprintf(talloc_tos(),
"%s/%s",
fsp->conn->connectpath,
- fsp->fsp_name->base_name);
+ fsp->fsp_name);
- /*
+ /*
* If the open file has a path that is a longer
* component, then it's a subpath.
*/
@@ -467,19 +446,17 @@ void file_free(struct smb_request *req, files_struct *fsp)
{
DLIST_REMOVE(Files, fsp);
+ string_free(&fsp->fsp_name);
+
TALLOC_FREE(fsp->fake_file_handle);
if (fsp->fh->ref_count == 1) {
- TALLOC_FREE(fsp->fh);
+ SAFE_FREE(fsp->fh);
} else {
fsp->fh->ref_count--;
}
if (fsp->notify) {
- if (fsp->is_directory) {
- notify_remove_onelevel(fsp->conn->notify_ctx,
- &fsp->file_id, fsp);
- }
notify_remove(fsp->conn->notify_ctx, fsp);
TALLOC_FREE(fsp->notify);
}
@@ -516,8 +493,7 @@ void file_free(struct smb_request *req, files_struct *fsp)
information */
ZERO_STRUCTP(fsp);
- /* fsp->fsp_name is a talloc child and is free'd automatically. */
- TALLOC_FREE(fsp);
+ SAFE_FREE(fsp);
}
/****************************************************************************
@@ -563,11 +539,11 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid)
Duplicate the file handle part for a DOS or FCB open.
****************************************************************************/
-NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
+void dup_file_fsp(struct smb_request *req, files_struct *from,
uint32 access_mask, uint32 share_access,
uint32 create_options, files_struct *to)
{
- TALLOC_FREE(to->fh);
+ SAFE_FREE(to->fh);
to->fh = from->fh;
to->fh->ref_count++;
@@ -592,25 +568,5 @@ NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
to->modified = from->modified;
to->is_directory = from->is_directory;
to->aio_write_behind = from->aio_write_behind;
- return fsp_set_smb_fname(to, from->fsp_name);
-}
-
-/**
- * The only way that the fsp->fsp_name field should ever be set.
- */
-NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
- const struct smb_filename *smb_fname_in)
-{
- NTSTATUS status;
- struct smb_filename *smb_fname_new;
-
- status = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- TALLOC_FREE(fsp->fsp_name);
- fsp->fsp_name = smb_fname_new;
-
- return NT_STATUS_OK;
+ string_set(&to->fsp_name,from->fsp_name);
}
diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c
index 68fa795ba2..9e7d103562 100644
--- a/source3/smbd/globals.c
+++ b/source3/smbd/globals.c
@@ -43,9 +43,18 @@ bool blocking_lock_cancel_state = false;
struct smbd_dmapi_context *dmapi_ctx = NULL;
#endif
+connection_struct *Connections = NULL;
+/* number of open connections */
+struct bitmap *bmap = 0;
+int num_open = 0;
+
bool dfree_broken = false;
+struct bitmap *dptr_bmap = NULL;
+struct dptr_struct *dirptrs = NULL;
+int dirhandles_open = 0;
+
/* how many write cache buffers have been allocated */
unsigned int allocated_write_caches = 0;
@@ -84,9 +93,41 @@ char *last_to = NULL;
struct msg_state *smbd_msg_state = NULL;
+bool global_encrypted_passwords_negotiated = false;
+bool global_spnego_negotiated = false;
+struct auth_context *negprot_global_auth_context = NULL;
+bool done_negprot = false;
+
bool logged_ioctl_message = false;
+/* users from session setup */
+char *session_userlist = NULL;
+/* workgroup from session setup. */
+char *session_workgroup = NULL;
+/* this holds info on user ids that are already validated for this VC */
+user_struct *validated_users = NULL;
+uint16_t next_vuid = VUID_OFFSET;
+int num_validated_vuids = 0;
+#ifdef HAVE_NETGROUP
+char *my_yp_domain = NULL;
+#endif
+
+bool already_got_session = false;
+
+/*
+ * Size of data we can send to client. Set
+ * by the client for all protocols above CORE.
+ * Set by us for CORE protocol.
+ */
+int max_send = BUFFER_SIZE;
+/*
+ * Size of the data we can receive. Set by us.
+ * Can be modified by the max xmit parameter.
+ */
+int max_recv = BUFFER_SIZE;
+uint16 last_session_tag = UID_FIELD_INVALID;
int trans_num = 0;
+char *orig_inbuf = NULL;
pid_t mypid = 0;
time_t last_smb_conf_reload_time = 0;
time_t last_printer_reload_time = 0;
@@ -95,7 +136,7 @@ time_t last_printer_reload_time = 0;
for processing.
****************************************************************************/
struct pending_message_list *deferred_open_queue = NULL;
-uint32_t common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES|FLAGS2_EXTENDED_ATTRIBUTES;
+uint32_t common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx = NULL;
struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx = NULL;
@@ -113,6 +154,11 @@ uint16_t last_flags = 0;
struct db_context *session_db_ctx_ptr = NULL;
uint32_t global_client_caps = 0;
+bool done_sesssetup = false;
+/****************************************************************************
+ List to store partial SPNEGO auth fragments.
+****************************************************************************/
+struct pending_auth_data *pd_list = NULL;
uint16_t fnf_handle = 257;
@@ -130,6 +176,8 @@ int32_t level_II_oplocks_open = 0;
bool global_client_failed_oplock_break = false;
struct kernel_oplocks *koplocks = NULL;
+struct notify_mid_map *notify_changes_by_mid = NULL;
+
int am_parent = 1;
int server_fd = -1;
struct event_context *smbd_event_ctx = NULL;
@@ -149,9 +197,4 @@ void smbd_init_globals(void)
ZERO_STRUCT(conn_ctx_stack);
ZERO_STRUCT(sec_ctx_stack);
-
- smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
- if (!smbd_server_conn) {
- exit_server("failed to create smbd_server_connection");
- }
}
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 0db61f87a3..6ac92ed3dd 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -42,8 +42,18 @@ struct smbd_dmapi_context;
extern struct smbd_dmapi_context *dmapi_ctx;
#endif
+extern connection_struct *Connections;
+/* number of open connections */
+extern struct bitmap *bmap;
+extern int num_open;
+
extern bool dfree_broken;
+extern struct bitmap *dptr_bmap;
+//struct dptr_struct;
+extern struct dptr_struct *dirptrs;
+extern int dirhandles_open;
+
/* how many write cache buffers have been allocated */
extern unsigned int allocated_write_caches;
@@ -81,9 +91,41 @@ extern char *last_to;
struct msg_state;
extern struct msg_state *smbd_msg_state;
+extern bool global_encrypted_passwords_negotiated;
+extern bool global_spnego_negotiated;
+extern struct auth_context *negprot_global_auth_context;
+extern bool done_negprot;
+
extern bool logged_ioctl_message;
+/* users from session setup */
+extern char *session_userlist;
+/* workgroup from session setup. */
+extern char *session_workgroup;
+/* this holds info on user ids that are already validated for this VC */
+extern user_struct *validated_users;
+extern uint16_t next_vuid;
+extern int num_validated_vuids;
+#ifdef HAVE_NETGROUP
+extern char *my_yp_domain;
+#endif
+
+extern bool already_got_session;
+
+/*
+ * Size of data we can send to client. Set
+ * by the client for all protocols above CORE.
+ * Set by us for CORE protocol.
+ */
+extern int max_send;
+/*
+ * Size of the data we can receive. Set by us.
+ * Can be modified by the max xmit parameter.
+ */
+extern int max_recv;
+extern uint16 last_session_tag;
extern int trans_num;
+extern char *orig_inbuf;
extern pid_t mypid;
extern time_t last_smb_conf_reload_time;
@@ -117,6 +159,12 @@ extern uint16_t last_flags;
extern struct db_context *session_db_ctx_ptr;
extern uint32_t global_client_caps;
+extern bool done_sesssetup;
+/****************************************************************************
+ List to store partial SPNEGO auth fragments.
+****************************************************************************/
+struct pending_auth_data;
+extern struct pending_auth_data *pd_list;
extern uint16_t fnf_handle;
@@ -139,6 +187,8 @@ extern int32_t level_II_oplocks_open;
extern bool global_client_failed_oplock_break;
extern struct kernel_oplocks *koplocks;
+extern struct notify_mid_map *notify_changes_by_mid;
+
extern int am_parent;
extern int server_fd;
extern struct event_context *smbd_event_ctx;
@@ -149,368 +199,10 @@ struct child_pid;
extern struct child_pid *children;
extern int num_children;
-struct tstream_context;
-struct smbd_smb2_request;
-struct smbd_smb2_session;
-struct smbd_smb2_tcon;
-
-DATA_BLOB negprot_spnego(void);
-
-NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key,
- struct iovec *vector,
- int count);
-NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key,
- const struct iovec *vector,
- int count);
-
-struct smbd_lock_element {
- uint32_t smbpid;
- enum brl_type brltype;
- uint64_t offset;
- uint64_t count;
-};
-
-NTSTATUS smbd_do_locking(struct smb_request *req,
- files_struct *fsp,
- uint8_t type,
- int32_t timeout,
- uint16_t num_ulocks,
- struct smbd_lock_element *ulocks,
- uint16_t num_locks,
- struct smbd_lock_element *locks,
- bool *async);
-
-NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- files_struct *fsp,
- struct smb_filename *smb_fname,
- bool delete_pending,
- struct timespec write_time_ts,
- bool ms_dfs_link,
- struct ea_list *ea_list,
- int lock_data_count,
- char *lock_data,
- uint16_t flags2,
- unsigned int max_data_bytes,
- char **ppdata,
- unsigned int *pdata_size);
-
-NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
- struct smb_request *req,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- files_struct *fsp,
- struct smb_filename *smb_fname,
- char **ppdata, int total_data,
- int *ret_data_size);
-
-NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- uint16_t flags2,
- unsigned int max_data_bytes,
- char **ppdata,
- int *ret_data_len);
-
-bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
- struct dptr_struct *dirptr,
- const char *mask,
- uint32_t dirtype,
- bool dont_descend,
- bool ask_sharemode,
- bool (*match_fn)(TALLOC_CTX *ctx,
- void *private_data,
- const char *dname,
- const char *mask,
- char **_fname),
- bool (*mode_fn)(TALLOC_CTX *ctx,
- void *private_data,
- struct smb_filename *smb_fname,
- uint32_t *_mode),
- void *private_data,
- char **_fname,
- struct smb_filename **_smb_fname,
- uint32_t *_mode,
- long *_prev_offset);
-
-bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct dptr_struct *dirptr,
- uint16 flags2,
- const char *path_mask,
- uint32 dirtype,
- int info_level,
- int requires_resume_key,
- bool dont_descend,
- bool ask_sharemode,
- uint8_t align,
- bool do_pad,
- char **ppdata,
- char *base_data,
- char *end_data,
- int space_remaining,
- bool *out_of_space,
- bool *got_exact_match,
- int *_last_entry_off,
- struct ea_list *name_list);
-
-NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
- const struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t *access_granted);
-
-void smbd_notify_cancel_by_smbreq(struct smbd_server_connection *sconn,
- const struct smb_request *smbreq);
-
-void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
- const char *reason,
- const char *location);
-#define smbd_server_connection_terminate(sconn, reason) \
- smbd_server_connection_terminate_ex(sconn, reason, __location__)
-
-bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size);
-
-void reply_smb2002(struct smb_request *req, uint16_t choice);
-void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
- const uint8_t *inbuf, size_t size);
-
-NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
- NTSTATUS status,
- DATA_BLOB *info,
- const char *location);
-#define smbd_smb2_request_error(req, status) \
- smbd_smb2_request_error_ex(req, status, NULL, __location__)
-NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
- NTSTATUS status,
- DATA_BLOB body, DATA_BLOB *dyn,
- const char *location);
-#define smbd_smb2_request_done(req, body, dyn) \
- smbd_smb2_request_done_ex(req, NT_STATUS_OK, body, dyn, __location__)
-
-NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
- uint64_t file_id_persistent,
- uint64_t file_id_volatile,
- uint8_t oplock_level);
-
-NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
- struct tevent_req *subreq);
-
-NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req);
-
-struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req);
-
-NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_tcon(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_find(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req);
-NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req);
-
-struct smbd_smb2_request {
- struct smbd_smb2_request *prev, *next;
-
- TALLOC_CTX *mem_pool;
- struct smbd_smb2_request **parent;
-
- struct smbd_server_connection *sconn;
-
- /* the session the request operates on, maybe NULL */
- struct smbd_smb2_session *session;
-
- /* the tcon the request operates on, maybe NULL */
- struct smbd_smb2_tcon *tcon;
-
- int current_idx;
- bool do_signing;
-
- struct files_struct *compat_chain_fsp;
-
- NTSTATUS next_status;
-
- /*
- * The sub request for async backend calls.
- * This is used for SMB2 Cancel.
- */
- struct tevent_req *subreq;
-
- struct {
- /* the NBT header is not allocated */
- uint8_t nbt_hdr[4];
- /*
- * vector[0] NBT
- * .
- * vector[1] SMB2
- * vector[2] fixed body
- * vector[3] dynamic body
- * .
- * .
- * .
- * vector[4] SMB2
- * vector[5] fixed body
- * vector[6] dynamic body
- * .
- * .
- * .
- */
- struct iovec *vector;
- int vector_count;
- } in;
- struct {
- /* the NBT header is not allocated */
- uint8_t nbt_hdr[4];
- /*
- * vector[0] NBT
- * .
- * vector[1] SMB2
- * vector[2] fixed body
- * vector[3] dynamic body
- * .
- * .
- * .
- * vector[4] SMB2
- * vector[5] fixed body
- * vector[6] dynamic body
- * .
- * .
- * .
- */
- struct iovec *vector;
- int vector_count;
- } out;
-};
-
-struct smbd_server_connection;
-
-struct smbd_smb2_session {
- struct smbd_smb2_session *prev, *next;
- struct smbd_server_connection *sconn;
- NTSTATUS status;
- uint64_t vuid;
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state;
- struct auth_serversupplied_info *server_info;
- DATA_BLOB session_key;
- bool do_signing;
-
- user_struct *compat_vuser;
-
- struct {
- /* an id tree used to allocate tids */
- struct idr_context *idtree;
-
- /* this is the limit of tid values for this connection */
- uint32_t limit;
-
- struct smbd_smb2_tcon *list;
- } tcons;
-};
-
-struct smbd_smb2_tcon {
- struct smbd_smb2_tcon *prev, *next;
- struct smbd_smb2_session *session;
- uint32_t tid;
- int snum;
- connection_struct *compat_conn;
-};
-
-struct pending_auth_data;
-
struct smbd_server_connection {
- struct {
- bool got_session;
- } nbt;
- bool allow_smb2;
- struct {
- struct fd_event *fde;
- uint64_t num_requests;
- struct {
- bool encrypted_passwords;
- bool spnego;
- struct auth_context *auth_context;
- bool done;
- /*
- * Size of the data we can receive. Set by us.
- * Can be modified by the max xmit parameter.
- */
- int max_recv;
- } negprot;
-
- struct {
- bool done_sesssetup;
- /*
- * Size of data we can send to client. Set
- * by the client for all protocols above CORE.
- * Set by us for CORE protocol.
- */
- int max_send;
- uint16_t last_session_tag;
-
- /* users from session setup */
- char *session_userlist;
- /* workgroup from session setup. */
- char *session_workgroup;
- /*
- * this holds info on user ids that are already
- * validated for this VC
- */
- user_struct *validated_users;
- uint16_t next_vuid;
- int num_validated_vuids;
-#ifdef HAVE_NETGROUP
- char *my_yp_domain;
-#endif
- } sessions;
- struct {
- connection_struct *Connections;
- /* number of open connections */
- struct bitmap *bmap;
- int num_open;
- } tcons;
- struct smb_signing_state *signing_state;
- /* List to store partial SPNEGO auth fragments. */
- struct pending_auth_data *pd_list;
-
- struct notify_mid_map *notify_mid_maps;
-
- struct {
- struct bitmap *dptr_bmap;
- struct dptr_struct *dirptrs;
- int dirhandles_open;
- } searches;
- } smb1;
- struct {
- struct tevent_context *event_ctx;
- struct tevent_queue *recv_queue;
- struct tevent_queue *send_queue;
- struct tstream_context *stream;
- struct {
- /* an id tree used to allocate vuids */
- /* this holds info on session vuids that are already
- * validated for this VC */
- struct idr_context *idtree;
-
- /* this is the limit of vuid values for this connection */
- uint64_t limit;
-
- struct smbd_smb2_session *list;
- } sessions;
- struct smbd_smb2_request *requests;
- } smb2;
+ struct fd_event *fde;
+ uint64_t num_requests;
};
-
extern struct smbd_server_connection *smbd_server_conn;
void smbd_init_globals(void);
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 97b338a536..2cf0038985 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -93,8 +93,6 @@ void send_trans_reply(connection_struct *conn,
int ldata = rdata ? rdata_len : 0;
int lparam = rparam ? rparam_len : 0;
- struct smbd_server_connection *sconn = smbd_server_conn;
- int max_send = sconn->smb1.sessions.max_send;
if (buffer_too_large)
DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
@@ -136,7 +134,6 @@ void send_trans_reply(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn), &req->pcd)) {
exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
}
@@ -196,7 +193,6 @@ void send_trans_reply(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn), &req->pcd))
exit_server_cleanly("send_trans_reply: srv_send_smb "
"failed.");
@@ -303,7 +299,6 @@ static void api_dcerpc_cmd_write_done(struct tevent_req *subreq)
send:
if (!srv_send_smb(
smbd_server_fd(), (char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn) || req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -330,7 +325,6 @@ static void api_dcerpc_cmd_read_done(struct tevent_req *subreq)
reply_nterror(req, status);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)
||req->encrypted, &req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb "
@@ -457,7 +451,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid,
}
DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n",
- subcommand, fsp_str_dbg(fsp), pnum));
+ subcommand, fsp->fsp_name, pnum));
DEBUG(10, ("api_fd_reply: p:%p max_trans_reply: %d\n", fsp, mdrcnt));
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 7b01968a1f..40b6acae9f 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -26,9 +26,6 @@
*/
#include "includes.h"
-#include "smbd/globals.h"
-#include "../librpc/gen_ndr/cli_samr.h"
-#include "../librpc/gen_ndr/srv_samr.h"
#include "../lib/util/binsearch.h"
#ifdef CHECK_TYPES
@@ -649,16 +646,18 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
{
int i;
fstring location;
- struct spoolss_DriverInfo8 *driver = NULL;
+ NT_PRINTER_DRIVER_INFO_LEVEL driver;
NT_PRINTER_INFO_LEVEL *printer = NULL;
+ ZERO_STRUCT(driver);
+
if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
lp_servicename(snum)));
goto err;
}
- if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
+ if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
"Windows 4.0", 0)) )
{
DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
@@ -666,38 +665,38 @@ static void fill_printq_info_52(connection_struct *conn, int snum,
goto err;
}
- trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
- trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
- trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
+ trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
+ trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
+ trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
PACKI(desc, "W", 0x0400); /* don't know */
- PACKS(desc, "z", driver->driver_name); /* long printer name */
- PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
- PACKS(desc, "z", driver->data_file); /* Datafile name */
- PACKS(desc, "z", driver->monitor_name); /* language monitor */
+ PACKS(desc, "z", driver.info_3->name); /* long printer name */
+ PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
+ PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
+ PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
standard_sub_basic( "", "", location, sizeof(location)-1 );
PACKS(desc,"z", location); /* share to retrieve files */
- PACKS(desc,"z", driver->default_datatype); /* default data type */
- PACKS(desc,"z", driver->help_file); /* helpfile name */
- PACKS(desc,"z", driver->driver_path); /* driver name */
+ PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
+ PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
+ PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
- DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
- DEBUG(3,("Driver: %s:\n",driver->driver_path));
- DEBUG(3,("Data File: %s:\n",driver->data_file));
- DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
+ DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
+ DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
+ DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
+ DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
DEBUG(3,("Driver Location: %s:\n",location));
- DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
- DEBUG(3,("Help File: %s:\n",driver->help_file));
+ DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
+ DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
PACKI(desc,"N",count); /* number of files to copy */
- for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
+ for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
{
- trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
- PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
- DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
+ trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
+ PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
+ DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
}
/* sanity check */
@@ -718,7 +717,8 @@ done:
if ( printer )
free_a_printer( &printer, 2 );
- free_a_printer_driver(driver);
+ if ( driver.info_3 )
+ free_a_printer_driver( driver, 3 );
}
@@ -807,7 +807,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
static int get_printerdrivernumber(int snum)
{
int result = 0;
- struct spoolss_DriverInfo8 *driver;
+ NT_PRINTER_DRIVER_INFO_LEVEL driver;
NT_PRINTER_INFO_LEVEL *printer = NULL;
ZERO_STRUCT(driver);
@@ -818,7 +818,7 @@ static int get_printerdrivernumber(int snum)
goto done;
}
- if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
+ if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
"Windows 4.0", 0)) )
{
DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
@@ -827,13 +827,15 @@ static int get_printerdrivernumber(int snum)
}
/* count the number of files */
- while (driver->dependent_files && *driver->dependent_files[result])
- result++;
+ while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
+ result++;
+ \
done:
if ( printer )
free_a_printer( &printer, 2 );
- free_a_printer_driver(driver);
+ if ( driver.info_3 )
+ free_a_printer_driver( driver, 3 );
return result;
}
@@ -1780,9 +1782,7 @@ static bool check_share_info(int uLevel, char* id)
}
break;
case 1:
- /* Level-2 descriptor is allowed (and ignored) */
- if (strcmp(id,"B13BWz") != 0 &&
- strcmp(id,"B13BWzWWWzB9B") != 0) {
+ if (strcmp(id,"B13BWz") != 0) {
return False;
}
break;
@@ -2885,7 +2885,6 @@ static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
fstring user;
char *p = get_safe_str_ptr(param,tpscnt,param,2);
*rparam_len = 2;
@@ -2943,7 +2942,7 @@ static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
* function.
*/
- (void)map_username(sconn, user);
+ (void)map_username(user);
if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
SSVAL(*rparam,0,NERR_Success);
@@ -3665,7 +3664,6 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
char *str2 = skip_string(param,tpscnt,str1);
char *UserName = skip_string(param,tpscnt,str2);
@@ -3678,7 +3676,7 @@ static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
/* get NIS home of a previously validated user - simeon */
/* With share level security vuid will always be zero.
Don't depend on vuser being non-null !!. JRA */
- user_struct *vuser = get_valid_user_struct(sconn, vuid);
+ user_struct *vuser = get_valid_user_struct(vuid);
if(vuser != NULL) {
DEBUG(3,(" Username of UID %d is %s\n",
(int)vuser->server_info->utok.uid,
@@ -3921,7 +3919,6 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
char *str2 = skip_string(param,tpscnt,str1);
char *p = skip_string(param,tpscnt,str2);
@@ -3930,7 +3927,7 @@ static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
char* name;
/* With share level security vuid will always be zero.
Don't depend on vuser being non-null !!. JRA */
- user_struct *vuser = get_valid_user_struct(sconn, vuid);
+ user_struct *vuser = get_valid_user_struct(vuid);
if (!str1 || !str2 || !p) {
return False;
@@ -4870,7 +4867,6 @@ void api_reply(connection_struct *conn, uint16 vuid,
int tdscnt, int tpscnt,
int mdrcnt, int mprcnt)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
int api_command;
char *rdata = NULL;
char *rparam = NULL;
@@ -4919,7 +4915,7 @@ void api_reply(connection_struct *conn, uint16 vuid,
/* Check whether this api call can be done anonymously */
if (api_commands[i].auth_user && lp_restrict_anonymous()) {
- user_struct *user = get_valid_user_struct(sconn, vuid);
+ user_struct *user = get_valid_user_struct(vuid);
if (!user || user->server_info->guest) {
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c
index d1af0994a8..11ccbee3e6 100644
--- a/source3/smbd/mangle_hash.c
+++ b/source3/smbd/mangle_hash.c
@@ -290,15 +290,15 @@ static bool is_8_3(const char *fname, bool check_case, bool allow_wildcards,
if (strlen(f) > 12)
return False;
- if (!push_ucs2_talloc(NULL, &ucs2name, f, &size)) {
- DEBUG(0,("is_8_3: internal error push_ucs2_talloc() failed!\n"));
+ if (!push_ucs2_allocate(&ucs2name, f, &size)) {
+ DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
goto done;
}
ret = is_8_3_w(ucs2name, allow_wildcards);
done:
- TALLOC_FREE(ucs2name);
+ SAFE_FREE(ucs2name);
if (!NT_STATUS_IS_OK(ret)) {
return False;
@@ -618,12 +618,12 @@ static bool must_mangle(const char *name,
magic_char = lp_magicchar(p);
- if (!push_ucs2_talloc(NULL, &name_ucs2, name, &converted_size)) {
- DEBUG(0, ("push_ucs2_talloc failed!\n"));
+ if (!push_ucs2_allocate(&name_ucs2, name, &converted_size)) {
+ DEBUG(0, ("push_ucs2_allocate failed!\n"));
return False;
}
status = is_valid_name(name_ucs2, False, False);
- TALLOC_FREE(name_ucs2);
+ SAFE_FREE(name_ucs2);
/* We return true if we *must* mangle, so if it's
* a valid name (status == OK) then we must return
* false. Bug #6939. */
@@ -660,20 +660,20 @@ static bool hash_name_to_8_3(const char *in,
DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in,
cache83 ? "True" : "False"));
- if (!push_ucs2_talloc(NULL, &in_ucs2, in, &converted_size)) {
- DEBUG(0, ("push_ucs2_talloc failed!\n"));
+ if (!push_ucs2_allocate(&in_ucs2, in, &converted_size)) {
+ DEBUG(0, ("push_ucs2_allocate failed!\n"));
return False;
}
/* If it's already 8.3, just copy. */
if (NT_STATUS_IS_OK(is_valid_name(in_ucs2, False, False)) &&
NT_STATUS_IS_OK(is_8_3_w(in_ucs2, False))) {
- TALLOC_FREE(in_ucs2);
+ SAFE_FREE(in_ucs2);
safe_strcpy(out, in, 12);
return True;
}
- TALLOC_FREE(in_ucs2);
+ SAFE_FREE(in_ucs2);
if (!to_8_3(magic_char, in, out, default_case)) {
return False;
}
diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c
index 24b4ddd271..fde2a3c4d3 100644
--- a/source3/smbd/map_username.c
+++ b/source3/smbd/map_username.c
@@ -68,7 +68,7 @@ static bool set_last_from_to(const char *from, const char *to)
return true;
}
-bool map_username(struct smbd_server_connection *sconn, fstring user)
+bool map_username(fstring user)
{
XFILE *f;
char *mapfile = lp_username_map();
@@ -184,7 +184,7 @@ bool map_username(struct smbd_server_connection *sconn, fstring user)
}
if (strchr_m(dosname,'*') ||
- user_in_list(sconn, user, (const char **)dosuserlist)) {
+ user_in_list(user, (const char **)dosuserlist)) {
DEBUG(3,("Mapped user %s to %s\n",user,unixname));
mapped_user = True;
diff --git a/source3/smbd/message.c b/source3/smbd/message.c
index 82b3dc30a2..dbc833f091 100644
--- a/source3/smbd/message.c
+++ b/source3/smbd/message.c
@@ -59,7 +59,7 @@ static void msg_deliver(struct msg_state *state)
if (!name) {
goto done;
}
- fd = mkstemp(name);
+ fd = smb_mkstemp(name);
if (fd == -1) {
DEBUG(1, ("can't open message file %s: %s\n", name,
@@ -145,7 +145,7 @@ void reply_sends(struct smb_request *req)
START_PROFILE(SMBsends);
if (!(*lp_msg_command())) {
- reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ reply_doserror(req, ERRSRV, ERRmsgoff);
END_PROFILE(SMBsends);
return;
}
@@ -193,7 +193,7 @@ void reply_sendstrt(struct smb_request *req)
START_PROFILE(SMBsendstrt);
if (!(*lp_msg_command())) {
- reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ reply_doserror(req, ERRSRV, ERRmsgoff);
END_PROFILE(SMBsendstrt);
return;
}
@@ -240,7 +240,7 @@ void reply_sendtxt(struct smb_request *req)
START_PROFILE(SMBsendtxt);
if (! (*lp_msg_command())) {
- reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ reply_doserror(req, ERRSRV, ERRmsgoff);
END_PROFILE(SMBsendtxt);
return;
}
@@ -288,7 +288,7 @@ void reply_sendend(struct smb_request *req)
START_PROFILE(SMBsendend);
if (! (*lp_msg_command())) {
- reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
+ reply_doserror(req, ERRSRV, ERRmsgoff);
END_PROFILE(SMBsendend);
return;
}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index dcef75e094..efbc05ceb0 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -268,11 +268,11 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
if (!smbd_vfs_init(conn)) {
NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n"));
- conn_free(conn);
+ conn_free_internal(conn);
return status;
}
- conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
+ conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
/*
* Windows seems to insist on doing trans2getdfsreferral() calls on
@@ -284,7 +284,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
if (oldcwd == NULL) {
NTSTATUS status = map_nt_error_from_unix(errno);
DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno)));
- conn_free(conn);
+ conn_free_internal(conn);
return status;
}
@@ -293,7 +293,7 @@ NTSTATUS create_conn_struct(TALLOC_CTX *ctx,
DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. "
"Error was %s\n",
conn->connectpath, strerror(errno) ));
- conn_free(conn);
+ conn_free_internal(conn);
return status;
}
@@ -411,6 +411,7 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
char **pp_link_target,
SMB_STRUCT_STAT *sbufp)
{
+ SMB_STRUCT_STAT st;
int referral_len = 0;
#if defined(HAVE_BROKEN_READLINK)
char link_target_buf[PATH_MAX];
@@ -419,7 +420,6 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
#endif
size_t bufsize = 0;
char *link_target = NULL;
- struct smb_filename smb_fname;
if (pp_link_target) {
bufsize = 1024;
@@ -433,22 +433,21 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx,
link_target = link_target_buf;
}
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = discard_const_p(char, path);
+ if (sbufp == NULL) {
+ sbufp = &st;
+ }
- if (SMB_VFS_LSTAT(conn, &smb_fname) != 0) {
+ if (SMB_VFS_LSTAT(conn, path, sbufp) != 0) {
DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n",
path));
goto err;
}
- if (!S_ISLNK(smb_fname.st.st_ex_mode)) {
+
+ if (!S_ISLNK(sbufp->st_mode)) {
DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n",
path));
goto err;
}
- if (sbufp != NULL) {
- *sbufp = smb_fname.st;
- }
referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1);
if (referral_len == -1) {
@@ -516,8 +515,9 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
{
char *p = NULL;
char *q = NULL;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
- struct smb_filename *smb_fname = NULL;
+ char *localpath = NULL;
char *canon_dfspath = NULL; /* Canonicalized dfs path. (only '/'
components). */
@@ -536,32 +536,20 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
* think this is needed. JRA.
*/
- status = unix_convert(ctx, conn, pdp->reqpath, &smb_fname,
- search_flag ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0);
-
- if (!NT_STATUS_IS_OK(status)) {
- if (!NT_STATUS_EQUAL(status,
- NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
- return status;
- }
-
- /* Create an smb_fname to use below. */
- status = create_synthetic_smb_fname(ctx, pdp->reqpath, NULL,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = unix_convert(ctx, conn, pdp->reqpath, search_flag, &localpath,
+ NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
+ return status;
}
/* Optimization - check if we can redirect the whole path. */
- if (is_msdfs_link_internal(ctx, conn, smb_fname->base_name,
- pp_targetpath, NULL)) {
+ if (is_msdfs_link_internal(ctx, conn, localpath, pp_targetpath, NULL)) {
if (search_flag) {
DEBUG(6,("dfs_path_lookup (FindFirst) No redirection "
"for dfs link %s.\n", dfspath));
- status = NT_STATUS_OK;
- goto out;
+ return NT_STATUS_OK;
}
DEBUG(6,("dfs_path_lookup: %s resolves to a "
@@ -571,8 +559,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
if (consumedcntp) {
*consumedcntp = strlen(dfspath);
}
- status = NT_STATUS_PATH_NOT_COVERED;
- goto out;
+ return NT_STATUS_PATH_NOT_COVERED;
}
/* Prepare to test only for '/' components in the given path,
@@ -581,8 +568,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
canon_dfspath = talloc_strdup(ctx, dfspath);
if (!canon_dfspath) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ return NT_STATUS_NO_MEMORY;
}
if (!pdp->posix_path) {
string_replace(canon_dfspath, '\\', '/');
@@ -604,7 +590,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
* DFS path. If we hit a DFS link then we're done.
*/
- p = strrchr_m(smb_fname->base_name, '/');
+ p = strrchr_m(localpath, '/');
if (consumedcntp) {
q = strrchr_m(canon_dfspath, '/');
}
@@ -616,11 +602,9 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
}
if (is_msdfs_link_internal(ctx, conn,
- smb_fname->base_name, pp_targetpath,
- NULL)) {
+ localpath, pp_targetpath, NULL)) {
DEBUG(4, ("dfs_path_lookup: Redirecting %s because "
- "parent %s is dfs link\n", dfspath,
- smb_fname_str_dbg(smb_fname)));
+ "parent %s is dfs link\n", dfspath, localpath));
if (consumedcntp) {
*consumedcntp = strlen(canon_dfspath);
@@ -630,12 +614,11 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
*consumedcntp));
}
- status = NT_STATUS_PATH_NOT_COVERED;
- goto out;
+ return NT_STATUS_PATH_NOT_COVERED;
}
/* Step back on the filesystem. */
- p = strrchr_m(smb_fname->base_name, '/');
+ p = strrchr_m(localpath, '/');
if (consumedcntp) {
/* And in the canonicalized dfs path. */
@@ -643,10 +626,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx,
}
}
- status = NT_STATUS_OK;
- out:
- TALLOC_FREE(smb_fname);
- return status;
+ return NT_STATUS_OK;
}
/*****************************************************************
@@ -932,7 +912,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
DEBUG(3,("get_referred_path: No valid referrals for path %s\n",
dfs_path));
vfs_ChDir(conn, oldpath);
- conn_free(conn);
+ conn_free_internal(conn);
TALLOC_FREE(pdp);
return status;
}
@@ -944,13 +924,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,
DEBUG(3,("get_referred_path: failed to parse symlink "
"target %s\n", targetpath ));
vfs_ChDir(conn, oldpath);
- conn_free(conn);
+ conn_free_internal(conn);
TALLOC_FREE(pdp);
return NT_STATUS_NOT_FOUND;
}
vfs_ChDir(conn, oldpath);
- conn_free(conn);
+ conn_free_internal(conn);
TALLOC_FREE(pdp);
return NT_STATUS_OK;
}
@@ -1367,7 +1347,7 @@ static bool junction_to_local_path(const struct junction_map *jucn,
jucn->volume_name);
if (!*pp_path_out) {
vfs_ChDir(*conn_out, *oldpath);
- conn_free(*conn_out);
+ conn_free_internal(*conn_out);
return False;
}
return True;
@@ -1426,22 +1406,9 @@ bool create_msdfs_link(const struct junction_map *jucn)
if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) {
if (errno == EEXIST) {
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
- status = create_synthetic_smb_fname(talloc_tos(), path,
- NULL, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
+ if(SMB_VFS_UNLINK(conn,path)!=0) {
goto out;
}
-
- if(SMB_VFS_UNLINK(conn, smb_fname)!=0) {
- TALLOC_FREE(smb_fname);
- goto out;
- }
- TALLOC_FREE(smb_fname);
}
if (SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) {
DEBUG(1,("create_msdfs_link: symlink failed "
@@ -1455,7 +1422,7 @@ bool create_msdfs_link(const struct junction_map *jucn)
out:
vfs_ChDir(conn, cwd);
- conn_free(conn);
+ conn_free_internal(conn);
return ret;
}
@@ -1465,28 +1432,17 @@ bool remove_msdfs_link(const struct junction_map *jucn)
char *cwd;
connection_struct *conn;
bool ret = False;
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
if (!junction_to_local_path(jucn, &path, &conn, &cwd)) {
return false;
}
- status = create_synthetic_smb_fname(talloc_tos(), path,
- NULL, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return false;
- }
-
- if( SMB_VFS_UNLINK(conn, smb_fname) == 0 ) {
+ if( SMB_VFS_UNLINK(conn, path) == 0 ) {
ret = True;
}
- TALLOC_FREE(smb_fname);
vfs_ChDir(conn, cwd);
- conn_free(conn);
+ conn_free_internal(conn);
return ret;
}
@@ -1498,8 +1454,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
{
size_t cnt = 0;
SMB_STRUCT_DIR *dirp = NULL;
- const char *dname = NULL;
- char *talloced = NULL;
+ char *dname = NULL;
const char *connect_path = lp_pathname(snum);
const char *msdfs_proxy = lp_msdfs_proxy(snum);
connection_struct *conn;
@@ -1536,21 +1491,19 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum)
goto out;
}
- while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
- != NULL) {
+ while ((dname = vfs_readdirname(conn, dirp, NULL)) != NULL) {
if (is_msdfs_link(conn,
dname,
NULL)) {
cnt++;
}
- TALLOC_FREE(talloced);
}
SMB_VFS_CLOSEDIR(conn,dirp);
out:
vfs_ChDir(conn, cwd);
- conn_free(conn);
+ conn_free_internal(conn);
return cnt;
}
@@ -1564,8 +1517,7 @@ static int form_junctions(TALLOC_CTX *ctx,
{
size_t cnt = 0;
SMB_STRUCT_DIR *dirp = NULL;
- const char *dname = NULL;
- char *talloced = NULL;
+ char *dname = NULL;
const char *connect_path = lp_pathname(snum);
char *service_name = lp_servicename(snum);
const char *msdfs_proxy = lp_msdfs_proxy(snum);
@@ -1639,13 +1591,11 @@ static int form_junctions(TALLOC_CTX *ctx,
goto out;
}
- while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced))
- != NULL) {
+ while ((dname = vfs_readdirname(conn, dirp, NULL)) != NULL) {
char *link_target = NULL;
if (cnt >= jn_remain) {
DEBUG(2, ("form_junctions: ran out of MSDFS "
"junction slots"));
- TALLOC_FREE(talloced);
goto out;
}
if (is_msdfs_link_internal(ctx,
@@ -1663,7 +1613,6 @@ static int form_junctions(TALLOC_CTX *ctx,
dname);
if (!jucn[cnt].service_name ||
!jucn[cnt].volume_name) {
- TALLOC_FREE(talloced);
goto out;
}
jucn[cnt].comment = "";
@@ -1671,7 +1620,6 @@ static int form_junctions(TALLOC_CTX *ctx,
}
TALLOC_FREE(link_target);
}
- TALLOC_FREE(talloced);
}
out:
@@ -1681,7 +1629,7 @@ out:
}
vfs_ChDir(conn, cwd);
- conn_free(conn);
+ conn_free_internal(conn);
return cnt;
}
@@ -1729,9 +1677,40 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn)
}
/******************************************************************************
- Core function to resolve a dfs pathname possibly containing a wildcard. If
- ppath_contains_wcard != NULL, it will be set to true if a wildcard is
- detected during dfs resolution.
+ Core function to resolve a dfs pathname.
+******************************************************************************/
+
+NTSTATUS resolve_dfspath(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ bool dfs_pathnames,
+ const char *name_in,
+ char **pp_name_out)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ bool dummy;
+ if (dfs_pathnames) {
+ status = dfs_redirect(ctx,
+ conn,
+ name_in,
+ False,
+ pp_name_out,
+ &dummy);
+ } else {
+ /*
+ * Cheat and just return a copy of the in ptr.
+ * Once srvstr_get_path() uses talloc it'll
+ * be a talloced ptr anyway.
+ */
+ *pp_name_out = CONST_DISCARD(char *,name_in);
+ }
+ return status;
+}
+
+/******************************************************************************
+ Core function to resolve a dfs pathname possibly containing a wildcard.
+ This function is identical to the above except for the bool param to
+ dfs_redirect but I need this to be separate so it's really clear when
+ we're allowing wildcards and when we're not. JRA.
******************************************************************************/
NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx,
@@ -1741,20 +1720,14 @@ NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx,
char **pp_name_out,
bool *ppath_contains_wcard)
{
- bool path_contains_wcard;
NTSTATUS status = NT_STATUS_OK;
-
if (dfs_pathnames) {
status = dfs_redirect(ctx,
conn,
name_in,
True,
pp_name_out,
- &path_contains_wcard);
-
- if (NT_STATUS_IS_OK(status) && ppath_contains_wcard != NULL) {
- *ppath_contains_wcard = path_contains_wcard;
- }
+ ppath_contains_wcard);
} else {
/*
* Cheat and just return a copy of the in ptr.
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 81d29d90f9..a921954c49 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -20,35 +20,29 @@
#include "includes.h"
#include "smbd/globals.h"
-#include "../libcli/auth/spnego.h"
extern fstring remote_proto;
+extern enum protocol_types Protocol;
static void get_challenge(uint8 buff[8])
{
NTSTATUS nt_status;
- struct smbd_server_connection *sconn = smbd_server_conn;
/* We might be called more than once, multiple negprots are
* permitted */
- if (sconn->smb1.negprot.auth_context) {
- DEBUG(3, ("get challenge: is this a secondary negprot? "
- "sconn->negprot.auth_context is non-NULL!\n"));
- sconn->smb1.negprot.auth_context->free(
- &sconn->smb1.negprot.auth_context);
+ if (negprot_global_auth_context) {
+ DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
+ (negprot_global_auth_context->free)(&negprot_global_auth_context);
}
DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
- nt_status = make_auth_context_subsystem(
- &sconn->smb1.negprot.auth_context);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(0, ("make_auth_context_subsystem returned %s",
- nt_errstr(nt_status)));
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
+ DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
smb_panic("cannot make_negprot_global_auth_context!");
}
DEBUG(10, ("get challenge: getting challenge\n"));
- sconn->smb1.negprot.auth_context->get_ntlm_challenge(
- sconn->smb1.negprot.auth_context, buff);
+ negprot_global_auth_context->get_ntlm_challenge(
+ negprot_global_auth_context, buff);
}
/****************************************************************************
@@ -60,7 +54,7 @@ static void reply_corep(struct smb_request *req, uint16 choice)
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf, smb_vwv0, choice);
- set_Protocol(PROTOCOL_CORE);
+ Protocol = PROTOCOL_CORE;
}
/****************************************************************************
@@ -80,7 +74,7 @@ static void reply_coreplus(struct smb_request *req, uint16 choice)
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
* encrypt */
- set_Protocol(PROTOCOL_COREPLUS);
+ Protocol = PROTOCOL_COREPLUS;
}
/****************************************************************************
@@ -92,32 +86,29 @@ static void reply_lanman1(struct smb_request *req, uint16 choice)
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
time_t t = time(NULL);
- struct smbd_server_connection *sconn = smbd_server_conn;
- sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
- if (lp_security()>=SEC_USER) {
+ if (lp_security()>=SEC_USER)
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- }
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated)
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- }
- reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
+ reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
SSVAL(req->outbuf,smb_vwv0,choice);
SSVAL(req->outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated) {
get_challenge((uint8 *)smb_buf(req->outbuf));
SSVAL(req->outbuf,smb_vwv11, 8);
}
- set_Protocol(PROTOCOL_LANMAN1);
+ Protocol = PROTOCOL_LANMAN1;
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
+ SSVAL(req->outbuf,smb_vwv2,max_recv);
SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
SSVAL(req->outbuf,smb_vwv4,1);
SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
@@ -139,34 +130,31 @@ static void reply_lanman2(struct smb_request *req, uint16 choice)
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
time_t t = time(NULL);
- struct smbd_server_connection *sconn = smbd_server_conn;
- sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
- if (lp_security()>=SEC_USER) {
+ if (lp_security()>=SEC_USER)
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- }
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated)
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- }
- reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
+ reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
SSVAL(req->outbuf,smb_vwv0,choice);
SSVAL(req->outbuf,smb_vwv1,secword);
SIVAL(req->outbuf,smb_vwv6,sys_getpid());
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated) {
get_challenge((uint8 *)smb_buf(req->outbuf));
SSVAL(req->outbuf,smb_vwv11, 8);
}
- set_Protocol(PROTOCOL_LANMAN2);
+ Protocol = PROTOCOL_LANMAN2;
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
+ SSVAL(req->outbuf,smb_vwv2,max_recv);
SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
SSVAL(req->outbuf,smb_vwv4,1);
SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
@@ -178,7 +166,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice)
Generate the spnego negprot reply blob. Return the number of bytes used.
****************************************************************************/
-DATA_BLOB negprot_spnego(void)
+static DATA_BLOB negprot_spnego(void)
{
DATA_BLOB blob;
nstring dos_name;
@@ -192,9 +180,8 @@ DATA_BLOB negprot_spnego(void)
OID_NTLMSSP,
NULL};
const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
- struct smbd_server_connection *sconn = smbd_server_conn;
- sconn->smb1.negprot.spnego = true;
+ global_spnego_negotiated = True;
memset(guid, '\0', sizeof(guid));
@@ -263,9 +250,8 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
bool negotiate_spnego = False;
time_t t = time(NULL);
ssize_t ret;
- struct smbd_server_connection *sconn = smbd_server_conn;
- sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
/* Check the flags field to see if this is Vista.
WinXP sets it and Vista does not. But we have to
@@ -284,7 +270,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
/* do spnego in user level security if the client
supports it and we can do encrypted passwords */
- if (sconn->smb1.negprot.encrypted_passwords &&
+ if (global_encrypted_passwords_negotiated &&
(lp_security() != SEC_SHARE) &&
lp_use_spnego() &&
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
@@ -318,13 +304,11 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
if (lp_host_msdfs())
capabilities |= CAP_DFS;
- if (lp_security() >= SEC_USER) {
+ if (lp_security() >= SEC_USER)
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- }
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated)
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- }
-
+
if (lp_server_signing()) {
if (lp_security() >= SEC_USER) {
secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
@@ -332,7 +316,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
capabilities &= ~CAP_RAW_MODE;
if (lp_server_signing() == Required)
secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
- srv_set_signing_negotiated(smbd_server_conn);
+ srv_set_signing_negotiated();
} else {
DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
if (lp_server_signing() == Required) {
@@ -344,12 +328,11 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
SSVAL(req->outbuf,smb_vwv0,choice);
SCVAL(req->outbuf,smb_vwv1,secword);
- set_Protocol(PROTOCOL_NT1);
+ Protocol = PROTOCOL_NT1;
SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
- SIVAL(req->outbuf,smb_vwv3+1,
- sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
+ SIVAL(req->outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
@@ -359,7 +342,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
p = q = smb_buf(req->outbuf);
if (!negotiate_spnego) {
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated) {
uint8 chal[8];
/* note that we do not send a challenge at all if
we are using plaintext */
@@ -498,7 +481,6 @@ static const struct {
void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
int protocol_level;
} supported_protocols[] = {
- {"SMB 2.002", "SMB2", reply_smb2002, PROTOCOL_SMB2},
{"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
{"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
{"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
@@ -528,15 +510,14 @@ void reply_negprot(struct smb_request *req)
char **cliprotos;
int i;
size_t converted_size;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBnegprot);
- if (sconn->smb1.negprot.done) {
+ if (done_negprot) {
END_PROFILE(SMBnegprot);
exit_server_cleanly("multiple negprot's are not permitted");
}
- sconn->smb1.negprot.done = true;
+ done_negprot = True;
if (req->buflen == 0) {
DEBUG(0, ("negprot got no protocols\n"));
@@ -697,7 +678,7 @@ void reply_negprot(struct smb_request *req)
DEBUG( 5, ( "negprot index=%d\n", choice ) );
- if ((lp_server_signing() == Required) && (get_Protocol() < PROTOCOL_NT1)) {
+ if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
exit_server_cleanly("SMB signing is required and "
"client negotiated a downlevel protocol");
}
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 0c75769594..059101cc5b 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -28,9 +28,6 @@ struct notify_change_request {
struct smb_request *req;
uint32 filter;
uint32 max_param;
- void (*reply_fn)(struct smb_request *req,
- NTSTATUS error_code,
- uint8_t *buf, size_t len);
struct notify_mid_map *mid_map;
void *backend_data;
};
@@ -67,10 +64,6 @@ static bool notify_marshall_changes(int num_changes,
int i;
UNISTR uni_name;
- if (num_changes == -1) {
- return false;
- }
-
uni_name.buffer = NULL;
for (i=0; i<num_changes; i++) {
@@ -88,7 +81,7 @@ static bool notify_marshall_changes(int num_changes,
c = &changes[i];
- if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE,
+ if (!convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE,
c->name, strlen(c->name)+1, &uni_name.buffer,
&namelen, True) || (uni_name.buffer == NULL)) {
goto fail;
@@ -116,7 +109,7 @@ static bool notify_marshall_changes(int num_changes,
*/
prs_set_offset(ps, prs_offset(ps)-2);
- TALLOC_FREE(uni_name.buffer);
+ SAFE_FREE(uni_name.buffer);
if (prs_offset(ps) > max_offset) {
/* Too much data for client. */
@@ -130,7 +123,7 @@ static bool notify_marshall_changes(int num_changes,
return True;
fail:
- TALLOC_FREE(uni_name.buffer);
+ SAFE_FREE(uni_name.buffer);
return False;
}
@@ -138,24 +131,35 @@ static bool notify_marshall_changes(int num_changes,
Setup the common parts of the return packet and send it.
*****************************************************************************/
-void change_notify_reply(connection_struct *conn,
- struct smb_request *req,
- NTSTATUS error_code,
- uint32_t max_param,
- struct notify_change_buf *notify_buf,
- void (*reply_fn)(struct smb_request *req,
- NTSTATUS error_code,
- uint8_t *buf, size_t len))
+static void change_notify_reply_packet(connection_struct *conn,
+ struct smb_request *req,
+ NTSTATUS error_code)
{
- prs_struct ps;
+ reply_outbuf(req, 18, 0);
if (!NT_STATUS_IS_OK(error_code)) {
- reply_fn(req, error_code, NULL, 0);
- return;
+ error_packet_set((char *)req->outbuf, 0, 0, error_code,
+ __LINE__,__FILE__);
}
- if (max_param == 0 || notify_buf == NULL) {
- reply_fn(req, NT_STATUS_OK, NULL, 0);
+ show_msg((char *)req->outbuf);
+ if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ req->encrypted, &req->pcd)) {
+ exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
+ "failed.");
+ }
+ TALLOC_FREE(req->outbuf);
+}
+
+void change_notify_reply(connection_struct *conn,
+ struct smb_request *req, uint32 max_param,
+ struct notify_change_buf *notify_buf)
+{
+ prs_struct ps;
+
+ if (notify_buf->num_changes == -1) {
+ change_notify_reply_packet(conn, req, NT_STATUS_OK);
+ notify_buf->num_changes = 0;
return;
}
@@ -167,12 +171,14 @@ void change_notify_reply(connection_struct *conn,
* We exceed what the client is willing to accept. Send
* nothing.
*/
- prs_mem_free(&ps);
- prs_init_empty(&ps, NULL, MARSHALL);
+ change_notify_reply_packet(conn, req, NT_STATUS_OK);
+ goto done;
}
- reply_fn(req, NT_STATUS_OK, (uint8_t *)prs_data_p(&ps), prs_offset(&ps));
+ send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps),
+ prs_offset(&ps), NULL, 0);
+ done:
prs_mem_free(&ps);
TALLOC_FREE(notify_buf->changes);
@@ -182,7 +188,7 @@ void change_notify_reply(connection_struct *conn,
static void notify_callback(void *private_data, const struct notify_event *e)
{
files_struct *fsp = (files_struct *)private_data;
- DEBUG(10, ("notify_callback called for %s\n", fsp_str_dbg(fsp)));
+ DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name));
notify_fsp(fsp, e->action, e->path);
}
@@ -200,9 +206,8 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
return NT_STATUS_NO_MEMORY;
}
- /* Do notify operations on the base_name. */
if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath,
- fsp->fsp_name->base_name) == -1) {
+ fsp->fsp_name) == -1) {
DEBUG(0, ("asprintf failed\n"));
TALLOC_FREE(fsp->notify);
return NT_STATUS_NO_MEMORY;
@@ -227,17 +232,13 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
NTSTATUS change_notify_add_request(struct smb_request *req,
uint32 max_param,
uint32 filter, bool recursive,
- struct files_struct *fsp,
- void (*reply_fn)(struct smb_request *req,
- NTSTATUS error_code,
- uint8_t *buf, size_t len))
+ struct files_struct *fsp)
{
struct notify_change_request *request = NULL;
struct notify_mid_map *map = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
DEBUG(10, ("change_notify_add_request: Adding request for %s: "
- "max_param = %d\n", fsp_str_dbg(fsp), (int)max_param));
+ "max_param = %d\n", fsp->fsp_name, (int)max_param));
if (!(request = talloc(NULL, struct notify_change_request))
|| !(map = talloc(request, struct notify_mid_map))) {
@@ -252,14 +253,16 @@ NTSTATUS change_notify_add_request(struct smb_request *req,
request->max_param = max_param;
request->filter = filter;
request->fsp = fsp;
- request->reply_fn = reply_fn;
request->backend_data = NULL;
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
map->mid = request->req->mid;
- DLIST_ADD(sconn->smb1.notify_mid_maps, map);
+ DLIST_ADD(notify_changes_by_mid, map);
+
+ /* Push the MID of this packet on the signing queue. */
+ srv_defer_sign_response(request->req->mid);
return NT_STATUS_OK;
}
@@ -268,7 +271,6 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
{
files_struct *fsp;
struct notify_change_request *req;
- struct smbd_server_connection *sconn = smbd_server_conn;
/*
* Paranoia checks, the fsp referenced must must have the request in
@@ -289,7 +291,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
}
DLIST_REMOVE(fsp->notify->requests, req);
- DLIST_REMOVE(sconn->smb1.notify_mid_maps, req->mid_map);
+ DLIST_REMOVE(notify_changes_by_mid, req->mid_map);
TALLOC_FREE(req);
}
@@ -300,9 +302,8 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
void remove_pending_change_notify_requests_by_mid(uint16 mid)
{
struct notify_mid_map *map;
- struct smbd_server_connection *sconn = smbd_server_conn;
- for (map = sconn->smb1.notify_mid_maps; map; map = map->next) {
+ for (map = notify_changes_by_mid; map; map = map->next) {
if (map->mid == mid) {
break;
}
@@ -312,28 +313,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid)
return;
}
- change_notify_reply(map->req->fsp->conn, map->req->req,
- NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
- change_notify_remove_request(map->req);
-}
-
-void smbd_notify_cancel_by_smbreq(struct smbd_server_connection *sconn,
- const struct smb_request *smbreq)
-{
- struct notify_mid_map *map;
-
- for (map = sconn->smb1.notify_mid_maps; map; map = map->next) {
- if (map->req->req == smbreq) {
- break;
- }
- }
-
- if (map == NULL) {
- return;
- }
-
- change_notify_reply(map->req->fsp->conn, map->req->req,
- NT_STATUS_CANCELLED, 0, NULL, map->req->reply_fn);
+ change_notify_reply_packet(map->req->fsp->conn, map->req->req,
+ NT_STATUS_CANCELLED);
change_notify_remove_request(map->req);
}
@@ -349,9 +330,8 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp,
}
while (fsp->notify->requests != NULL) {
- change_notify_reply(fsp->conn, fsp->notify->requests->req,
- status, 0, NULL,
- fsp->notify->requests->reply_fn);
+ change_notify_reply_packet(
+ fsp->conn, fsp->notify->requests->req, status);
change_notify_remove_request(fsp->notify->requests);
}
}
@@ -360,33 +340,17 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
const char *path)
{
char *fullpath;
- char *parent;
- const char *name;
if (path[0] == '.' && path[1] == '/') {
path += 2;
}
- if (parent_dirname(talloc_tos(), path, &parent, &name)) {
- struct smb_filename smb_fname_parent;
-
- ZERO_STRUCT(smb_fname_parent);
- smb_fname_parent.base_name = parent;
-
- if (SMB_VFS_STAT(conn, &smb_fname_parent) != -1) {
- notify_onelevel(conn->notify_ctx, action, filter,
- SMB_VFS_FILE_ID_CREATE(conn, &smb_fname_parent.st),
- name);
- }
- }
-
- fullpath = talloc_asprintf(talloc_tos(), "%s/%s", conn->connectpath,
- path);
- if (fullpath == NULL) {
+ if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) {
DEBUG(0, ("asprintf failed\n"));
return;
}
+
notify_trigger(conn->notify_ctx, action, filter, fullpath);
- TALLOC_FREE(fullpath);
+ SAFE_FREE(fullpath);
}
static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
@@ -419,10 +383,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
if (fsp->notify->requests != NULL) {
change_notify_reply(fsp->conn,
fsp->notify->requests->req,
- NT_STATUS_OK,
fsp->notify->requests->max_param,
- fsp->notify,
- fsp->notify->requests->reply_fn);
+ fsp->notify);
change_notify_remove_request(fsp->notify->requests);
}
return;
@@ -480,10 +442,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
change_notify_reply(fsp->conn,
fsp->notify->requests->req,
- NT_STATUS_OK,
fsp->notify->requests->max_param,
- fsp->notify,
- fsp->notify->requests->reply_fn);
+ fsp->notify);
change_notify_remove_request(fsp->notify->requests);
}
diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c
index 61599456c6..a12c0a6e7c 100644
--- a/source3/smbd/notify_inotify.c
+++ b/source3/smbd/notify_inotify.c
@@ -2,17 +2,17 @@
Unix SMB/CIFS implementation.
Copyright (C) Andrew Tridgell 2006
-
+
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 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -142,12 +142,12 @@ static bool filter_match(struct inotify_watch_context *w,
return True;
}
-
+
/*
dispatch one inotify event
-
+
the cookies are used to correctly handle renames
*/
static void inotify_dispatch(struct inotify_private *in,
@@ -211,7 +211,7 @@ static void inotify_dispatch(struct inotify_private *in,
ne.action = NOTIFY_ACTION_MODIFIED;
e->mask = IN_ATTRIB;
-
+
for (w=in->watches;w;w=next) {
next = w->next;
if (w->wd == e->wd && filter_match(w, e) &&
@@ -242,7 +242,6 @@ static void inotify_handler(struct event_context *ev, struct fd_event *fde,
if (ioctl(in->fd, FIONREAD, &bufsize) != 0 ||
bufsize == 0) {
DEBUG(0,("No data on inotify fd?!\n"));
- TALLOC_FREE(fde);
return;
}
@@ -303,7 +302,7 @@ static NTSTATUS inotify_setup(struct sys_notify_context *ctx)
/* add a event waiting for the inotify fd to be readable */
event_add_fd(ctx->ev, in, in->fd, EVENT_FD_READ, inotify_handler, in);
-
+
return NT_STATUS_OK;
}
@@ -357,7 +356,7 @@ static int watch_destructor(struct inotify_watch_context *w)
DEBUG(1, ("inotify_rm_watch returned %s\n",
strerror(errno)));
}
-
+
}
return 0;
}
@@ -438,7 +437,7 @@ NTSTATUS inotify_watch(struct sys_notify_context *ctx,
/* the caller frees the handle to stop watching */
talloc_set_destructor(w, watch_destructor);
-
+
return NT_STATUS_OK;
}
diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c
index 1850e2b57f..06da717799 100644
--- a/source3/smbd/notify_internal.c
+++ b/source3/smbd/notify_internal.c
@@ -2,17 +2,17 @@
Unix SMB/CIFS implementation.
Copyright (C) Andrew Tridgell 2006
-
+
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 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -27,8 +27,7 @@
#include "librpc/gen_ndr/ndr_notify.h"
struct notify_context {
- struct db_context *db_recursive;
- struct db_context *db_onelevel;
+ struct db_context *db;
struct server_id server;
struct messaging_context *messaging_ctx;
struct notify_list *list;
@@ -92,18 +91,10 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
return NULL;
}
- notify->db_recursive = db_open(notify, lock_path("notify.tdb"),
- 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
- O_RDWR|O_CREAT, 0644);
- if (notify->db_recursive == NULL) {
- talloc_free(notify);
- return NULL;
- }
-
- notify->db_onelevel = db_open(notify, lock_path("notify_onelevel.tdb"),
- 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
- O_RDWR|O_CREAT, 0644);
- if (notify->db_onelevel == NULL) {
+ notify->db = db_open(notify, lock_path("notify.tdb"),
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ O_RDWR|O_CREAT, 0644);
+ if (notify->db == NULL) {
talloc_free(notify);
return NULL;
}
@@ -112,8 +103,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
notify->messaging_ctx = messaging_ctx;
notify->list = NULL;
notify->array = NULL;
- notify->seqnum = notify->db_recursive->get_seqnum(
- notify->db_recursive);
+ notify->seqnum = notify->db->get_seqnum(notify->db);
notify->key = string_term_tdb_data(NOTIFY_KEY);
talloc_set_destructor(notify, notify_destructor);
@@ -133,8 +123,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
*/
static NTSTATUS notify_fetch_locked(struct notify_context *notify, struct db_record **rec)
{
- *rec = notify->db_recursive->fetch_locked(notify->db_recursive,
- notify, notify->key);
+ *rec = notify->db->fetch_locked(notify->db, notify, notify->key);
if (*rec == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -151,7 +140,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
NTSTATUS status;
int seqnum;
- seqnum = notify->db_recursive->get_seqnum(notify->db_recursive);
+ seqnum = notify->db->get_seqnum(notify->db);
if (seqnum == notify->seqnum && notify->array != NULL) {
return NT_STATUS_OK;
@@ -164,8 +153,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
NT_STATUS_HAVE_NO_MEMORY(notify->array);
if (!rec) {
- if (notify->db_recursive->fetch(notify->db_recursive, notify,
- notify->key, &dbuf) != 0) {
+ if (notify->db->fetch(notify->db, notify, notify->key, &dbuf) != 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
} else {
@@ -356,96 +344,6 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record
}
/*
- Add a non-recursive watch
-*/
-
-static void notify_add_onelevel(struct notify_context *notify,
- struct notify_entry *e, void *private_data)
-{
- struct notify_entry_array *array;
- struct db_record *rec;
- DATA_BLOB blob;
- TDB_DATA dbuf;
- enum ndr_err_code ndr_err;
- NTSTATUS status;
-
- array = talloc_zero(talloc_tos(), struct notify_entry_array);
- if (array == NULL) {
- return;
- }
-
- rec = notify->db_onelevel->fetch_locked(
- notify->db_onelevel, talloc_tos(),
- make_tdb_data((uint8_t *)&e->dir_id, sizeof(e->dir_id)));
- if (rec == NULL) {
- DEBUG(10, ("notify_add_onelevel: fetch_locked for %s failed"
- "\n", file_id_string_tos(&e->dir_id)));
- TALLOC_FREE(array);
- return;
- }
-
- blob.data = (uint8_t *)rec->value.dptr;
- blob.length = rec->value.dsize;
-
- if (blob.length > 0) {
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
- (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
- ndr_errstr(ndr_err)));
- TALLOC_FREE(array);
- return;
- }
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_add_onelevel:\n"));
- NDR_PRINT_DEBUG(notify_entry_array, array);
- }
- }
-
- array->entries = talloc_realloc(array, array->entries,
- struct notify_entry,
- array->num_entries+1);
- if (array->entries == NULL) {
- TALLOC_FREE(array);
- return;
- }
- array->entries[array->num_entries] = *e;
- array->entries[array->num_entries].private_data = private_data;
- array->entries[array->num_entries].server = notify->server;
- array->num_entries += 1;
-
- ndr_err = ndr_push_struct_blob(
- &blob, rec, NULL, array,
- (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
- ndr_errstr(ndr_err)));
- TALLOC_FREE(array);
- return;
- }
-
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_add_onelevel:\n"));
- NDR_PRINT_DEBUG(notify_entry_array, array);
- }
-
- dbuf.dptr = blob.data;
- dbuf.dsize = blob.length;
-
- status = rec->store(rec, dbuf, TDB_REPLACE);
- TALLOC_FREE(array);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("notify_add_onelevel: store failed: %s\n",
- nt_errstr(status)));
- return;
- }
- e->filter = 0;
- return;
-}
-
-
-/*
add a notify watch. This is called when a notify is first setup on a open
directory handle.
*/
@@ -513,11 +411,6 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
}
}
- if (e.filter != 0) {
- notify_add_onelevel(notify, &e, private_data);
- status = NT_STATUS_OK;
- }
-
/* if the system notify handler couldn't handle some of the
filter bits, or couldn't handle a request for recursion
then we need to install it in the array used for the
@@ -533,106 +426,6 @@ done:
return status;
}
-NTSTATUS notify_remove_onelevel(struct notify_context *notify,
- const struct file_id *fid,
- void *private_data)
-{
- struct notify_entry_array *array;
- struct db_record *rec;
- DATA_BLOB blob;
- TDB_DATA dbuf;
- enum ndr_err_code ndr_err;
- NTSTATUS status;
- int i;
-
- if (notify == NULL) {
- return NT_STATUS_NOT_IMPLEMENTED;
- }
-
- array = talloc_zero(talloc_tos(), struct notify_entry_array);
- if (array == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- rec = notify->db_onelevel->fetch_locked(
- notify->db_onelevel, array,
- make_tdb_data((uint8_t *)fid, sizeof(*fid)));
- if (rec == NULL) {
- DEBUG(10, ("notify_remove_onelevel: fetch_locked for %s failed"
- "\n", file_id_string_tos(fid)));
- TALLOC_FREE(array);
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- blob.data = (uint8_t *)rec->value.dptr;
- blob.length = rec->value.dsize;
-
- if (blob.length > 0) {
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
- (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
- ndr_errstr(ndr_err)));
- TALLOC_FREE(array);
- return ndr_map_error2ntstatus(ndr_err);
- }
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_remove_onelevel:\n"));
- NDR_PRINT_DEBUG(notify_entry_array, array);
- }
- }
-
- for (i=0; i<array->num_entries; i++) {
- if ((private_data == array->entries[i].private_data) &&
- cluster_id_equal(&notify->server,
- &array->entries[i].server)) {
- break;
- }
- }
-
- if (i == array->num_entries) {
- TALLOC_FREE(array);
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
-
- array->entries[i] = array->entries[array->num_entries-1];
- array->num_entries -= 1;
-
- if (array->num_entries == 0) {
- rec->delete_rec(rec);
- TALLOC_FREE(array);
- return NT_STATUS_OK;
- }
-
- ndr_err = ndr_push_struct_blob(
- &blob, rec, NULL, array,
- (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
- ndr_errstr(ndr_err)));
- TALLOC_FREE(array);
- return ndr_map_error2ntstatus(ndr_err);
- }
-
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_add_onelevel:\n"));
- NDR_PRINT_DEBUG(notify_entry_array, array);
- }
-
- dbuf.dptr = blob.data;
- dbuf.dsize = blob.length;
-
- status = rec->store(rec, dbuf, TDB_REPLACE);
- TALLOC_FREE(array);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("notify_add_onelevel: store failed: %s\n",
- nt_errstr(status)));
- return status;
- }
- return NT_STATUS_OK;
-}
-
/*
remove a notify watch. Called when the directory handle is closed
*/
@@ -781,96 +574,6 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *
return status;
}
-void notify_onelevel(struct notify_context *notify, uint32_t action,
- uint32_t filter, struct file_id fid, const char *name)
-{
- struct notify_entry_array *array;
- TDB_DATA dbuf;
- DATA_BLOB blob;
- bool have_dead_entries = false;
- int i;
-
- if (notify == NULL) {
- return;
- }
-
- array = talloc_zero(talloc_tos(), struct notify_entry_array);
- if (array == NULL) {
- return;
- }
-
- if (notify->db_onelevel->fetch(
- notify->db_onelevel, array,
- make_tdb_data((uint8_t *)&fid, sizeof(fid)),
- &dbuf) == -1) {
- TALLOC_FREE(array);
- return;
- }
-
- blob.data = (uint8 *)dbuf.dptr;
- blob.length = dbuf.dsize;
-
- if (blob.length > 0) {
- enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
- (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
- ndr_errstr(ndr_err)));
- TALLOC_FREE(array);
- return;
- }
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_onelevel:\n"));
- NDR_PRINT_DEBUG(notify_entry_array, array);
- }
- }
-
- for (i=0; i<array->num_entries; i++) {
- struct notify_entry *e = &array->entries[i];
-
- if ((e->filter & filter) != 0) {
- NTSTATUS status;
-
- status = notify_send(notify, e, name, action);
- if (NT_STATUS_EQUAL(
- status, NT_STATUS_INVALID_HANDLE)) {
- /*
- * Mark the entry as dead. All entries have a
- * path set. The marker used here is setting
- * that to NULL.
- */
- e->path = NULL;
- have_dead_entries = true;
- }
- }
- }
-
- if (!have_dead_entries) {
- TALLOC_FREE(array);
- return;
- }
-
- for (i=0; i<array->num_entries; i++) {
- struct notify_entry *e = &array->entries[i];
- if (e->path != NULL) {
- continue;
- }
- DEBUG(10, ("Deleting notify entries for process %s because "
- "it's gone\n", procid_str_static(&e->server)));
- /*
- * Potential TODO: This might need optimizing,
- * notify_remove_onelevel() does a fetch_locked() operation at
- * every call. But this would only matter if a process with
- * MANY notifies has died without shutting down properly.
- */
- notify_remove_onelevel(notify, &e->dir_id, e->private_data);
- }
-
- TALLOC_FREE(array);
- return;
-}
/*
trigger a notify message for anyone waiting on a matching event
@@ -911,7 +614,7 @@ void notify_trigger(struct notify_context *notify,
/* see if there are any entries at this depth */
if (d->num_entries == 0) continue;
-
+
/* try to skip based on the maximum mask. If next_p is
NULL then we know it will be a 'this directory'
match, otherwise it must be a subdir match */
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 656375499f..4bfbcd1690 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -21,6 +21,7 @@
#include "includes.h"
#include "smbd/globals.h"
+extern enum protocol_types Protocol;
extern const struct generic_mapping file_generic_mapping;
static char *nttrans_realloc(char **ptr, size_t size)
@@ -57,8 +58,6 @@ void send_nt_replies(connection_struct *conn,
int params_sent_thistime, data_sent_thistime, total_sent_thistime;
int alignment_offset = 3;
int data_alignment_offset = 0;
- struct smbd_server_connection *sconn = smbd_server_conn;
- int max_send = sconn->smb1.sessions.max_send;
/*
* If there genuinely are no parameters or data to send just send
@@ -67,20 +66,7 @@ void send_nt_replies(connection_struct *conn,
if(params_to_send == 0 && data_to_send == 0) {
reply_outbuf(req, 18, 0);
- if (NT_STATUS_V(nt_error)) {
- error_packet_set((char *)req->outbuf,
- 0, 0, nt_error,
- __LINE__,__FILE__);
- }
show_msg((char *)req->outbuf);
- if (!srv_send_smb(smbd_server_fd(),
- (char *)req->outbuf,
- true, req->seqnum+1,
- IS_CONN_ENCRYPTED(conn),
- &req->pcd)) {
- exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
- }
- TALLOC_FREE(req->outbuf);
return;
}
@@ -244,7 +230,6 @@ void send_nt_replies(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
&req->pcd)) {
exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
@@ -271,6 +256,53 @@ void send_nt_replies(connection_struct *conn,
}
/****************************************************************************
+ Is it an NTFS stream name ?
+ An NTFS file name is <path>.<extention>:<stream name>:<stream type>
+ $DATA can be used as both a stream name and a stream type. A missing stream
+ name or type implies $DATA.
+
+ Both Windows stream names and POSIX files can contain the ':' character.
+ This function first checks for the existence of a colon in the last component
+ of the given name. If the name contains a colon we differentiate between a
+ stream and POSIX file by checking if the latter exists through a POSIX stat.
+
+ Function assumes we've already chdir() to the "root" directory of fname.
+****************************************************************************/
+
+bool is_ntfs_stream_name(const char *fname)
+{
+ const char *lastcomp;
+ SMB_STRUCT_STAT sbuf;
+
+ /* If all pathnames are treated as POSIX we ignore streams. */
+ if (lp_posix_pathnames()) {
+ return false;
+ }
+
+ /* Find the last component of the name. */
+ if ((lastcomp = strrchr_m(fname, '/')) != NULL)
+ ++lastcomp;
+ else
+ lastcomp = fname;
+
+ /* If there is no colon in the last component, it's not a stream. */
+ if (strchr_m(lastcomp, ':') == NULL)
+ return false;
+
+ /*
+ * If file already exists on disk, it's not a stream. The stat must
+ * bypass the vfs layer so streams modules don't intefere.
+ */
+ if (sys_stat(fname, &sbuf) == 0) {
+ DEBUG(5, ("is_ntfs_stream_name: file %s contains a ':' but is "
+ "not a stream\n", fname));
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
Reply to an NT create and X call on a pipe
****************************************************************************/
@@ -374,53 +406,6 @@ static void do_ntcreate_pipe_open(connection_struct *conn,
chain_reply(req);
}
-struct case_semantics_state {
- connection_struct *conn;
- bool case_sensitive;
- bool case_preserve;
- bool short_case_preserve;
-};
-
-/****************************************************************************
- Restore case semantics.
-****************************************************************************/
-
-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 struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
- connection_struct *conn)
-{
- struct case_semantics_state *result;
-
- if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
- return NULL;
- }
-
- result->conn = conn;
- 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;
-
- talloc_set_destructor(result, restore_case_semantics);
-
- return result;
-}
-
/****************************************************************************
Reply to an NT create and X call.
****************************************************************************/
@@ -428,7 +413,6 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx
void reply_ntcreate_and_X(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 flags;
uint32 access_mask;
@@ -442,14 +426,13 @@ void reply_ntcreate_and_X(struct smb_request *req)
reply bits separately. */
uint32 fattr=0;
SMB_OFF_T file_len = 0;
+ SMB_STRUCT_STAT sbuf;
int info = 0;
files_struct *fsp = NULL;
char *p = NULL;
- struct timespec create_timespec;
struct timespec c_timespec;
struct timespec a_timespec;
struct timespec m_timespec;
- struct timespec write_time_ts;
NTSTATUS status;
int oplock_request;
uint8_t oplock_granted = NO_OPLOCK_RETURN;
@@ -458,9 +441,11 @@ void reply_ntcreate_and_X(struct smb_request *req)
START_PROFILE(SMBntcreateX);
+ SET_STAT_INVALID(sbuf);
+
if (req->wct < 24) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
flags = IVAL(req->vwv+3, 1);
@@ -481,7 +466,8 @@ void reply_ntcreate_and_X(struct smb_request *req)
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBntcreateX);
+ return;
}
DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
@@ -510,10 +496,12 @@ void reply_ntcreate_and_X(struct smb_request *req)
if (IS_IPC(conn)) {
if (lp_nt_pipe_support()) {
do_ntcreate_pipe_open(conn, req);
- goto out;
+ END_PROFILE(SMBntcreateX);
+ return;
}
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBntcreateX);
+ return;
}
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
@@ -522,47 +510,31 @@ void reply_ntcreate_and_X(struct smb_request *req)
? BATCH_OPLOCK : 0;
}
+ /*
+ * Check if POSIX semantics are wanted.
+ */
+
if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
case_state = set_posix_case_semantics(ctx, conn);
if (!case_state) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
- }
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
-
- TALLOC_FREE(case_state);
-
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBntcreateX);
+ return;
}
- reply_nterror(req, status);
- goto out;
+ /*
+ * Bug #6898 - clients using Windows opens should
+ * never be able to set this attribute into the
+ * VFS.
+ */
+ file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
}
- /*
- * Bug #6898 - clients using Windows opens should
- * never be able to set this attribute into the
- * VFS.
- */
- file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
-
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
root_dir_fid, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_access, /* share_access */
create_disposition, /* create_disposition*/
@@ -573,21 +545,27 @@ void reply_ntcreate_and_X(struct smb_request *req)
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
+
+ TALLOC_FREE(case_state);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call, no error. */
- goto out;
+ END_PROFILE(SMBntcreateX);
+ return;
}
- reply_openerror(req, status);
- goto out;
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ reply_botherror(req, status, ERRDOS, ERRfilexists);
+ }
+ else {
+ reply_nterror(req, status);
+ }
+ END_PROFILE(SMBntcreateX);
+ return;
}
- /* Ensure we're pointing at the correct stat struct. */
- TALLOC_FREE(smb_fname);
- smb_fname = fsp->fsp_name;
-
/*
* If the caller set the extended oplock request bit
* and we granted one (by whatever means) - set the
@@ -613,7 +591,11 @@ void reply_ntcreate_and_X(struct smb_request *req)
oplock_granted = NO_OPLOCK_RETURN;
}
- file_len = smb_fname->st.st_ex_size;
+ file_len = sbuf.st_size;
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
+ if (fattr == 0) {
+ fattr = FILE_ATTRIBUTE_NORMAL;
+ }
if (flags & EXTENDED_RESPONSE_REQUIRED) {
/* This is very strange. We
@@ -642,66 +624,34 @@ void reply_ntcreate_and_X(struct smb_request *req)
}
p += 4;
- fattr = dos_mode(conn, smb_fname);
- if (fattr == 0) {
- fattr = FILE_ATTRIBUTE_NORMAL;
- }
-
- /* Deal with other possible opens having a modified
- write time. JRA. */
- ZERO_STRUCT(write_time_ts);
- get_file_infos(fsp->file_id, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&smb_fname->st, write_time_ts);
- }
-
/* Create time. */
- create_timespec = get_create_timespec(conn, fsp, smb_fname);
- a_timespec = smb_fname->st.st_ex_atime;
- m_timespec = smb_fname->st.st_ex_mtime;
- c_timespec = get_change_timespec(conn, fsp, smb_fname);
+ c_timespec = get_create_timespec(
+ &sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ a_timespec = get_atimespec(&sbuf);
+ m_timespec = get_mtimespec(&sbuf);
if (lp_dos_filetime_resolution(SNUM(conn))) {
- dos_filetime_timespec(&create_timespec);
+ dos_filetime_timespec(&c_timespec);
dos_filetime_timespec(&a_timespec);
dos_filetime_timespec(&m_timespec);
- dos_filetime_timespec(&c_timespec);
}
- put_long_date_timespec(conn->ts_res, p, create_timespec); /* create time. */
+ put_long_date_timespec(conn->ts_res, p, c_timespec); /* create time. */
p += 8;
put_long_date_timespec(conn->ts_res, p, a_timespec); /* access time */
p += 8;
put_long_date_timespec(conn->ts_res, p, m_timespec); /* write time */
p += 8;
- put_long_date_timespec(conn->ts_res, p, c_timespec); /* change time */
+ put_long_date_timespec(conn->ts_res, p, m_timespec); /* change time */
p += 8;
SIVAL(p,0,fattr); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&smb_fname->st));
+ SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 8;
if (flags & EXTENDED_RESPONSE_REQUIRED) {
- uint16_t file_status = (NO_EAS|NO_SUBSTREAMS|NO_REPARSETAG);
- size_t num_names = 0;
- unsigned int num_streams;
- struct stream_struct *streams = NULL;
-
- /* Do we have any EA's ? */
- status = get_ea_names_from_file(ctx, conn, fsp,
- smb_fname->base_name, NULL, &num_names);
- if (NT_STATUS_IS_OK(status) && num_names) {
- file_status &= ~NO_EAS;
- }
- status = SMB_VFS_STREAMINFO(conn, NULL, smb_fname->base_name, ctx,
- &num_streams, &streams);
- /* There is always one stream, ::$DATA. */
- if (NT_STATUS_IS_OK(status) && num_streams > 1) {
- file_status &= ~NO_SUBSTREAMS;
- }
- TALLOC_FREE(streams);
- SSVAL(p,2,file_status);
+ SSVAL(p,2,0x7);
}
p += 4;
SCVAL(p,0,fsp->is_directory ? 1 : 0);
@@ -709,8 +659,8 @@ void reply_ntcreate_and_X(struct smb_request *req)
if (flags & EXTENDED_RESPONSE_REQUIRED) {
uint32 perms = 0;
p += 25;
- if (fsp->is_directory ||
- can_write_to_file(conn, smb_fname)) {
+ if (fsp->is_directory
+ || can_write_to_file(conn, fsp->fsp_name, &sbuf)) {
perms = FILE_GENERIC_ALL;
} else {
perms = FILE_GENERIC_READ|FILE_EXECUTE;
@@ -719,10 +669,9 @@ void reply_ntcreate_and_X(struct smb_request *req)
}
DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n",
- fsp->fnum, smb_fname_str_dbg(smb_fname)));
+ fsp->fnum, fsp->fsp_name));
chain_reply(req);
- out:
END_PROFILE(SMBntcreateX);
return;
}
@@ -752,7 +701,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn,
if(parameter_count < 54) {
DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -782,7 +731,7 @@ static void do_nt_transact_create_pipe(connection_struct *conn,
}
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -855,7 +804,7 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len,
security_acl_map_generic(psd->sacl, &file_generic_mapping);
if (DEBUGLEVEL >= 10) {
- DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp)));
+ DEBUG(10,("set_sd for file %s\n", fsp->fsp_name ));
NDR_PRINT_DEBUG(security_descriptor, psd);
}
@@ -870,7 +819,7 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len,
Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
****************************************************************************/
-struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
+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;
@@ -908,13 +857,13 @@ static void call_nt_transact_create(connection_struct *conn,
char **ppdata, uint32 data_count,
uint32 max_data_count)
{
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
char *params = *ppparams;
char *data = *ppdata;
/* Breakout the oplock request bits so we can set the reply bits separately. */
uint32 fattr=0;
SMB_OFF_T file_len = 0;
+ SMB_STRUCT_STAT sbuf;
int info = 0;
files_struct *fsp = NULL;
char *p = NULL;
@@ -928,11 +877,9 @@ static void call_nt_transact_create(connection_struct *conn,
struct security_descriptor *sd = NULL;
uint32 ea_len;
uint16 root_dir_fid;
- struct timespec create_timespec;
struct timespec c_timespec;
struct timespec a_timespec;
struct timespec m_timespec;
- struct timespec write_time_ts;
struct ea_list *ea_list = NULL;
NTSTATUS status;
size_t param_len;
@@ -942,6 +889,8 @@ static void call_nt_transact_create(connection_struct *conn,
struct case_semantics_state *case_state = NULL;
TALLOC_CTX *ctx = talloc_tos();
+ SET_STAT_INVALID(sbuf);
+
DEBUG(5,("call_nt_transact_create\n"));
/*
@@ -955,10 +904,10 @@ static void call_nt_transact_create(connection_struct *conn,
ppsetup, setup_count,
ppparams, parameter_count,
ppdata, data_count);
- goto out;
+ return;
}
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ return;
}
/*
@@ -968,7 +917,7 @@ static void call_nt_transact_create(connection_struct *conn,
if(parameter_count < 54) {
DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
flags = IVAL(params,0);
@@ -999,7 +948,7 @@ static void call_nt_transact_create(connection_struct *conn,
"%u, data_count = %u\n", (unsigned int)ea_len,
(unsigned int)sd_len, (unsigned int)data_count));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
if (sd_len) {
@@ -1013,7 +962,7 @@ static void call_nt_transact_create(connection_struct *conn,
"unmarshall_sec_desc failed: %s\n",
nt_errstr(status)));
reply_nterror(req, status);
- goto out;
+ return;
}
}
@@ -1023,7 +972,7 @@ static void call_nt_transact_create(connection_struct *conn,
"EA's not supported.\n",
(unsigned int)ea_len));
reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- goto out;
+ return;
}
if (ea_len < 10) {
@@ -1031,7 +980,7 @@ static void call_nt_transact_create(connection_struct *conn,
"too small (should be more than 10)\n",
(unsigned int)ea_len ));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
/* We have already checked that ea_len <= data_count here. */
@@ -1039,7 +988,7 @@ static void call_nt_transact_create(connection_struct *conn,
ea_len);
if (ea_list == NULL) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
}
@@ -1048,36 +997,7 @@ static void call_nt_transact_create(connection_struct *conn,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
- }
-
- if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
- case_state = set_posix_case_semantics(ctx, conn);
- if (!case_state) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
- }
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
-
- TALLOC_FREE(case_state);
-
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
+ return;
}
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
@@ -1087,17 +1007,29 @@ static void call_nt_transact_create(connection_struct *conn,
}
/*
- * Bug #6898 - clients using Windows opens should
- * never be able to set this attribute into the
- * VFS.
+ * Check if POSIX semantics are wanted.
*/
- file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+
+ if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ case_state = set_posix_case_semantics(ctx, conn);
+ if (!case_state) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ /*
+ * Bug #6898 - clients using Windows opens should
+ * never be able to set this attribute into the
+ * VFS.
+ */
+ file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
+ }
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
root_dir_fid, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_access, /* share_access */
create_disposition, /* create_disposition*/
@@ -1108,7 +1040,10 @@ static void call_nt_transact_create(connection_struct *conn,
sd, /* sd */
ea_list, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
+
+ TALLOC_FREE(case_state);
if(!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
@@ -1116,13 +1051,9 @@ static void call_nt_transact_create(connection_struct *conn,
return;
}
reply_openerror(req, status);
- goto out;
+ return;
}
- /* Ensure we're pointing at the correct stat struct. */
- TALLOC_FREE(smb_fname);
- smb_fname = fsp->fsp_name;
-
/*
* If the caller set the extended oplock request bit
* and we granted one (by whatever means) - set the
@@ -1148,7 +1079,11 @@ static void call_nt_transact_create(connection_struct *conn,
oplock_granted = NO_OPLOCK_RETURN;
}
- file_len = smb_fname->st.st_ex_size;
+ file_len = sbuf.st_size;
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
+ if (fattr == 0) {
+ fattr = FILE_ATTRIBUTE_NORMAL;
+ }
/* Realloc the size of parameters and data we will return */
if (flags & EXTENDED_RESPONSE_REQUIRED) {
@@ -1159,8 +1094,8 @@ static void call_nt_transact_create(connection_struct *conn,
}
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ reply_doserror(req, ERRDOS, ERRnomem);
+ return;
}
p = params;
@@ -1177,43 +1112,29 @@ static void call_nt_transact_create(connection_struct *conn,
}
p += 8;
- fattr = dos_mode(conn, smb_fname);
- if (fattr == 0) {
- fattr = FILE_ATTRIBUTE_NORMAL;
- }
-
- /* Deal with other possible opens having a modified
- write time. JRA. */
- ZERO_STRUCT(write_time_ts);
- get_file_infos(fsp->file_id, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&smb_fname->st, write_time_ts);
- }
-
/* Create time. */
- create_timespec = get_create_timespec(conn, fsp, smb_fname);
- a_timespec = smb_fname->st.st_ex_atime;
- m_timespec = smb_fname->st.st_ex_mtime;
- c_timespec = get_change_timespec(conn, fsp, smb_fname);
+ c_timespec = get_create_timespec(
+ &sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ a_timespec = get_atimespec(&sbuf);
+ m_timespec = get_mtimespec(&sbuf);
if (lp_dos_filetime_resolution(SNUM(conn))) {
- dos_filetime_timespec(&create_timespec);
+ dos_filetime_timespec(&c_timespec);
dos_filetime_timespec(&a_timespec);
dos_filetime_timespec(&m_timespec);
- dos_filetime_timespec(&c_timespec);
}
- put_long_date_timespec(conn->ts_res, p, create_timespec); /* create time. */
+ put_long_date_timespec(conn->ts_res, p, c_timespec); /* create time. */
p += 8;
put_long_date_timespec(conn->ts_res, p, a_timespec); /* access time */
p += 8;
put_long_date_timespec(conn->ts_res, p, m_timespec); /* write time */
p += 8;
- put_long_date_timespec(conn->ts_res, p, c_timespec); /* change time */
+ put_long_date_timespec(conn->ts_res, p, m_timespec); /* change time */
p += 8;
SIVAL(p,0,fattr); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st));
+ SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 8;
@@ -1226,8 +1147,8 @@ static void call_nt_transact_create(connection_struct *conn,
if (flags & EXTENDED_RESPONSE_REQUIRED) {
uint32 perms = 0;
p += 25;
- if (fsp->is_directory ||
- can_write_to_file(conn, smb_fname)) {
+ if (fsp->is_directory
+ || can_write_to_file(conn, fsp->fsp_name, &sbuf)) {
perms = FILE_GENERIC_ALL;
} else {
perms = FILE_GENERIC_READ|FILE_EXECUTE;
@@ -1235,12 +1156,11 @@ static void call_nt_transact_create(connection_struct *conn,
SIVAL(p,0,perms);
}
- DEBUG(5,("call_nt_transact_create: open name = %s\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(5,("call_nt_transact_create: open name = %s\n", fsp->fsp_name));
/* Send the required number of replies */
send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0);
- out:
+
return;
}
@@ -1256,9 +1176,9 @@ void reply_ntcancel(struct smb_request *req)
*/
START_PROFILE(SMBntcancel);
- srv_cancel_sign_response(smbd_server_conn);
remove_pending_change_notify_requests_by_mid(req->mid);
remove_pending_lock_requests_by_mid(req->mid);
+ srv_cancel_sign_response(req->mid, true);
DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid));
@@ -1273,10 +1193,15 @@ void reply_ntcancel(struct smb_request *req)
static NTSTATUS copy_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_fname_src,
- struct smb_filename *smb_fname_dst,
+ const char *oldname_in,
+ const char *newname_in,
uint32 attrs)
{
+ SMB_STRUCT_STAT sbuf1, sbuf2;
+ char *oldname = NULL;
+ char *newname = NULL;
+ char *last_component_oldname = NULL;
+ char *last_component_newname = NULL;
files_struct *fsp1,*fsp2;
uint32 fattr;
int info;
@@ -1284,45 +1209,70 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NTSTATUS status = NT_STATUS_OK;
char *parent;
+ ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(sbuf2);
+
if (!CAN_WRITE(conn)) {
- status = NT_STATUS_MEDIA_WRITE_PROTECTED;
- goto out;
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- /* Source must already exist. */
- if (!VALID_STAT(smb_fname_src->st)) {
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- goto out;
+ status = unix_convert(ctx, conn, oldname_in, False, &oldname,
+ &last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Source must already exist. */
+ if (!VALID_STAT(sbuf1)) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
/* Ensure attributes match. */
- fattr = dos_mode(conn, smb_fname_src);
+ fattr = dos_mode(conn,oldname,&sbuf1);
if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
- status = NT_STATUS_NO_SUCH_FILE;
- goto out;
+ return NT_STATUS_NO_SUCH_FILE;
}
- /* Disallow if dst file already exists. */
- if (VALID_STAT(smb_fname_dst->st)) {
- status = NT_STATUS_OBJECT_NAME_COLLISION;
- goto out;
+ status = unix_convert(ctx, conn, newname_in, False, &newname,
+ &last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Disallow if newname already exists. */
+ if (VALID_STAT(sbuf2)) {
+ return NT_STATUS_OBJECT_NAME_COLLISION;
}
/* No links from a directory. */
- if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
- status = NT_STATUS_FILE_IS_A_DIRECTORY;
- goto out;
+ if (S_ISDIR(sbuf1.st_mode)) {
+ return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
+ /* Ensure this is within the share. */
+ 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",
- smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ oldname, newname));
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname_src, /* fname */
+ oldname, /* fname */
+ 0, /* create_file_flags */
FILE_READ_DATA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -1334,17 +1284,19 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp1, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname_dst, /* fname */
+ newname, /* fname */
+ 0, /* create_file_flags */
FILE_WRITE_DATA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -1356,15 +1308,16 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp2, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf2); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
close_file(NULL, fsp1, ERROR_CLOSE);
- goto out;
+ return status;
}
- if (smb_fname_src->st.st_ex_size) {
- ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
+ if (sbuf1.st_size) {
+ ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
}
/*
@@ -1376,32 +1329,27 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
+ set_close_write_time(fsp2, get_mtimespec(&sbuf1));
status = close_file(NULL, fsp2, NORMAL_CLOSE);
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
- if (!parent_dirname(talloc_tos(), smb_fname_dst->base_name, &parent,
- NULL)) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ if (!parent_dirname(talloc_tos(), newname, &parent, NULL)) {
+ return NT_STATUS_NO_MEMORY;
}
- file_set_dosmode(conn, smb_fname_dst, fattr, parent, false);
+ file_set_dosmode(conn, newname, fattr, &sbuf2, parent, false);
TALLOC_FREE(parent);
- if (ret < (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
- status = NT_STATUS_DISK_FULL;
- goto out;
+ if (ret < (SMB_OFF_T)sbuf1.st_size) {
+ return NT_STATUS_DISK_FULL;
}
- out:
+
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
- nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ nt_errstr(status), oldname, newname));
}
-
return status;
}
@@ -1412,8 +1360,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
void reply_ntrename(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname_old = NULL;
- struct smb_filename *smb_fname_new = NULL;
char *oldname = NULL;
char *newname = NULL;
const char *p;
@@ -1421,8 +1367,6 @@ void reply_ntrename(struct smb_request *req)
bool src_has_wcard = False;
bool dest_has_wcard = False;
uint32 attrs;
- uint32_t ucf_flags_src = 0;
- uint32_t ucf_flags_dst = 0;
uint16 rename_type;
TALLOC_CTX *ctx = talloc_tos();
@@ -1430,7 +1374,8 @@ void reply_ntrename(struct smb_request *req)
if (req->wct < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
attrs = SVAL(req->vwv+0, 0);
@@ -1441,12 +1386,14 @@ void reply_ntrename(struct smb_request *req)
&status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
if (ms_has_wild(oldname)) {
reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
p++;
@@ -1454,81 +1401,66 @@ void reply_ntrename(struct smb_request *req)
&status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
- }
-
- /* The newname must begin with a ':' if the oldname contains a ':'. */
- if (strchr_m(oldname, ':') && (newname[0] != ':')) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
- /*
- * If this is a rename operation, allow wildcards and save the
- * destination's last component.
- */
- if (rename_type == RENAME_FLAG_RENAME) {
- ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP;
- ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP;
- }
-
- /* rename_internals() calls unix_convert(), so don't call it here. */
- status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- oldname,
- ucf_flags_src,
- NULL,
- &smb_fname_old);
+ status = resolve_dfspath(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ oldname,
+ &oldname);
if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,
- NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
- status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- newname,
- ucf_flags_dst,
- &dest_has_wcard,
- &smb_fname_new);
+ status = resolve_dfspath(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ newname,
+ &newname);
if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,
- NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
+ }
+
+ /* The new name must begin with a ':' if the old name is a stream. */
+ if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ END_PROFILE(SMBntrename);
+ return;
}
- DEBUG(3,("reply_ntrename: %s -> %s\n",
- smb_fname_str_dbg(smb_fname_old),
- smb_fname_str_dbg(smb_fname_new)));
+ DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
switch(rename_type) {
case RENAME_FLAG_RENAME:
- status = rename_internals(ctx, conn, req,
- smb_fname_old, smb_fname_new,
- attrs, False, src_has_wcard,
- dest_has_wcard,
- DELETE_ACCESS);
+ status = rename_internals(ctx, conn, req, oldname,
+ newname, attrs, False, src_has_wcard,
+ dest_has_wcard, DELETE_ACCESS);
break;
case RENAME_FLAG_HARD_LINK:
if (src_has_wcard || dest_has_wcard) {
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
- status = hardlink_internals(ctx, conn,
- smb_fname_old,
- smb_fname_new);
+ status = hardlink_internals(ctx,
+ conn,
+ oldname,
+ newname);
}
break;
case RENAME_FLAG_COPY:
@@ -1536,10 +1468,8 @@ void reply_ntrename(struct smb_request *req)
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
- status = copy_internals(ctx, conn, req,
- smb_fname_old,
- smb_fname_new,
- attrs);
+ status = copy_internals(ctx, conn, req, oldname,
+ newname, attrs);
}
break;
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
@@ -1553,15 +1483,17 @@ void reply_ntrename(struct smb_request *req)
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBntrename);
+ return;
}
reply_outbuf(req, 0, 0);
- out:
+
END_PROFILE(SMBntrename);
return;
}
@@ -1571,13 +1503,6 @@ void reply_ntrename(struct smb_request *req)
don't allow a directory to be opened.
****************************************************************************/
-static void smbd_smb1_notify_reply(struct smb_request *req,
- NTSTATUS error_code,
- uint8_t *buf, size_t len)
-{
- send_nt_replies(req->conn, req, error_code, (char *)buf, len, NULL, 0);
-}
-
static void call_nt_transact_notify_change(connection_struct *conn,
struct smb_request *req,
uint16 **ppsetup,
@@ -1595,7 +1520,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
bool recursive;
if(setup_count < 6) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
return;
}
@@ -1606,7 +1531,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
DEBUG(3,("call_nt_transact_notify_change\n"));
if(!fsp) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
@@ -1620,7 +1545,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
DEBUG(3,("call_nt_transact_notify_change: notify change "
"called on %s, filter = %s, recursive = %d\n",
- fsp_str_dbg(fsp), filter_string, recursive));
+ fsp->fsp_name, filter_string, recursive));
TALLOC_FREE(filter_string);
}
@@ -1653,11 +1578,8 @@ static void call_nt_transact_notify_change(connection_struct *conn,
* here.
*/
- change_notify_reply(fsp->conn, req,
- NT_STATUS_OK,
- max_param_count,
- fsp->notify,
- smbd_smb1_notify_reply);
+ change_notify_reply(fsp->conn, req, max_param_count,
+ fsp->notify);
/*
* change_notify_reply() above has independently sent its
@@ -1673,8 +1595,7 @@ static void call_nt_transact_notify_change(connection_struct *conn,
status = change_notify_add_request(req,
max_param_count,
filter,
- recursive, fsp,
- smbd_smb1_notify_reply);
+ recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
}
@@ -1700,7 +1621,7 @@ static void call_nt_transact_rename(connection_struct *conn,
TALLOC_CTX *ctx = talloc_tos();
if(parameter_count < 5) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
return;
}
@@ -1723,7 +1644,7 @@ static void call_nt_transact_rename(connection_struct *conn,
send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s ignored!\n",
- fsp_str_dbg(fsp), new_name));
+ fsp->fsp_name, new_name));
return;
}
@@ -1769,25 +1690,24 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
DATA_BLOB blob;
if(parameter_count < 8) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
return;
}
fsp = file_fsp(req, SVAL(params,0));
if(!fsp) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
security_info_wanted = IVAL(params,4);
- DEBUG(3,("call_nt_transact_query_security_desc: file = %s, "
- "info_wanted = 0x%x\n", fsp_str_dbg(fsp),
- (unsigned int)security_info_wanted));
+ DEBUG(3,("call_nt_transact_query_security_desc: file = %s, info_wanted = 0x%x\n", fsp->fsp_name,
+ (unsigned int)security_info_wanted ));
params = nttrans_realloc(ppparams, 4);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -1820,8 +1740,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
if (DEBUGLEVEL >= 10) {
- DEBUG(10,("call_nt_transact_query_security_desc for file %s\n",
- fsp_str_dbg(fsp)));
+ DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name));
NDR_PRINT_DEBUG(security_descriptor, psd);
}
@@ -1839,7 +1758,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
data = nttrans_realloc(ppdata, sd_size);
if(data == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -1880,12 +1799,12 @@ static void call_nt_transact_set_security_desc(connection_struct *conn,
NTSTATUS status;
if(parameter_count < 8) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
return;
}
if((fsp = file_fsp(req, SVAL(params,0))) == NULL) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
@@ -1895,11 +1814,11 @@ static void call_nt_transact_set_security_desc(connection_struct *conn,
security_info_sent = IVAL(params,4);
- DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n",
- fsp_str_dbg(fsp), (unsigned int)security_info_sent));
+ DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name,
+ (unsigned int)security_info_sent ));
if (data_count == 0) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -2120,7 +2039,7 @@ static void call_nt_transact_ioctl(connection_struct *conn,
cur_pdata+=12;
DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
- shadow_data->num_volumes, fsp_str_dbg(fsp)));
+ shadow_data->num_volumes,fsp->fsp_name));
if (labels && shadow_data->labels) {
for (i=0;i<shadow_data->num_volumes;i++) {
srvstr_push(pdata, req->flags2,
@@ -2243,7 +2162,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
DEBUG(1,("get_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -2253,7 +2172,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
if (parameter_count < 4) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRinvalidparam);
return;
}
@@ -2288,7 +2207,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -2308,7 +2227,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
}
if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) {
- reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ reply_doserror(req, ERRSRV, ERRerror);
return;
}
@@ -2316,7 +2235,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -2325,7 +2244,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/
if(pdata == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -2388,20 +2307,20 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
if (data_count < 8) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
sid_len = IVAL(pdata,4);
/* Ensure this is less than 1mb. */
if (sid_len > (1024*1024)) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
if (data_count < 8+sid_len) {
DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len)));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
@@ -2432,13 +2351,13 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
param_len = 4;
params = nttrans_realloc(ppparams, param_len);
if(params == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
pdata = nttrans_realloc(ppdata, data_len);
if(pdata == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
return;
}
@@ -2472,7 +2391,7 @@ static void call_nt_transact_get_user_quota(connection_struct *conn,
default:
DEBUG(0,("do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX\n",fsp->fnum,level));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRSRV, ERRerror);
return;
break;
}
@@ -2510,7 +2429,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
DEBUG(1,("set_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -2520,7 +2439,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
if (parameter_count < 2) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRinvalidparam);
return;
}
@@ -2534,7 +2453,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
if (data_count < 40) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
@@ -2548,7 +2467,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
if (data_count < 40+sid_len) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
@@ -2565,7 +2484,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
((qt.usedspace != 0xFFFFFFFF)||
(IVAL(pdata,20)!=0xFFFFFFFF))) {
/* more than 32 bits? */
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
#endif /* LARGE_SMB_OFF_T */
@@ -2579,7 +2498,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
((qt.softlim != 0xFFFFFFFF)||
(IVAL(pdata,28)!=0xFFFFFFFF))) {
/* more than 32 bits? */
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
#endif /* LARGE_SMB_OFF_T */
@@ -2593,7 +2512,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
((qt.hardlim != 0xFFFFFFFF)||
(IVAL(pdata,36)!=0xFFFFFFFF))) {
/* more than 32 bits? */
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRDOS, ERRunknownlevel);
return;
}
#endif /* LARGE_SMB_OFF_T */
@@ -2604,7 +2523,7 @@ static void call_nt_transact_set_user_quota(connection_struct *conn,
/* 44 unknown bytes left... */
if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
- reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ reply_doserror(req, ERRSRV, ERRerror);
return;
}
@@ -2617,7 +2536,7 @@ static void handle_nttrans(connection_struct *conn,
struct trans_state *state,
struct smb_request *req)
{
- if (get_Protocol() >= PROTOCOL_NT1) {
+ if (Protocol >= PROTOCOL_NT1) {
req->flags2 |= 0x40; /* IS_LONG_NAME */
SSVAL(req->inbuf,smb_flg2,req->flags2);
}
@@ -2738,7 +2657,7 @@ static void handle_nttrans(connection_struct *conn,
/* Error in request */
DEBUG(0,("handle_nttrans: Unknown request %d in "
"nttrans call\n", state->call));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_doserror(req, ERRSRV, ERRerror);
return;
}
return;
@@ -2774,7 +2693,7 @@ void reply_nttrans(struct smb_request *req)
function_code = SVAL(req->vwv+18, 0);
if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
END_PROFILE(SMBnttrans);
return;
}
@@ -2788,7 +2707,7 @@ void reply_nttrans(struct smb_request *req)
}
if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRSRV, ERRaccess);
END_PROFILE(SMBnttrans);
return;
}
@@ -2834,7 +2753,7 @@ void reply_nttrans(struct smb_request *req)
/* Don't allow more than 128mb for each value. */
if ((state->total_data > (1024*1024*128)) ||
(state->total_param > (1024*1024*128))) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
END_PROFILE(SMBnttrans);
return;
}
@@ -2855,7 +2774,7 @@ void reply_nttrans(struct smb_request *req)
DEBUG(0,("reply_nttrans: data malloc fail for %u "
"bytes !\n", (unsigned int)state->total_data));
TALLOC_FREE(state);
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
END_PROFILE(SMBnttrans);
return;
}
@@ -2877,7 +2796,7 @@ void reply_nttrans(struct smb_request *req)
"bytes !\n", (unsigned int)state->total_param));
SAFE_FREE(state->data);
TALLOC_FREE(state);
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
END_PROFILE(SMBnttrans);
return;
}
@@ -2910,7 +2829,7 @@ void reply_nttrans(struct smb_request *req)
SAFE_FREE(state->data);
SAFE_FREE(state->param);
TALLOC_FREE(state);
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
END_PROFILE(SMBnttrans);
return;
}
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 120de0f21a..ab3bf1ec75 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -31,7 +31,7 @@ struct deferred_open_record {
static NTSTATUS create_file_unixpath(connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_fname,
+ const char *fname,
uint32_t access_mask,
uint32_t share_access,
uint32_t create_disposition,
@@ -43,7 +43,8 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
struct ea_list *ea_list,
files_struct **result,
- int *pinfo);
+ int *pinfo,
+ SMB_STRUCT_STAT *psbuf);
/****************************************************************************
SMB1 file varient of se_access_check. Never test FILE_READ_ATTRIBUTES.
@@ -64,14 +65,14 @@ NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd,
Check if we have open rights.
****************************************************************************/
-NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
- const struct smb_filename *smb_fname,
+static NTSTATUS check_open_rights(struct connection_struct *conn,
+ const char *fname,
uint32_t access_mask,
uint32_t *access_granted)
{
/* Check if we have rights to open. */
NTSTATUS status;
- struct security_descriptor *sd = NULL;
+ struct security_descriptor *sd;
*access_granted = 0;
@@ -84,15 +85,15 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
return NT_STATUS_OK;
}
- status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
+ status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION),&sd);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("smbd_check_open_rights: Could not get acl "
+ DEBUG(10, ("check_open_rights: Could not get acl "
"on %s: %s\n",
- smb_fname_str_dbg(smb_fname),
+ fname,
nt_errstr(status)));
return status;
}
@@ -102,23 +103,15 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
access_mask,
access_granted);
- DEBUG(10,("smbd_check_open_rights: file %s requesting "
+ TALLOC_FREE(sd);
+
+ DEBUG(10,("check_open_rights: file %s requesting "
"0x%x returning 0x%x (%s)\n",
- smb_fname_str_dbg(smb_fname),
+ fname,
(unsigned int)access_mask,
(unsigned int)*access_granted,
nt_errstr(status) ));
- if (!NT_STATUS_IS_OK(status)) {
- if (DEBUGLEVEL >= 10) {
- DEBUG(10,("smbd_check_open_rights: acl for %s is:\n",
- smb_fname_str_dbg(smb_fname) ));
- NDR_PRINT_DEBUG(security_descriptor, sd);
- }
- }
-
- TALLOC_FREE(sd);
-
return status;
}
@@ -127,11 +120,11 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn,
****************************************************************************/
static NTSTATUS fd_open(struct connection_struct *conn,
+ const char *fname,
files_struct *fsp,
int flags,
mode_t mode)
{
- struct smb_filename *smb_fname = fsp->fsp_name;
NTSTATUS status = NT_STATUS_OK;
#ifdef O_NOFOLLOW
@@ -145,7 +138,7 @@ static NTSTATUS fd_open(struct connection_struct *conn,
}
#endif
- fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
+ fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
if (fsp->fh->fd == -1) {
status = map_nt_error_from_unix(errno);
if (errno == EMFILE) {
@@ -163,7 +156,7 @@ static NTSTATUS fd_open(struct connection_struct *conn,
}
DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
- smb_fname_str_dbg(smb_fname), flags, (int)mode, fsp->fh->fd,
+ fname, flags, (int)mode, fsp->fh->fd,
(fsp->fh->fd == -1) ? strerror(errno) : "" ));
return status;
@@ -201,41 +194,31 @@ void change_file_owner_to_parent(connection_struct *conn,
const char *inherit_from_dir,
files_struct *fsp)
{
- struct smb_filename *smb_fname_parent = NULL;
- NTSTATUS status;
+ SMB_STRUCT_STAT parent_st;
int ret;
- status = create_synthetic_smb_fname(talloc_tos(), inherit_from_dir,
- NULL, NULL, &smb_fname_parent);
- if (!NT_STATUS_IS_OK(status)) {
- return;
- }
-
- ret = SMB_VFS_STAT(conn, smb_fname_parent);
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- smb_fname_str_dbg(smb_fname_parent),
- strerror(errno)));
+ inherit_from_dir, strerror(errno) ));
return;
}
become_root();
- ret = SMB_VFS_FCHOWN(fsp, smb_fname_parent->st.st_ex_uid, (gid_t)-1);
+ ret = SMB_VFS_FCHOWN(fsp, parent_st.st_uid, (gid_t)-1);
unbecome_root();
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to fchown "
"file %s to parent directory uid %u. Error "
- "was %s\n", fsp_str_dbg(fsp),
- (unsigned int)smb_fname_parent->st.st_ex_uid,
+ "was %s\n", fsp->fsp_name,
+ (unsigned int)parent_st.st_uid,
strerror(errno) ));
}
DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
- "parent directory uid %u.\n", fsp_str_dbg(fsp),
- (unsigned int)smb_fname_parent->st.st_ex_uid));
-
- TALLOC_FREE(smb_fname_parent);
+ "parent directory uid %u.\n", fsp->fsp_name,
+ (unsigned int)parent_st.st_uid ));
}
NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
@@ -243,27 +226,20 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct smb_filename *smb_fname_parent = NULL;
- struct smb_filename *smb_fname_cwd = NULL;
char *saved_dir = NULL;
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT parent_st;
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
int ret;
- status = create_synthetic_smb_fname(ctx, inherit_from_dir, NULL, NULL,
- &smb_fname_parent);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- ret = SMB_VFS_STAT(conn, smb_fname_parent);
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- smb_fname_str_dbg(smb_fname_parent),
- strerror(errno)));
- goto out;
+ inherit_from_dir, strerror(errno) ));
+ return status;
}
/* We've already done an lstat into psbuf, and we know it's a
@@ -279,7 +255,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to get "
"current working directory. Error was %s\n",
strerror(errno)));
- goto out;
+ return status;
}
/* Chdir into the new path. */
@@ -288,58 +264,47 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to change "
"current working directory to %s. Error "
"was %s\n", fname, strerror(errno) ));
- goto chdir;
- }
-
- status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
- &smb_fname_cwd);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto out;
}
- ret = SMB_VFS_STAT(conn, smb_fname_cwd);
- if (ret == -1) {
+ if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat "
"directory '.' (%s) Error was %s\n",
fname, strerror(errno)));
- goto chdir;
+ goto out;
}
/* Ensure we're pointing at the same place. */
- if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev ||
- smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino ||
- smb_fname_cwd->st.st_ex_mode != psbuf->st_ex_mode ) {
+ if (sbuf.st_dev != psbuf->st_dev ||
+ sbuf.st_ino != psbuf->st_ino ||
+ sbuf.st_mode != psbuf->st_mode ) {
DEBUG(0,("change_dir_owner_to_parent: "
"device/inode/mode on directory %s changed. "
"Refusing to chown !\n", fname ));
status = NT_STATUS_ACCESS_DENIED;
- goto chdir;
+ goto out;
}
become_root();
- ret = SMB_VFS_CHOWN(conn, ".", smb_fname_parent->st.st_ex_uid,
- (gid_t)-1);
+ ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
unbecome_root();
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(10,("change_dir_owner_to_parent: failed to chown "
"directory %s to parent directory uid %u. "
"Error was %s\n", fname,
- (unsigned int)smb_fname_parent->st.st_ex_uid,
- strerror(errno) ));
- goto chdir;
+ (unsigned int)parent_st.st_uid, strerror(errno) ));
+ goto out;
}
DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
"directory %s to parent directory uid %u.\n",
- fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
+ fname, (unsigned int)parent_st.st_uid ));
- chdir:
- vfs_ChDir(conn,saved_dir);
out:
- TALLOC_FREE(smb_fname_parent);
- TALLOC_FREE(smb_fname_cwd);
+
+ vfs_ChDir(conn,saved_dir);
return status;
}
@@ -351,16 +316,18 @@ static NTSTATUS open_file(files_struct *fsp,
connection_struct *conn,
struct smb_request *req,
const char *parent_dir,
+ const char *name,
+ const char *path,
+ SMB_STRUCT_STAT *psbuf,
int flags,
mode_t unx_mode,
uint32 access_mask, /* client requested access mask. */
uint32 open_access_mask) /* what we're actually using in the open. */
{
- struct smb_filename *smb_fname = fsp->fsp_name;
NTSTATUS status = NT_STATUS_OK;
int accmode = (flags & O_ACCMODE);
int local_flags = flags;
- bool file_existed = VALID_STAT(fsp->fsp_name->st);
+ bool file_existed = VALID_STAT(*psbuf);
fsp->fh->fd = -1;
errno = EPERM;
@@ -380,8 +347,7 @@ static NTSTATUS open_file(files_struct *fsp,
if (!CAN_WRITE(conn)) {
/* It's a read-only share - fail if we wanted to write. */
if(accmode != O_RDONLY || (flags & O_TRUNC) || (flags & O_APPEND)) {
- DEBUG(3,("Permission denied opening %s\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(3,("Permission denied opening %s\n", path));
return NT_STATUS_ACCESS_DENIED;
} else if(flags & O_CREAT) {
/* We don't want to write - but we must make sure that
@@ -407,7 +373,7 @@ static NTSTATUS open_file(files_struct *fsp,
if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
DEBUG(10,("open_file: truncate requested on read-only open "
- "for file %s\n", smb_fname_str_dbg(smb_fname)));
+ "for file %s\n", path));
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
}
@@ -430,7 +396,7 @@ static NTSTATUS open_file(files_struct *fsp,
* open flags. JRA.
*/
- if (file_existed && S_ISFIFO(smb_fname->st.st_ex_mode)) {
+ if (file_existed && S_ISFIFO(psbuf->st_mode)) {
local_flags |= O_NONBLOCK;
}
#endif
@@ -441,9 +407,9 @@ static NTSTATUS open_file(files_struct *fsp,
* wildcard characters are allowed in stream names
* only test the basefilename
*/
- wild = fsp->base_fsp->fsp_name->base_name;
+ wild = fsp->base_fsp->fsp_name;
} else {
- wild = smb_fname->base_name;
+ wild = path;
}
if ((local_flags & O_CREAT) && !file_existed &&
ms_has_wild(wild)) {
@@ -451,11 +417,11 @@ static NTSTATUS open_file(files_struct *fsp,
}
/* Actually do the open */
- status = fd_open(conn, fsp, local_flags, unx_mode);
+ status = fd_open(conn, path, fsp, local_flags, unx_mode);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
- "(flags=%d)\n", smb_fname_str_dbg(smb_fname),
- nt_errstr(status),local_flags,flags));
+ "(flags=%d)\n",
+ path,nt_errstr(status),local_flags,flags));
return status;
}
@@ -463,9 +429,8 @@ static NTSTATUS open_file(files_struct *fsp,
/* Inherit the ACL if required */
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir,
- smb_fname->base_name,
- unx_mode);
+ inherit_access_posix_acl(conn, parent_dir, path,
+ unx_mode);
}
/* Change the owner if required. */
@@ -475,8 +440,7 @@ static NTSTATUS open_file(files_struct *fsp,
}
notify_fname(conn, NOTIFY_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_FILE_NAME,
- smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_FILE_NAME, path);
}
} else {
@@ -484,8 +448,8 @@ static NTSTATUS open_file(files_struct *fsp,
if (file_existed) {
uint32_t access_granted = 0;
- status = smbd_check_open_rights(conn,
- smb_fname,
+ status = check_open_rights(conn,
+ path,
access_mask,
&access_granted);
if (!NT_STATUS_IS_OK(status)) {
@@ -503,19 +467,14 @@ static NTSTATUS open_file(files_struct *fsp,
lp_map_system(SNUM(conn)))) {
access_granted &= ~FILE_WRITE_ATTRIBUTES;
- DEBUG(10,("open_file: "
- "overrode "
- "FILE_WRITE_"
- "ATTRIBUTES "
- "on file %s\n",
- smb_fname_str_dbg(
- smb_fname)));
+ DEBUG(10,("open_file: overrode FILE_WRITE_ATTRIBUTES "
+ "on file %s\n",
+ path ));
}
if ((access_mask & DELETE_ACCESS) &&
- (access_granted & DELETE_ACCESS) &&
- can_delete_file_in_directory(conn,
- smb_fname)) {
+ (access_granted & DELETE_ACCESS) &&
+ can_delete_file_in_directory(conn, path)) {
/* Were we trying to do a stat open
* for delete and didn't get DELETE
* access (only) ? Check if the
@@ -526,38 +485,30 @@ static NTSTATUS open_file(files_struct *fsp,
access_granted &= ~DELETE_ACCESS;
- DEBUG(10,("open_file: "
- "overrode "
- "DELETE_ACCESS on "
- "file %s\n",
- smb_fname_str_dbg(
- smb_fname)));
+ DEBUG(10,("open_file: overrode DELETE_ACCESS "
+ "on file %s\n",
+ path ));
}
if (access_granted != 0) {
- DEBUG(10,("open_file: Access "
- "denied on file "
- "%s\n",
- smb_fname_str_dbg(
- smb_fname)));
+ DEBUG(10, ("open_file: Access denied on "
+ "file %s\n",
+ path));
return status;
}
} else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) &&
- fsp->posix_open &&
- S_ISLNK(smb_fname->st.st_ex_mode)) {
+ fsp->posix_open &&
+ S_ISLNK(psbuf->st_mode)) {
/* This is a POSIX stat open for delete
* or rename on a symlink that points
* nowhere. Allow. */
- DEBUG(10,("open_file: allowing POSIX "
- "open on bad symlink %s\n",
- smb_fname_str_dbg(
- smb_fname)));
+ DEBUG(10, ("open_file: allowing POSIX open "
+ "on bad symlink %s\n",
+ path ));
} else {
- DEBUG(10,("open_file: "
- "smbd_check_open_rights on file "
- "%s returned %s\n",
- smb_fname_str_dbg(smb_fname),
- nt_errstr(status) ));
+ DEBUG(10, ("open_file: check_open_rights "
+ "on file %s returned %s\n",
+ path, nt_errstr(status) ));
return status;
}
}
@@ -568,15 +519,13 @@ static NTSTATUS open_file(files_struct *fsp,
int ret;
if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn, path, psbuf);
} else {
- ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
+ ret = SMB_VFS_FSTAT(fsp, psbuf);
/* If we have an fd, this stat should succeed. */
if (ret == -1) {
DEBUG(0,("Error doing fstat on open file %s "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno) ));
+ "(%s)\n", path,strerror(errno) ));
}
}
@@ -594,14 +543,14 @@ static NTSTATUS open_file(files_struct *fsp,
* so catch a directory open and return an EISDIR. JRA.
*/
- if(S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if(S_ISDIR(psbuf->st_mode)) {
fd_close(fsp);
errno = EISDIR;
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- fsp->mode = smb_fname->st.st_ex_mode;
- fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+ fsp->mode = psbuf->st_mode;
+ fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
fsp->file_pid = req ? req->smbpid : 0;
fsp->can_lock = True;
@@ -617,16 +566,16 @@ static NTSTATUS open_file(files_struct *fsp,
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = False;
if (conn->aio_write_behind_list &&
- is_in_path(smb_fname->base_name, conn->aio_write_behind_list,
- conn->case_sensitive)) {
+ is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) {
fsp->aio_write_behind = True;
}
+ string_set(&fsp->fsp_name, path);
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
conn->server_info->unix_name,
- smb_fname_str_dbg(smb_fname),
+ fsp->fsp_name,
BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
conn->num_files_open));
@@ -793,8 +742,7 @@ static void validate_my_share_entries(int num,
str = talloc_asprintf(talloc_tos(),
"validate_my_share_entries: "
"file %s, oplock_type = 0x%x, op_type = 0x%x\n",
- fsp->fsp_name->base_name,
- (unsigned int)fsp->oplock_type,
+ fsp->fsp_name, (unsigned int)fsp->oplock_type,
(unsigned int)share_entry->op_type );
smb_panic(str);
}
@@ -817,6 +765,7 @@ bool is_stat_open(uint32 access_mask)
****************************************************************************/
static NTSTATUS open_mode_check(connection_struct *conn,
+ const char *fname,
struct share_mode_lock *lck,
uint32 access_mask,
uint32 share_access,
@@ -1028,7 +977,7 @@ static bool delay_for_oplocks(struct share_mode_lock *lck,
}
DEBUG(10,("delay_for_oplocks: oplock type 0x%x on file %s\n",
- fsp->oplock_type, fsp_str_dbg(fsp)));
+ fsp->oplock_type, fsp->fsp_name));
/* No delay. */
return false;
@@ -1084,6 +1033,15 @@ static void defer_open(struct share_mode_lock *lck,
exit_server("push_deferred_smb_message failed");
}
add_deferred_open(lck, req->mid, request_time, state->id);
+
+ /*
+ * Push the MID of this packet on the signing queue.
+ * We only do this once, the first time we push the packet
+ * onto the deferred open queue, as this has a side effect
+ * of incrementing the response sequence number.
+ */
+
+ srv_defer_sign_response(req->mid);
}
@@ -1092,6 +1050,7 @@ static void defer_open(struct share_mode_lock *lck,
****************************************************************************/
bool open_match_attributes(connection_struct *conn,
+ const char *path,
uint32 old_dos_attr,
uint32 new_dos_attr,
mode_t existing_unx_mode,
@@ -1110,9 +1069,10 @@ bool open_match_attributes(connection_struct *conn,
*returned_unx_mode = (mode_t)0;
}
- DEBUG(10,("open_match_attributes: old_dos_attr = 0x%x, "
+ DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, "
"existing_unx_mode = 0%o, new_dos_attr = 0x%x "
"returned_unx_mode = 0%o\n",
+ path,
(unsigned int)old_dos_attr,
(unsigned int)existing_unx_mode,
(unsigned int)new_dos_attr,
@@ -1142,7 +1102,7 @@ bool open_match_attributes(connection_struct *conn,
NTSTATUS fcb_or_dos_open(struct smb_request *req,
connection_struct *conn,
files_struct *fsp_to_dup_into,
- const struct smb_filename *smb_fname,
+ const char *fname,
struct file_id id,
uint16 file_pid,
uint16 vuid,
@@ -1153,14 +1113,14 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
files_struct *fsp;
DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
- "file %s.\n", smb_fname_str_dbg(smb_fname)));
+ "file %s.\n", fname ));
for(fsp = file_find_di_first(id); fsp;
fsp = file_find_di_next(fsp)) {
DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
"vuid = %u, file_pid = %u, private_options = 0x%x "
- "access_mask = 0x%x\n", fsp_str_dbg(fsp),
+ "access_mask = 0x%x\n", fsp->fsp_name,
fsp->fh->fd, (unsigned int)fsp->vuid,
(unsigned int)fsp->file_pid,
(unsigned int)fsp->fh->private_options,
@@ -1172,9 +1132,7 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
(fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
(fsp->access_mask & FILE_WRITE_DATA) &&
- strequal(fsp->fsp_name->base_name, smb_fname->base_name) &&
- strequal(fsp->fsp_name->stream_name,
- smb_fname->stream_name)) {
+ strequal(fsp->fsp_name, fname)) {
DEBUG(10,("fcb_or_dos_open: file match\n"));
break;
}
@@ -1185,23 +1143,24 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req,
}
/* quite an insane set of semantics ... */
- if (is_executable(smb_fname->base_name) &&
+ if (is_executable(fname) &&
(fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n"));
return NT_STATUS_INVALID_PARAMETER;
}
/* We need to duplicate this fsp. */
- return dup_file_fsp(req, fsp, access_mask, share_access,
- create_options, fsp_to_dup_into);
+ dup_file_fsp(req, fsp, access_mask, share_access,
+ create_options, fsp_to_dup_into);
+
+ return NT_STATUS_OK;
}
/****************************************************************************
Open a file with a share mode - old openX method - map into NTCreate.
****************************************************************************/
-bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
- int deny_mode, int open_func,
+bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func,
uint32 *paccess_mask,
uint32 *pshare_mode,
uint32 *pcreate_disposition,
@@ -1214,8 +1173,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
"open_func = 0x%x\n",
- smb_fname_str_dbg(smb_fname), (unsigned int)deny_mode,
- (unsigned int)open_func ));
+ fname, (unsigned int)deny_mode, (unsigned int)open_func ));
/* Create the NT compatible access_mask. */
switch (GET_OPENX_MODE(deny_mode)) {
@@ -1289,7 +1247,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
case DENY_DOS:
create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
- if (is_executable(smb_fname->base_name)) {
+ if (is_executable(fname)) {
share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
} else {
if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
@@ -1314,7 +1272,7 @@ bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname,
DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
"share_mode = 0x%x, create_disposition = 0x%x, "
"create_options = 0x%x\n",
- smb_fname_str_dbg(smb_fname),
+ fname,
(unsigned int)access_mask,
(unsigned int)share_mode,
(unsigned int)create_disposition,
@@ -1379,7 +1337,7 @@ static void schedule_defer_open(struct share_mode_lock *lck,
****************************************************************************/
static NTSTATUS calculate_access_mask(connection_struct *conn,
- const struct smb_filename *smb_fname,
+ const char *fname,
bool file_existed,
uint32_t access_mask,
uint32_t *access_mask_out)
@@ -1399,7 +1357,7 @@ static NTSTATUS calculate_access_mask(connection_struct *conn,
struct security_descriptor *sd;
uint32_t access_granted = 0;
- status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name,
+ status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
DACL_SECURITY_INFORMATION),&sd);
@@ -1407,7 +1365,7 @@ static NTSTATUS calculate_access_mask(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("calculate_access_mask: Could not get acl "
"on file %s: %s\n",
- smb_fname_str_dbg(smb_fname),
+ fname,
nt_errstr(status)));
return NT_STATUS_ACCESS_DENIED;
}
@@ -1422,7 +1380,7 @@ static NTSTATUS calculate_access_mask(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("calculate_access_mask: Access denied on "
"file %s: when calculating maximum access\n",
- smb_fname_str_dbg(smb_fname)));
+ fname));
return NT_STATUS_ACCESS_DENIED;
}
@@ -1442,6 +1400,8 @@ static NTSTATUS calculate_access_mask(connection_struct *conn,
static NTSTATUS open_file_ntcreate(connection_struct *conn,
struct smb_request *req,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */
uint32 share_access, /* share constants (FILE_SHARE_READ etc) */
uint32 create_disposition, /* FILE_OPEN_IF etc. */
@@ -1452,10 +1412,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
int *pinfo,
files_struct *fsp)
{
- struct smb_filename *smb_fname = fsp->fsp_name;
int flags=0;
int flags2=0;
- bool file_existed = VALID_STAT(smb_fname->st);
+ bool file_existed = VALID_STAT(*psbuf);
bool def_acl = False;
bool posix_open = False;
bool new_file_created = False;
@@ -1471,7 +1430,9 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
struct share_mode_lock *lck = NULL;
uint32 open_access_mask = access_mask;
NTSTATUS status;
+ int ret_flock;
char *parent_dir;
+ const char *newname;
ZERO_STRUCT(id);
@@ -1485,21 +1446,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
*pinfo = FILE_WAS_CREATED;
}
- DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
- if (!req) {
- DEBUG(0,("open_file_ntcreate: printer open without "
- "an SMB request!\n"));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- return print_fsp_open(req, conn, smb_fname->base_name,
- req->vuid, fsp);
+ return print_fsp_open(req, conn, fname, req->vuid, fsp, psbuf);
}
- if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir,
- NULL)) {
+ if (!parent_dirname(talloc_tos(), fname, &parent_dir, &newname)) {
return NT_STATUS_NO_MEMORY;
}
@@ -1510,17 +1462,17 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
} else {
/* We add aARCH to this as this mode is only used if the file is
* created new. */
- unx_mode = unix_mode(conn, new_dos_attributes | aARCH,
- smb_fname, parent_dir);
+ unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname,
+ parent_dir);
}
DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
"access_mask=0x%x share_access=0x%x "
"create_disposition = 0x%x create_options=0x%x "
"unix mode=0%o oplock_request=%d\n",
- smb_fname_str_dbg(smb_fname), new_dos_attributes,
- access_mask, share_access, create_disposition,
- create_options, (unsigned int)unx_mode, oplock_request));
+ fname, new_dos_attributes, access_mask, share_access,
+ create_disposition, create_options, (unsigned int)unx_mode,
+ oplock_request));
if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
DEBUG(0, ("No smb request but not an internal only open!\n"));
@@ -1556,7 +1508,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
remove_deferred_open_smb_message(req->mid);
}
- status = check_name(conn, smb_fname->base_name);
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -1564,19 +1516,19 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (!posix_open) {
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
if (file_existed) {
- existing_dos_attributes = dos_mode(conn, smb_fname);
+ existing_dos_attributes = dos_mode(conn, fname, psbuf);
}
}
/* ignore any oplock requests if oplocks are disabled */
if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break ||
- IS_VETO_OPLOCK_PATH(conn, smb_fname->base_name)) {
+ IS_VETO_OPLOCK_PATH(conn, fname)) {
/* Mask off everything except the private Samba bits. */
oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
}
/* this is for OS/2 long file names - say we don't support them */
- if (!lp_posix_pathnames() && strstr(smb_fname->base_name,".+,;=[].")) {
+ if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
/* OS/2 Workplace shell fix may be main code stream in a later
* release. */
DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
@@ -1613,8 +1565,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (!file_existed) {
DEBUG(5,("open_file_ntcreate: FILE_OPEN "
"requested for file %s and file "
- "doesn't exist.\n",
- smb_fname_str_dbg(smb_fname)));
+ "doesn't exist.\n", fname ));
errno = ENOENT;
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -1626,8 +1577,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (!file_existed) {
DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
"requested for file %s and file "
- "doesn't exist.\n",
- smb_fname_str_dbg(smb_fname) ));
+ "doesn't exist.\n", fname ));
errno = ENOENT;
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -1641,9 +1591,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (file_existed) {
DEBUG(5,("open_file_ntcreate: FILE_CREATE "
"requested for file %s and file "
- "already exists.\n",
- smb_fname_str_dbg(smb_fname)));
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ "already exists.\n", fname ));
+ if (S_ISDIR(psbuf->st_mode)) {
errno = EISDIR;
} else {
errno = EEXIST;
@@ -1668,29 +1617,29 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) ||
(create_disposition == FILE_OVERWRITE_IF))) {
- if (!open_match_attributes(conn, existing_dos_attributes,
- new_dos_attributes,
- smb_fname->st.st_ex_mode,
+ if (!open_match_attributes(conn, fname,
+ existing_dos_attributes,
+ new_dos_attributes, psbuf->st_mode,
unx_mode, &new_unx_mode)) {
DEBUG(5,("open_file_ntcreate: attributes missmatch "
"for file %s (%x %x) (0%o, 0%o)\n",
- smb_fname_str_dbg(smb_fname),
- existing_dos_attributes,
+ fname, existing_dos_attributes,
new_dos_attributes,
- (unsigned int)smb_fname->st.st_ex_mode,
+ (unsigned int)psbuf->st_mode,
(unsigned int)unx_mode ));
errno = EACCES;
return NT_STATUS_ACCESS_DENIED;
}
}
- status = calculate_access_mask(conn, smb_fname, file_existed,
+ status = calculate_access_mask(conn, fname, file_existed,
access_mask,
&access_mask);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_file_ntcreate: calculate_access_mask "
"on file %s returned %s\n",
- smb_fname_str_dbg(smb_fname), nt_errstr(status)));
+ fname,
+ nt_errstr(status)));
return status;
}
@@ -1701,8 +1650,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping "
- "access_mask=0x%x\n", smb_fname_str_dbg(smb_fname),
- access_mask));
+ "access_mask=0x%x\n", fname, access_mask ));
/*
* Note that we ignore the append flag as append does not
@@ -1755,13 +1703,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
(!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) {
DEBUG(5,("open_file_ntcreate: write access requested for "
"file %s on read only %s\n",
- smb_fname_str_dbg(smb_fname),
- !CAN_WRITE(conn) ? "share" : "file" ));
+ fname, !CAN_WRITE(conn) ? "share" : "file" ));
errno = EACCES;
return NT_STATUS_ACCESS_DENIED;
}
- fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+ fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
fsp->share_access = share_access;
fsp->fh->private_options = create_options;
fsp->access_mask = open_access_mask; /* We change this to the
@@ -1777,12 +1724,12 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (file_existed) {
- struct timespec old_write_time = smb_fname->st.st_ex_mtime;
- id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+ struct timespec old_write_time = get_mtimespec(psbuf);
+ id = vfs_file_id_from_sbuf(conn, psbuf);
lck = get_share_mode_lock(talloc_tos(), id,
conn->connectpath,
- smb_fname, &old_write_time);
+ fname, &old_write_time);
if (lck == NULL) {
DEBUG(0, ("Could not get share mode lock\n"));
@@ -1800,7 +1747,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
/* Use the client requested access mask here, not the one we
* open with. */
- status = open_mode_check(conn, lck, access_mask, share_access,
+ status = open_mode_check(conn, fname, lck,
+ access_mask, share_access,
create_options, &file_existed);
if (NT_STATUS_IS_OK(status)) {
@@ -1846,7 +1794,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
status = fcb_or_dos_open(req,
conn,
fsp,
- smb_fname,
+ fname,
id,
req->smbpid,
req->vuid,
@@ -1881,10 +1829,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
can_access_mask = FILE_READ_DATA;
}
- if (((can_access_mask & FILE_WRITE_DATA) &&
- !CAN_WRITE(conn)) ||
- !can_access_file_data(conn, smb_fname,
- can_access_mask)) {
+ if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
+ !can_access_file_data(conn,fname,psbuf,can_access_mask)) {
can_access = False;
}
@@ -1970,7 +1916,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
* open_file strips any O_TRUNC flags itself.
*/
- fsp_open = open_file(fsp, conn, req, parent_dir,
+ fsp_open = open_file(fsp, conn, req, parent_dir, newname, fname, psbuf,
flags|flags2, unx_mode, access_mask,
open_access_mask);
@@ -1982,7 +1928,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (!file_existed) {
- struct timespec old_write_time = smb_fname->st.st_ex_mtime;
+ struct timespec old_write_time = get_mtimespec(psbuf);
/*
* Deal with the race condition where two smbd's detect the
* file doesn't exist and do the create at the same time. One
@@ -2002,12 +1948,11 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
lck = get_share_mode_lock(talloc_tos(), id,
conn->connectpath,
- smb_fname, &old_write_time);
+ fname, &old_write_time);
if (lck == NULL) {
DEBUG(0, ("open_file_ntcreate: Could not get share "
- "mode lock for %s\n",
- smb_fname_str_dbg(smb_fname)));
+ "mode lock for %s\n", fname));
fd_close(fsp);
return NT_STATUS_SHARING_VIOLATION;
}
@@ -2022,7 +1967,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
return NT_STATUS_SHARING_VIOLATION;
}
- status = open_mode_check(conn, lck, access_mask, share_access,
+ status = open_mode_check(conn, fname, lck,
+ access_mask, share_access,
create_options, &file_existed);
if (NT_STATUS_IS_OK(status)) {
@@ -2072,9 +2018,8 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
SMB_ASSERT(lck != NULL);
/* Delete streams if create_disposition requires it */
- if (file_existed && clear_ads &&
- !is_ntfs_stream_smb_fname(smb_fname)) {
- status = delete_all_streams(conn, smb_fname->base_name);
+ if (file_existed && clear_ads && !is_ntfs_stream_name(fname)) {
+ status = delete_all_streams(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(lck);
fd_close(fsp);
@@ -2091,8 +2036,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
note that GPFS supports it as well - jmcd */
if (fsp->fh->fd != -1) {
- int ret_flock;
- ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access, access_mask);
+ ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access);
if(ret_flock == -1 ){
TALLOC_FREE(lck);
@@ -2118,7 +2062,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
* struct..
*/
if ((SMB_VFS_FTRUNCATE(fsp, 0) == -1) ||
- (SMB_VFS_FSTAT(fsp, &smb_fname->st)==-1)) {
+ (SMB_VFS_FSTAT(fsp, psbuf)==-1)) {
status = map_nt_error_from_unix(errno);
TALLOC_FREE(lck);
fd_close(fsp);
@@ -2173,7 +2117,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
/* Handle strange delete on close create semantics. */
if (create_options & FILE_DELETE_ON_CLOSE) {
- status = can_set_delete_on_close(fsp, new_dos_attributes);
+ status = can_set_delete_on_close(fsp, True, new_dos_attributes);
if (!NT_STATUS_IS_OK(status)) {
/* Remember to delete the mode we just added. */
@@ -2192,10 +2136,14 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
- if (file_set_dosmode(conn, smb_fname,
+ SMB_STRUCT_STAT tmp_sbuf;
+ SET_STAT_INVALID(tmp_sbuf);
+ if (file_set_dosmode(
+ conn, fname,
new_dos_attributes | aARCH,
- parent_dir, true) == 0) {
- unx_mode = smb_fname->st.st_ex_mode;
+ &tmp_sbuf, parent_dir,
+ true) == 0) {
+ unx_mode = tmp_sbuf.st_mode;
}
}
}
@@ -2232,8 +2180,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
} else {
DEBUG(5, ("open_file_ntcreate: reset "
"attributes of file %s to 0%o\n",
- smb_fname_str_dbg(smb_fname),
- (unsigned int)new_unx_mode));
+ fname, (unsigned int)new_unx_mode));
ret = 0; /* Don't do the fchmod below. */
}
}
@@ -2242,8 +2189,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
(SMB_VFS_FCHMOD(fsp, new_unx_mode) == -1))
DEBUG(5, ("open_file_ntcreate: failed to reset "
"attributes of file %s to 0%o\n",
- smb_fname_str_dbg(smb_fname),
- (unsigned int)new_unx_mode));
+ fname, (unsigned int)new_unx_mode));
}
/* If this is a successful open, we must remove any deferred open
@@ -2262,13 +2208,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
****************************************************************************/
NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
- struct smb_filename *smb_fname,
- files_struct **result)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf, files_struct **result)
{
files_struct *fsp = NULL;
NTSTATUS status;
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*psbuf)) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -2277,11 +2223,12 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
return status;
}
- status = SMB_VFS_CREATE_FILE(
+ status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
FILE_WRITE_DATA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -2293,7 +2240,8 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ psbuf); /* psbuf */
/*
* This is not a user visible file open.
@@ -2321,11 +2269,13 @@ NTSTATUS close_file_fchmod(struct smb_request *req, files_struct *fsp)
}
static NTSTATUS mkdir_internal(connection_struct *conn,
- struct smb_filename *smb_dname,
- uint32 file_attributes)
+ const char *name,
+ uint32 file_attributes,
+ SMB_STRUCT_STAT *psbuf)
{
mode_t mode;
char *parent_dir;
+ const char *dirname;
NTSTATUS status;
bool posix_open = false;
@@ -2335,13 +2285,12 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
return NT_STATUS_ACCESS_DENIED;
}
- status = check_name(conn, smb_dname->base_name);
+ status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- if (!parent_dirname(talloc_tos(), smb_dname->base_name, &parent_dir,
- NULL)) {
+ if (!parent_dirname(talloc_tos(), name, &parent_dir, &dirname)) {
return NT_STATUS_NO_MEMORY;
}
@@ -2349,65 +2298,61 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
posix_open = true;
mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
} else {
- mode = unix_mode(conn, aDIR, smb_dname, parent_dir);
+ mode = unix_mode(conn, aDIR, name, parent_dir);
}
- if (SMB_VFS_MKDIR(conn, smb_dname->base_name, mode) != 0) {
+ if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
return map_nt_error_from_unix(errno);
}
/* Ensure we're checking for a symlink here.... */
/* We don't want to get caught by a symlink racer. */
- if (SMB_VFS_LSTAT(conn, smb_dname) == -1) {
+ if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
- smb_fname_str_dbg(smb_dname), strerror(errno)));
+ name, strerror(errno)));
return map_nt_error_from_unix(errno);
}
- if (!S_ISDIR(smb_dname->st.st_ex_mode)) {
+ if (!S_ISDIR(psbuf->st_mode)) {
DEBUG(0, ("Directory just '%s' created is not a directory\n",
- smb_fname_str_dbg(smb_dname)));
+ name));
return NT_STATUS_ACCESS_DENIED;
}
if (lp_store_dos_attributes(SNUM(conn))) {
if (!posix_open) {
- file_set_dosmode(conn, smb_dname,
- file_attributes | aDIR,
- parent_dir, true);
+ file_set_dosmode(conn, name,
+ file_attributes | aDIR, NULL,
+ parent_dir,
+ true);
}
}
if (lp_inherit_perms(SNUM(conn))) {
- inherit_access_posix_acl(conn, parent_dir,
- smb_dname->base_name, mode);
+ inherit_access_posix_acl(conn, parent_dir, name, mode);
}
- if (!posix_open) {
+ if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
/*
* Check if high bits should have been set,
* then (if bits are missing): add them.
* Consider bits automagically set by UNIX, i.e. SGID bit from parent
* dir.
*/
- if ((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) &&
- (mode & ~smb_dname->st.st_ex_mode)) {
- SMB_VFS_CHMOD(conn, smb_dname->base_name,
- (smb_dname->st.st_ex_mode |
- (mode & ~smb_dname->st.st_ex_mode)));
+ if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
+ SMB_VFS_CHMOD(conn, name,
+ psbuf->st_mode | (mode & ~psbuf->st_mode));
}
}
/* Change the owner if required. */
if (lp_inherit_owner(SNUM(conn))) {
- change_dir_owner_to_parent(conn, parent_dir,
- smb_dname->base_name,
- &smb_dname->st);
+ change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
}
notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
+ name);
return NT_STATUS_OK;
}
@@ -2418,7 +2363,8 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
static NTSTATUS open_directory(connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_dname,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
uint32 access_mask,
uint32 share_access,
uint32 create_disposition,
@@ -2428,18 +2374,16 @@ static NTSTATUS open_directory(connection_struct *conn,
files_struct **result)
{
files_struct *fsp = NULL;
- bool dir_existed = VALID_STAT(smb_dname->st) ? True : False;
+ bool dir_existed = VALID_STAT(*psbuf) ? True : False;
struct share_mode_lock *lck = NULL;
NTSTATUS status;
struct timespec mtimespec;
int info = 0;
- SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
-
DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
"share_access = 0x%x create_options = 0x%x, "
"create_disposition = 0x%x, file_attributes = 0x%x\n",
- smb_fname_str_dbg(smb_dname),
+ fname,
(unsigned int)access_mask,
(unsigned int)share_access,
(unsigned int)create_options,
@@ -2448,18 +2392,18 @@ static NTSTATUS open_directory(connection_struct *conn,
if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) &&
(conn->fs_capabilities & FILE_NAMED_STREAMS) &&
- is_ntfs_stream_smb_fname(smb_dname)) {
- DEBUG(2, ("open_directory: %s is a stream name!\n",
- smb_fname_str_dbg(smb_dname)));
+ is_ntfs_stream_name(fname)) {
+ DEBUG(2, ("open_directory: %s is a stream name!\n", fname));
return NT_STATUS_NOT_A_DIRECTORY;
}
- status = calculate_access_mask(conn, smb_dname, dir_existed,
- access_mask, &access_mask);
+ status = calculate_access_mask(conn, fname, dir_existed,
+ access_mask,
+ &access_mask);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_directory: calculate_access_mask "
"on file %s returned %s\n",
- smb_fname_str_dbg(smb_dname),
+ fname,
nt_errstr(status)));
return status;
}
@@ -2468,7 +2412,7 @@ static NTSTATUS open_directory(connection_struct *conn,
if (access_mask & SEC_FLAG_SYSTEM_SECURITY) {
DEBUG(10, ("open_directory: open on %s "
"failed - SEC_FLAG_SYSTEM_SECURITY denied.\n",
- smb_fname_str_dbg(smb_dname)));
+ fname));
return NT_STATUS_PRIVILEGE_NOT_HELD;
}
@@ -2481,7 +2425,7 @@ static NTSTATUS open_directory(connection_struct *conn,
* We want to follow symlinks here.
*/
- if (SMB_VFS_STAT(conn, smb_dname) != 0) {
+ if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
return map_nt_error_from_unix(errno);
}
@@ -2492,13 +2436,14 @@ static NTSTATUS open_directory(connection_struct *conn,
/* If directory exists error. If directory doesn't
* exist create. */
- status = mkdir_internal(conn, smb_dname,
- file_attributes);
+ status = mkdir_internal(conn,
+ fname,
+ file_attributes,
+ psbuf);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("open_directory: unable to create "
- "%s. Error was %s\n",
- smb_fname_str_dbg(smb_dname),
+ "%s. Error was %s\n", fname,
nt_errstr(status)));
return status;
}
@@ -2512,8 +2457,10 @@ static NTSTATUS open_directory(connection_struct *conn,
* exist create.
*/
- status = mkdir_internal(conn, smb_dname,
- file_attributes);
+ status = mkdir_internal(conn,
+ fname,
+ file_attributes,
+ psbuf);
if (NT_STATUS_IS_OK(status)) {
info = FILE_WAS_CREATED;
@@ -2533,21 +2480,22 @@ static NTSTATUS open_directory(connection_struct *conn,
default:
DEBUG(5,("open_directory: invalid create_disposition "
"0x%x for directory %s\n",
- (unsigned int)create_disposition,
- smb_fname_str_dbg(smb_dname)));
+ (unsigned int)create_disposition, fname));
return NT_STATUS_INVALID_PARAMETER;
}
- if(!S_ISDIR(smb_dname->st.st_ex_mode)) {
+ if(!S_ISDIR(psbuf->st_mode)) {
DEBUG(5,("open_directory: %s is not a directory !\n",
- smb_fname_str_dbg(smb_dname)));
+ fname ));
return NT_STATUS_NOT_A_DIRECTORY;
}
if (info == FILE_WAS_OPENED) {
uint32_t access_granted = 0;
- status = smbd_check_open_rights(conn, smb_dname, access_mask,
- &access_granted);
+ status = check_open_rights(conn,
+ fname,
+ access_mask,
+ &access_granted);
/* Were we trying to do a directory open
* for delete and didn't get DELETE
@@ -2558,19 +2506,19 @@ static NTSTATUS open_directory(connection_struct *conn,
* for details. */
if ((NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
- (access_mask & DELETE_ACCESS) &&
- (access_granted == DELETE_ACCESS) &&
- can_delete_file_in_directory(conn, smb_dname))) {
+ (access_mask & DELETE_ACCESS) &&
+ (access_granted == DELETE_ACCESS) &&
+ can_delete_file_in_directory(conn, fname))) {
DEBUG(10,("open_directory: overrode ACCESS_DENIED "
"on directory %s\n",
- smb_fname_str_dbg(smb_dname)));
+ fname ));
status = NT_STATUS_OK;
}
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("open_directory: smbd_check_open_rights on "
+ DEBUG(10, ("open_directory: check_open_rights on "
"file %s failed with %s\n",
- smb_fname_str_dbg(smb_dname),
+ fname,
nt_errstr(status)));
return status;
}
@@ -2585,8 +2533,8 @@ static NTSTATUS open_directory(connection_struct *conn,
* Setup the files_struct for it.
*/
- fsp->mode = smb_dname->st.st_ex_mode;
- fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_dname->st);
+ fsp->mode = psbuf->st_mode;
+ fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
fsp->file_pid = req ? req->smbpid : 0;
fsp->can_lock = False;
@@ -2605,25 +2553,24 @@ static NTSTATUS open_directory(connection_struct *conn,
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True;
fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
- status = fsp_set_smb_fname(fsp, smb_dname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- mtimespec = smb_dname->st.st_ex_mtime;
+ string_set(&fsp->fsp_name,fname);
+
+ mtimespec = get_mtimespec(psbuf);
lck = get_share_mode_lock(talloc_tos(), fsp->file_id,
- conn->connectpath, smb_dname, &mtimespec);
+ conn->connectpath,
+ fname, &mtimespec);
if (lck == NULL) {
- DEBUG(0, ("open_directory: Could not get share mode lock for "
- "%s\n", smb_fname_str_dbg(smb_dname)));
+ DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
file_free(req, fsp);
return NT_STATUS_SHARING_VIOLATION;
}
- status = open_mode_check(conn, lck, access_mask, share_access,
- create_options, &dir_existed);
+ status = open_mode_check(conn, fname, lck,
+ access_mask, share_access,
+ create_options, &dir_existed);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(lck);
@@ -2636,7 +2583,7 @@ static NTSTATUS open_directory(connection_struct *conn,
/* For directories the delete on close bit at open time seems
always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
if (create_options & FILE_DELETE_ON_CLOSE) {
- status = can_set_delete_on_close(fsp, 0);
+ status = can_set_delete_on_close(fsp, True, 0);
if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
TALLOC_FREE(lck);
file_free(req, fsp);
@@ -2660,17 +2607,20 @@ static NTSTATUS open_directory(connection_struct *conn,
return NT_STATUS_OK;
}
-NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
- struct smb_filename *smb_dname)
+NTSTATUS create_directory(connection_struct *conn, struct smb_request *req, const char *directory)
{
NTSTATUS status;
+ SMB_STRUCT_STAT sbuf;
files_struct *fsp;
+ SET_STAT_INVALID(sbuf);
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_dname, /* fname */
+ directory, /* fname */
+ 0, /* create_file_flags */
FILE_READ_ATTRIBUTES, /* access_mask */
FILE_SHARE_NONE, /* share_access */
FILE_CREATE, /* create_disposition*/
@@ -2681,7 +2631,8 @@ NTSTATUS create_directory(connection_struct *conn, struct smb_request *req,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
@@ -2705,11 +2656,8 @@ void msg_file_was_renamed(struct messaging_context *msg,
char *frm = (char *)data->data;
struct file_id id;
const char *sharepath;
- const char *base_name;
- const char *stream_name;
- struct smb_filename *smb_fname = NULL;
- size_t sp_len, bn_len;
- NTSTATUS status;
+ const char *newname;
+ size_t sp_len;
if (data->data == NULL
|| data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) {
@@ -2721,37 +2669,18 @@ void msg_file_was_renamed(struct messaging_context *msg,
/* Unpack the message. */
pull_file_id_24(frm, &id);
sharepath = &frm[24];
+ newname = sharepath + strlen(sharepath) + 1;
sp_len = strlen(sharepath);
- base_name = sharepath + sp_len + 1;
- bn_len = strlen(base_name);
- stream_name = sharepath + sp_len + 1 + bn_len + 1;
-
- /* stream_name must always be NULL if there is no stream. */
- if (stream_name[0] == '\0') {
- stream_name = NULL;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(), base_name,
- stream_name, NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return;
- }
DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, "
"file_id %s\n",
- sharepath, smb_fname_str_dbg(smb_fname),
- file_id_string_tos(&id)));
+ sharepath, newname, file_id_string_tos(&id)));
for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) {
if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
-
- DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
- smb_fname_str_dbg(smb_fname)));
- status = fsp_set_smb_fname(fsp, smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
+ DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
+ fsp->fnum, fsp->fsp_name, newname ));
+ string_set(&fsp->fsp_name, newname);
} else {
/* TODO. JRA. */
/* Now we have the complete path we can work out if this is
@@ -2762,13 +2691,56 @@ void msg_file_was_renamed(struct messaging_context *msg,
fsp->conn->connectpath,
sharepath,
fsp->fnum,
- fsp_str_dbg(fsp),
- smb_fname_str_dbg(smb_fname)));
+ fsp->fsp_name,
+ newname ));
}
}
- out:
- TALLOC_FREE(smb_fname);
- return;
+}
+
+struct case_semantics_state {
+ connection_struct *conn;
+ bool case_sensitive;
+ bool case_preserve;
+ bool short_case_preserve;
+};
+
+/****************************************************************************
+ Restore case semantics.
+****************************************************************************/
+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.
+****************************************************************************/
+struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
+ connection_struct *conn)
+{
+ struct case_semantics_state *result;
+
+ if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ result->conn = conn;
+ 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;
+
+ talloc_set_destructor(result, restore_case_semantics);
+
+ return result;
}
/*
@@ -2819,30 +2791,28 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
}
for (i=0; i<num_streams; i++) {
- struct smb_filename *smb_fname = NULL;
+ char *streamname;
if (strequal(stream_info[i].name, "::$DATA")) {
streams[i] = NULL;
continue;
}
- status = create_synthetic_smb_fname(talloc_tos(), fname,
- stream_info[i].name,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
+ streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
+ stream_info[i].name);
- if (SMB_VFS_STAT(conn, smb_fname) == -1) {
- DEBUG(10, ("Unable to stat stream: %s\n",
- smb_fname_str_dbg(smb_fname)));
+ if (streamname == NULL) {
+ DEBUG(0, ("talloc_aprintf failed\n"));
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ streamname, /* fname */
+ 0, /* create_file_flags */
DELETE_ACCESS, /* access_mask */
(FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE | FILE_SHARE_DELETE),
@@ -2854,17 +2824,16 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&streams[i], /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL); /* psbuf */
+
+ TALLOC_FREE(streamname);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Could not open stream %s: %s\n",
- smb_fname_str_dbg(smb_fname),
- nt_errstr(status)));
-
- TALLOC_FREE(smb_fname);
+ streamname, nt_errstr(status)));
break;
}
- TALLOC_FREE(smb_fname);
}
/*
@@ -2877,7 +2846,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
}
DEBUG(10, ("Closing stream # %d, %s\n", i,
- fsp_str_dbg(streams[i])));
+ streams[i]->fsp_name));
close_file(NULL, streams[i], NORMAL_CLOSE);
}
@@ -2892,7 +2861,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
static NTSTATUS create_file_unixpath(connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_fname,
+ const char *fname,
uint32_t access_mask,
uint32_t share_access,
uint32_t create_disposition,
@@ -2904,8 +2873,10 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
struct ea_list *ea_list,
files_struct **result,
- int *pinfo)
+ int *pinfo,
+ SMB_STRUCT_STAT *psbuf)
{
+ SMB_STRUCT_STAT sbuf;
int info = FILE_WAS_OPENED;
files_struct *base_fsp = NULL;
files_struct *fsp = NULL;
@@ -2922,7 +2893,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
(unsigned int)create_disposition,
(unsigned int)create_options,
(unsigned int)oplock_request,
- ea_list, sd, smb_fname_str_dbg(smb_fname)));
+ ea_list, sd, fname));
if (create_options & FILE_OPEN_BY_FILE_ID) {
status = NT_STATUS_NOT_SUPPORTED;
@@ -2938,14 +2909,23 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
oplock_request |= INTERNAL_OPEN_ONLY;
}
+ if (psbuf != NULL) {
+ sbuf = *psbuf;
+ }
+ else {
+ if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) {
+ SET_STAT_INVALID(sbuf);
+ }
+ }
+
if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
&& (access_mask & DELETE_ACCESS)
- && !is_ntfs_stream_smb_fname(smb_fname)) {
+ && !is_ntfs_stream_name(fname)) {
/*
* We can't open a file with DELETE access if any of the
* streams is open without FILE_SHARE_DELETE
*/
- status = open_streams_for_delete(conn, smb_fname->base_name);
+ status = open_streams_for_delete(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
@@ -2965,12 +2945,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (create_disposition != FILE_CREATE)
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
- && (!(can_delete_file_in_directory(conn, smb_fname) ||
- can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) {
+ && (!(can_delete_file_in_directory(conn, fname) ||
+ can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
status = NT_STATUS_ACCESS_DENIED;
DEBUG(10,("create_file_unixpath: open file %s "
- "for delete ACCESS_DENIED\n",
- smb_fname_str_dbg(smb_fname)));
+ "for delete ACCESS_DENIED\n", fname ));
goto fail;
}
@@ -2990,7 +2969,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
}
/* Don't allow a SACL set from an NTtrans create until we
* support SeSecurityPrivilege. */
- if (!VALID_STAT(smb_fname->st) &&
+ if (!VALID_STAT(sbuf) &&
lp_nt_acl_support(SNUM(conn)) &&
sd && (sd->sacl != NULL)) {
status = NT_STATUS_PRIVILEGE_NOT_HELD;
@@ -2999,16 +2978,27 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
#endif
if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && is_ntfs_stream_smb_fname(smb_fname)
+ && is_ntfs_stream_name(fname)
&& (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) {
+ char *base;
uint32 base_create_disposition;
- struct smb_filename *smb_fname_base = NULL;
if (create_options & FILE_DIRECTORY_FILE) {
status = NT_STATUS_NOT_A_DIRECTORY;
goto fail;
}
+ status = split_ntfs_stream_name(talloc_tos(), fname,
+ &base, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("create_file_unixpath: "
+ "split_ntfs_stream_name failed: %s\n",
+ nt_errstr(status)));
+ goto fail;
+ }
+
+ SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
+
switch (create_disposition) {
case FILE_OPEN:
base_create_disposition = FILE_OPEN;
@@ -3018,34 +3008,16 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
break;
}
- /* Create an smb_filename with stream_name == NULL. */
- status = create_synthetic_smb_fname(talloc_tos(),
- smb_fname->base_name,
- NULL, NULL,
- &smb_fname_base);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
- if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
- DEBUG(10, ("Unable to stat stream: %s\n",
- smb_fname_str_dbg(smb_fname_base)));
- }
-
- /* Open the base file. */
- status = create_file_unixpath(conn, NULL, smb_fname_base, 0,
+ status = create_file_unixpath(conn, NULL, base, 0,
FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE,
base_create_disposition,
0, 0, 0, 0, NULL, NULL,
- &base_fsp, NULL);
- TALLOC_FREE(smb_fname_base);
-
+ &base_fsp, NULL, NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("create_file_unixpath for base %s failed: "
- "%s\n", smb_fname->base_name,
- nt_errstr(status)));
+ "%s\n", base, nt_errstr(status)));
goto fail;
}
/* we don't need to low level fd */
@@ -3078,7 +3050,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
oplock_request = 0;
status = open_directory(
- conn, req, smb_fname, access_mask, share_access,
+ conn, req, fname, &sbuf, access_mask, share_access,
create_disposition, create_options, file_attributes,
&info, &fsp);
} else {
@@ -3092,11 +3064,6 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
goto fail;
}
- status = fsp_set_smb_fname(fsp, smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
/*
* We're opening the stream element of a base_fsp
* we already opened. Set up the base_fsp pointer.
@@ -3107,6 +3074,8 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
status = open_file_ntcreate(conn,
req,
+ fname,
+ &sbuf,
access_mask,
share_access,
create_disposition,
@@ -3142,7 +3111,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
oplock_request = 0;
status = open_directory(
- conn, req, smb_fname, access_mask,
+ conn, req, fname, &sbuf, access_mask,
share_access, create_disposition,
create_options, file_attributes,
&info, &fsp);
@@ -3195,14 +3164,14 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
}
if ((ea_list != NULL) &&
- ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN))) {
- status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
+ ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN))) {
+ status = set_ea(conn, fsp, fname, ea_list);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
}
- if (!fsp->is_directory && S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
+ if (!fsp->is_directory && S_ISDIR(sbuf.st_mode)) {
status = NT_STATUS_ACCESS_DENIED;
goto fail;
}
@@ -3210,7 +3179,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
/* Save the requested allocation size. */
if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
if (allocation_size
- && (allocation_size > fsp->fsp_name->st.st_ex_size)) {
+ && (allocation_size > sbuf.st_size)) {
fsp->initial_allocation_size = smb_roundup(
fsp->conn, allocation_size);
if (fsp->is_directory) {
@@ -3225,7 +3194,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
}
} else {
fsp->initial_allocation_size = smb_roundup(
- fsp->conn, (uint64_t)fsp->fsp_name->st.st_ex_size);
+ fsp->conn, (uint64_t)sbuf.st_size);
}
}
@@ -3235,9 +3204,14 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
if (pinfo != NULL) {
*pinfo = info;
}
-
- smb_fname->st = fsp->fsp_name->st;
-
+ if (psbuf != NULL) {
+ if ((fsp->fh == NULL) || (fsp->fh->fd == -1)) {
+ *psbuf = sbuf;
+ }
+ else {
+ SMB_VFS_FSTAT(fsp, psbuf);
+ }
+ }
return NT_STATUS_OK;
fail:
@@ -3267,28 +3241,19 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
NTSTATUS get_relative_fid_filename(connection_struct *conn,
struct smb_request *req,
uint16_t root_dir_fid,
- struct smb_filename *smb_fname)
+ const char *fname, char **new_fname)
{
files_struct *dir_fsp;
char *parent_fname = NULL;
- char *new_base_name = NULL;
- NTSTATUS status;
- if (root_dir_fid == 0 || !smb_fname) {
- status = NT_STATUS_INTERNAL_ERROR;
- goto out;
+ if (root_dir_fid == 0 || !fname || !new_fname) {
+ return NT_STATUS_INTERNAL_ERROR;
}
dir_fsp = file_fsp(req, root_dir_fid);
if (dir_fsp == NULL) {
- status = NT_STATUS_INVALID_HANDLE;
- goto out;
- }
-
- if (is_ntfs_stream_smb_fname(dir_fsp->fsp_name)) {
- status = NT_STATUS_INVALID_HANDLE;
- goto out;
+ return NT_STATUS_INVALID_HANDLE;
}
if (!dir_fsp->is_directory) {
@@ -3298,9 +3263,8 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
*/
if ((conn->fs_capabilities & FILE_NAMED_STREAMS) &&
- is_ntfs_stream_smb_fname(smb_fname)) {
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- goto out;
+ is_ntfs_stream_name(fname)) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
/*
@@ -3310,11 +3274,10 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
(hint from demyn plantenberg)
*/
- status = NT_STATUS_INVALID_HANDLE;
- goto out;
+ return NT_STATUS_INVALID_HANDLE;
}
- if (ISDOT(dir_fsp->fsp_name->base_name)) {
+ if (ISDOT(dir_fsp->fsp_name)) {
/*
* We're at the toplevel dir, the final file name
* must not contain ./, as this is filtered out
@@ -3323,11 +3286,10 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
*/
parent_fname = talloc_strdup(talloc_tos(), "");
if (parent_fname == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ return NT_STATUS_NO_MEMORY;
}
} else {
- size_t dir_name_len = strlen(dir_fsp->fsp_name->base_name);
+ size_t dir_name_len = strlen(dir_fsp->fsp_name);
/*
* Copy in the base directory name.
@@ -3336,10 +3298,9 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
parent_fname = TALLOC_ARRAY(talloc_tos(), char,
dir_name_len+2);
if (parent_fname == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ return NT_STATUS_NO_MEMORY;
}
- memcpy(parent_fname, dir_fsp->fsp_name->base_name,
+ memcpy(parent_fname, dir_fsp->fsp_name,
dir_name_len+1);
/*
@@ -3355,26 +3316,20 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn,
}
}
- new_base_name = talloc_asprintf(smb_fname, "%s%s", parent_fname,
- smb_fname->base_name);
- if (new_base_name == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ *new_fname = talloc_asprintf(talloc_tos(), "%s%s", parent_fname,
+ fname);
+ if (*new_fname == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = new_base_name;
- status = NT_STATUS_OK;
-
- out:
- TALLOC_FREE(parent_fname);
- return status;
+ return NT_STATUS_OK;
}
NTSTATUS create_file_default(connection_struct *conn,
struct smb_request *req,
uint16_t root_dir_fid,
- struct smb_filename *smb_fname,
+ const char *fname,
+ uint32_t create_file_flags,
uint32_t access_mask,
uint32_t share_access,
uint32_t create_disposition,
@@ -3384,9 +3339,12 @@ NTSTATUS create_file_default(connection_struct *conn,
uint64_t allocation_size,
struct security_descriptor *sd,
struct ea_list *ea_list,
+
files_struct **result,
- int *pinfo)
+ int *pinfo,
+ SMB_STRUCT_STAT *psbuf)
{
+ SMB_STRUCT_STAT sbuf;
int info = FILE_WAS_OPENED;
files_struct *fsp = NULL;
NTSTATUS status;
@@ -3396,7 +3354,7 @@ NTSTATUS create_file_default(connection_struct *conn,
"create_disposition = 0x%x create_options = 0x%x "
"oplock_request = 0x%x "
"root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, "
- "fname = %s\n",
+ "create_file_flags = 0x%x, fname = %s\n",
(unsigned int)access_mask,
(unsigned int)file_attributes,
(unsigned int)share_access,
@@ -3404,28 +3362,55 @@ NTSTATUS create_file_default(connection_struct *conn,
(unsigned int)create_options,
(unsigned int)oplock_request,
(unsigned int)root_dir_fid,
- ea_list, sd, smb_fname_str_dbg(smb_fname)));
+ ea_list, sd, create_file_flags, fname));
+
+ /* MSDFS pathname processing must be done FIRST.
+ MSDFS pathnames containing IPv6 addresses can
+ be confused with NTFS stream names (they contain
+ ":" characters. JRA. */
+
+ if ((req != NULL) && (req->flags2 & FLAGS2_DFS_PATHNAMES)) {
+ char *resolved_fname;
+
+ status = resolve_dfspath(talloc_tos(), conn, true, fname,
+ &resolved_fname);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * For PATH_NOT_COVERED we had
+ * reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ * ERRSRV, ERRbadpath);
+ * Need to fix in callers
+ */
+ goto fail;
+ }
+ fname = resolved_fname;
+ }
/*
* Calculate the filename from the root_dir_if if necessary.
*/
if (root_dir_fid != 0) {
+ char *new_fname;
+
status = get_relative_fid_filename(conn, req, root_dir_fid,
- smb_fname);
+ fname, &new_fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+
+ fname = new_fname;
}
/*
* Check to see if this is a mac fork of some kind.
*/
- if (is_ntfs_stream_smb_fname(smb_fname)) {
+ if (is_ntfs_stream_name(fname)) {
enum FAKE_FILE_TYPE fake_file_type;
- fake_file_type = is_fake_file(smb_fname);
+ fake_file_type = is_fake_file(fname);
if (fake_file_type != FAKE_FILE_TYPE_NONE) {
@@ -3441,34 +3426,56 @@ NTSTATUS create_file_default(connection_struct *conn,
* close it
*/
status = open_fake_file(req, conn, req->vuid,
- fake_file_type, smb_fname,
+ fake_file_type, fname,
access_mask, &fsp);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
- ZERO_STRUCT(smb_fname->st);
+ ZERO_STRUCT(sbuf);
goto done;
}
if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) {
- status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ goto fail;
+ }
+ }
+
+ if (create_file_flags & CFF_DOS_PATH) {
+ char *converted_fname;
+
+ SET_STAT_INVALID(sbuf);
+
+ status = unix_convert(talloc_tos(), conn, fname, False,
+ &converted_fname, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ fname = converted_fname;
+ } else {
+ if (psbuf != NULL) {
+ sbuf = *psbuf;
+ } else {
+ if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) {
+ SET_STAT_INVALID(sbuf);
+ }
+ }
+
}
/* All file access must go through check_name() */
- status = check_name(conn, smb_fname->base_name);
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
status = create_file_unixpath(
- conn, req, smb_fname, access_mask, share_access,
+ conn, req, fname, access_mask, share_access,
create_disposition, create_options, file_attributes,
oplock_request, allocation_size, sd, ea_list,
- &fsp, &info);
+ &fsp, &info, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
@@ -3481,6 +3488,9 @@ NTSTATUS create_file_default(connection_struct *conn,
if (pinfo != NULL) {
*pinfo = info;
}
+ if (psbuf != NULL) {
+ *psbuf = sbuf;
+ }
return NT_STATUS_OK;
fail:
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index cdb6093fe9..086ce1ac23 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -81,7 +81,7 @@ bool set_file_oplock(files_struct *fsp, int oplock_type)
DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, "
"tv_sec = %x, tv_usec = %x\n",
- fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id, (int)fsp->open_time.tv_sec,
(int)fsp->open_time.tv_usec ));
@@ -158,15 +158,14 @@ bool remove_oplock(files_struct *fsp)
NULL);
if (lck == NULL) {
DEBUG(0,("remove_oplock: failed to lock share entry for "
- "file %s\n", fsp_str_dbg(fsp)));
+ "file %s\n", fsp->fsp_name ));
return False;
}
ret = remove_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("remove_oplock: failed to remove share oplock for "
"file %s fnum %d, %s\n",
- fsp_str_dbg(fsp), fsp->fnum,
- file_id_string_tos(&fsp->file_id)));
+ fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id)));
}
release_file_oplock(fsp);
TALLOC_FREE(lck);
@@ -185,15 +184,14 @@ bool downgrade_oplock(files_struct *fsp)
NULL);
if (lck == NULL) {
DEBUG(0,("downgrade_oplock: failed to lock share entry for "
- "file %s\n", fsp_str_dbg(fsp)));
+ "file %s\n", fsp->fsp_name ));
return False;
}
ret = downgrade_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
"for file %s fnum %d, file_id %s\n",
- fsp_str_dbg(fsp), fsp->fnum,
- file_id_string_tos(&fsp->file_id)));
+ fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id)));
}
downgrade_file_oplock(fsp);
@@ -296,8 +294,7 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f
if(fsp->oplock_type == NO_OPLOCK) {
if( DEBUGLVL( 3 ) ) {
- dbgtext( "initial_break_processing: file %s ",
- fsp_str_dbg(fsp));
+ dbgtext( "initial_break_processing: file %s ", fsp->fsp_name );
dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n",
file_id_string_tos(&id), fsp->fh->gen_id );
dbgtext( "Allowing break to succeed regardless.\n" );
@@ -317,8 +314,7 @@ static void oplock_timeout_handler(struct event_context *ctx,
/* Remove the timed event handler. */
TALLOC_FREE(fsp->oplock_timeout);
- DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
- fsp_str_dbg(fsp)));
+ DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name));
global_client_failed_oplock_break = True;
remove_oplock(fsp);
reply_to_oplock_break_requests(fsp);
@@ -357,6 +353,7 @@ static void add_oplock_timeout_handler(files_struct *fsp)
void break_level2_to_none_async(files_struct *fsp)
{
char *break_msg;
+ bool sign_state;
if (fsp->oplock_type == NO_OPLOCK) {
/* We already got a "break to none" message and we've handled
@@ -379,7 +376,7 @@ void break_level2_to_none_async(files_struct *fsp)
DEBUG(10,("process_oplock_async_level2_break_message: sending break "
"to none message for fid %d, file %s\n", fsp->fnum,
- fsp_str_dbg(fsp)));
+ fsp->fsp_name));
/* Now send a break to none message to our client. */
break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
@@ -387,14 +384,20 @@ void break_level2_to_none_async(files_struct *fsp)
exit_server("Could not talloc break_msg\n");
}
+ /* Save the server smb signing state. */
+ sign_state = srv_oplock_set_signing(False);
+
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg, false, 0,
+ break_msg,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
+ /* Restore the sign state to what it was. */
+ srv_oplock_set_signing(sign_state);
+
TALLOC_FREE(break_msg);
/* Async level2 request, don't send a reply, just remove the oplock. */
@@ -433,7 +436,7 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
message_to_share_mode_entry(&msg, (char *)data->data);
DEBUG(10, ("Got oplock async level 2 break message from pid %s: "
- "%s/%lu\n", procid_str(talloc_tos(), &src),
+ "%s/%lu\n", procid_str(debug_ctx(), &src),
file_id_string_tos(&msg.id), msg.share_file_id));
fsp = initial_break_processing(msg.id, msg.share_file_id);
@@ -463,6 +466,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
files_struct *fsp;
char *break_msg;
bool break_to_level2 = False;
+ bool sign_state;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -478,7 +482,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
message_to_share_mode_entry(&msg, (char *)data->data);
DEBUG(10, ("Got oplock break message from pid %s: %s/%lu\n",
- procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id),
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
msg.share_file_id));
fsp = initial_break_processing(msg.id, msg.share_file_id);
@@ -510,7 +514,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
DEBUG(3, ("Already downgraded oplock on %s: %s\n",
file_id_string_tos(&fsp->file_id),
- fsp_str_dbg(fsp)));
+ fsp->fsp_name));
/* We just send the same message back. */
messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,
(uint8 *)data->data,
@@ -536,14 +540,20 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
wait_before_sending_break();
}
+ /* Save the server smb signing state. */
+ sign_state = srv_oplock_set_signing(False);
+
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg, false, 0,
+ break_msg,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
+ /* Restore the sign state to what it was. */
+ srv_oplock_set_signing(sign_state);
+
TALLOC_FREE(break_msg);
fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
@@ -570,6 +580,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
unsigned long file_id;
files_struct *fsp;
char *break_msg;
+ bool sign_state;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -586,7 +597,7 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
file_id = (unsigned long)IVAL(data->data, 24);
DEBUG(10, ("Got kernel oplock break message from pid %s: %s/%u\n",
- procid_str(talloc_tos(), &src), file_id_string_tos(&id),
+ procid_str(debug_ctx(), &src), file_id_string_tos(&id),
(unsigned int)file_id));
fsp = initial_break_processing(id, file_id);
@@ -609,14 +620,20 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
exit_server("Could not talloc break_msg\n");
}
+ /* Save the server smb signing state. */
+ sign_state = srv_oplock_set_signing(False);
+
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg, false, 0,
+ break_msg,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
+ /* Restore the sign state to what it was. */
+ srv_oplock_set_signing(sign_state);
+
TALLOC_FREE(break_msg);
fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
@@ -682,7 +699,7 @@ static void process_oplock_break_response(struct messaging_context *msg_ctx,
message_to_share_mode_entry(&msg, (char *)data->data);
DEBUG(10, ("Got oplock break response from pid %s: %s/%lu mid %u\n",
- procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id),
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
msg.share_file_id, (unsigned int)msg.op_mid));
/* Here's the hack from open.c, store the mid in the 'port' field */
@@ -711,7 +728,7 @@ static void process_open_retry_message(struct messaging_context *msg_ctx,
message_to_share_mode_entry(&msg, (char *)data->data);
DEBUG(10, ("Got open retry msg from pid %s: %s mid %u\n",
- procid_str(talloc_tos(), &src), file_id_string_tos(&msg.id),
+ procid_str(debug_ctx(), &src), file_id_string_tos(&msg.id),
(unsigned int)msg.op_mid));
schedule_deferred_open_smb_message(msg.op_mid);
@@ -744,7 +761,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
NULL);
if (lck == NULL) {
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
- "share mode entry for file %s.\n", fsp_str_dbg(fsp)));
+ "share mode entry for file %s.\n", fsp->fsp_name ));
return;
}
diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c
index dd32177988..89b8e0f7b5 100644
--- a/source3/smbd/oplock_irix.c
+++ b/source3/smbd/oplock_irix.c
@@ -212,8 +212,7 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx,
DEBUG(0,("irix_set_kernel_oplock: Unable to get "
"kernel oplock on file %s, file_id %s "
"gen_id = %ul. Error was %s\n",
- fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id,
strerror(errno) ));
} else {
@@ -221,7 +220,7 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx,
"file %s, fd = %d, file_id = %s, "
"gen_id = %ul. Another process had the file "
"open.\n",
- fsp_str_dbg(fsp), fsp->fh->fd,
+ fsp->fsp_name, fsp->fh->fd,
file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id ));
}
@@ -230,7 +229,7 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx,
DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
"gen_id = %ul\n",
- fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id));
return True;
@@ -251,8 +250,7 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx,
int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
dbgtext("irix_release_kernel_oplock: file %s, file_id = %s"
"gen_id = %ul, has kernel oplock state "
- "of %x.\n", fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
+ "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id, state );
}
@@ -265,8 +263,7 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx,
"removing kernel oplock on file " );
dbgtext("%s, file_id = %s gen_id = %ul. "
"Error was %s\n",
- fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id,
strerror(errno) );
}
diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index c60c745177..2bc0a55518 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -115,7 +115,7 @@ static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx,
if ( SMB_VFS_LINUX_SETLEASE(fsp, F_WRLCK) == -1) {
DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, "
"fd = %d, file_id = %s. (%s)\n",
- fsp_str_dbg(fsp), fsp->fh->fd,
+ fsp->fsp_name, fsp->fh->fd,
file_id_string_tos(&fsp->file_id),
strerror(errno)));
return False;
@@ -123,7 +123,7 @@ static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx,
DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, "
"file_id = %s gen_id = %lu\n",
- fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id));
return True;
@@ -144,8 +144,7 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx,
int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
dbgtext("linux_release_kernel_oplock: file %s, file_id = %s "
"gen_id = %lu has kernel oplock state "
- "of %x.\n", fsp_str_dbg(fsp),
- file_id_string_tos(&fsp->file_id),
+ "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id, state );
}
@@ -157,7 +156,7 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx,
dbgtext("linux_release_kernel_oplock: Error when "
"removing kernel oplock on file " );
dbgtext("%s, file_id = %s, gen_id = %lu. "
- "Error was %s\n", fsp_str_dbg(fsp),
+ "Error was %s\n", fsp->fsp_name,
file_id_string_tos(&fsp->file_id),
fsp->fh->gen_id, strerror(errno) );
}
diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c
index c80925ced3..d359f9c6f2 100644
--- a/source3/smbd/oplock_onefs.c
+++ b/source3/smbd/oplock_onefs.c
@@ -60,30 +60,29 @@ struct onefs_callback_record {
struct onefs_callback_record *callback_recs;
/**
- * Convert a onefs_callback_record to a debug string using the dbg_ctx().
+ * Convert a onefs_callback_record to a string.
*/
-const char *onefs_cb_record_str_dbg(const struct onefs_callback_record *r)
+static char *onefs_callback_record_str_static(const struct onefs_callback_record *r)
{
- char *result;
+ static fstring result;
if (r == NULL) {
- result = talloc_strdup(talloc_tos(), "NULL callback record");
+ fstrcpy(result, "NULL callback record");
return result;
}
switch (r->state) {
case ONEFS_OPEN_FILE:
- result = talloc_asprintf(talloc_tos(), "cb record %llu for "
- "file %s", r->id,
- fsp_str_dbg(r->data.fsp));
+ fstr_sprintf(result, "cb record %llu for file %s",
+ r->id, r->data.fsp->fsp_name);
+ break;
case ONEFS_WAITING_FOR_OPLOCK:
- result = talloc_asprintf(talloc_tos(), "cb record %llu for "
- "pending mid %d", r->id,
- (int)r->data.mid);
+ fstr_sprintf(result, "cb record %llu for pending mid %d",
+ r->id, (int)r->data.mid);
break;
default:
- result = talloc_asprintf(talloc_tos(), "cb record %llu unknown "
- "state %d", r->id, r->state);
+ fstr_sprintf(result, "cb record %llu unknown state %d",
+ r->id, r->state);
break;
}
@@ -103,7 +102,7 @@ static void debug_cb_records(const char *fn)
DEBUG(10, ("cb records (%s):\n", fn));
for (rec = callback_recs; rec; rec = rec->next) {
- DEBUGADD(10, ("%s\n", onefs_cb_record_str_dbg(rec)));
+ DEBUGADD(10, ("%s\n", onefs_callback_record_str_static(rec)));
}
}
@@ -128,7 +127,7 @@ static struct onefs_callback_record *onefs_find_cb(uint64_t id,
for (rec = callback_recs; rec; rec = rec->next) {
if (rec->id == id) {
DEBUG(10, ("found %s\n",
- onefs_cb_record_str_dbg(rec)));
+ onefs_callback_record_str_static(rec)));
break;
}
}
@@ -140,7 +139,7 @@ static struct onefs_callback_record *onefs_find_cb(uint64_t id,
if (rec->state != expected_state) {
DEBUG(0, ("Expected cb type %d, got %s", expected_state,
- onefs_cb_record_str_dbg(rec)));
+ onefs_callback_record_str_static(rec)));
SMB_ASSERT(0);
return NULL;
}
@@ -300,7 +299,7 @@ static void oplock_break_to_none_handler(uint64_t id)
}
DEBUG(10, ("oplock_break_to_none_handler called for file %s\n",
- fsp_str_dbg(cb->data.fsp)));
+ cb->data.fsp->fsp_name));
init_share_mode_entry(&sme, cb, FORCE_OPLOCK_BREAK_TO_NONE);
share_mode_entry_to_message(msg, &sme);
@@ -337,7 +336,7 @@ static void oplock_break_to_level_two_handler(uint64_t id)
}
DEBUG(10, ("oplock_break_to_level_two_handler called for file %s\n",
- fsp_str_dbg(cb->data.fsp)));
+ cb->data.fsp->fsp_name));
init_share_mode_entry(&sme, cb, LEVEL_II_OPLOCK);
share_mode_entry_to_message(msg, &sme);
@@ -378,7 +377,7 @@ static void oplock_revoked_handler(uint64_t id)
SMB_ASSERT(fsp->oplock_timeout == NULL);
DEBUG(0,("Level 1 oplock break failed for file %s. Forcefully "
- "revoking oplock\n", fsp_str_dbg(fsp)));
+ "revoking oplock\n", fsp->fsp_name));
global_client_failed_oplock_break = True;
remove_oplock(fsp);
@@ -414,7 +413,7 @@ static void semlock_available_handler(uint64_t id)
char *msg;
if (asprintf(&msg, "Semlock available on an open that wasn't "
"deferred: %s\n",
- onefs_cb_record_str_dbg(cb)) != -1) {
+ onefs_callback_record_str_static(cb)) != -1) {
smb_panic(msg);
}
smb_panic("Semlock available on an open that wasn't "
@@ -458,7 +457,7 @@ static void semlock_async_failure_handler(uint64_t id)
char *msg;
if (asprintf(&msg, "Semlock failure on an open that wasn't "
"deferred: %s\n",
- onefs_cb_record_str_dbg(cb)) != -1) {
+ onefs_callback_record_str_static(cb)) != -1) {
smb_panic(msg);
}
smb_panic("Semlock failure on an open that wasn't deferred\n");
@@ -502,7 +501,7 @@ static void onefs_release_kernel_oplock(struct kernel_oplocks *_ctx,
enum oplock_type oplock = onefs_samba_oplock_to_oplock(oplock_type);
DEBUG(10, ("onefs_release_kernel_oplock: Releasing %s to type %s\n",
- fsp_str_dbg(fsp), onefs_oplock_str(oplock)));
+ fsp->fsp_name, onefs_oplock_str(oplock)));
if (fsp->fh->fd == -1) {
DEBUG(1, ("no fd\n"));
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 755ff5d6cd..15d120a79c 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -25,9 +25,7 @@ enum server_allocated_state { SERVER_ALLOCATED_REQUIRED_YES,
SERVER_ALLOCATED_REQUIRED_NO,
SERVER_ALLOCATED_REQUIRED_ANY};
-static user_struct *get_valid_user_struct_internal(
- struct smbd_server_connection *sconn,
- uint16 vuid,
+static user_struct *get_valid_user_struct_internal(uint16 vuid,
enum server_allocated_state server_allocated)
{
user_struct *usp;
@@ -36,8 +34,7 @@ static user_struct *get_valid_user_struct_internal(
if (vuid == UID_FIELD_INVALID)
return NULL;
- usp=sconn->smb1.sessions.validated_users;
- for (;usp;usp=usp->next,count++) {
+ for (usp=validated_users;usp;usp=usp->next,count++) {
if (vuid == usp->vuid) {
switch (server_allocated) {
case SERVER_ALLOCATED_REQUIRED_YES:
@@ -53,8 +50,7 @@ static user_struct *get_valid_user_struct_internal(
break;
}
if (count > 10) {
- DLIST_PROMOTE(sconn->smb1.sessions.validated_users,
- usp);
+ DLIST_PROMOTE(validated_users, usp);
}
return usp;
}
@@ -69,26 +65,24 @@ static user_struct *get_valid_user_struct_internal(
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
-user_struct *get_valid_user_struct(struct smbd_server_connection *sconn,
- uint16 vuid)
+user_struct *get_valid_user_struct(uint16 vuid)
{
- return get_valid_user_struct_internal(sconn, vuid,
+ return get_valid_user_struct_internal(vuid,
SERVER_ALLOCATED_REQUIRED_YES);
}
-bool is_partial_auth_vuid(struct smbd_server_connection *sconn, uint16 vuid)
+bool is_partial_auth_vuid(uint16 vuid)
{
- return (get_partial_auth_user_struct(sconn, vuid) != NULL);
+ return (get_partial_auth_user_struct(vuid) != NULL);
}
/****************************************************************************
Get the user struct of a partial NTLMSSP login
****************************************************************************/
-user_struct *get_partial_auth_user_struct(struct smbd_server_connection *sconn,
- uint16 vuid)
+user_struct *get_partial_auth_user_struct(uint16 vuid)
{
- return get_valid_user_struct_internal(sconn, vuid,
+ return get_valid_user_struct_internal(vuid,
SERVER_ALLOCATED_REQUIRED_NO);
}
@@ -96,11 +90,11 @@ user_struct *get_partial_auth_user_struct(struct smbd_server_connection *sconn,
Invalidate a uid.
****************************************************************************/
-void invalidate_vuid(struct smbd_server_connection *sconn, uint16 vuid)
+void invalidate_vuid(uint16 vuid)
{
user_struct *vuser = NULL;
- vuser = get_valid_user_struct_internal(sconn, vuid,
+ vuser = get_valid_user_struct_internal(vuid,
SERVER_ALLOCATED_REQUIRED_ANY);
if (vuser == NULL) {
return;
@@ -112,29 +106,24 @@ void invalidate_vuid(struct smbd_server_connection *sconn, uint16 vuid)
auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
}
- DLIST_REMOVE(sconn->smb1.sessions.validated_users, vuser);
+ DLIST_REMOVE(validated_users, vuser);
/* clear the vuid from the 'cache' on each connection, and
from the vuid 'owner' of connections */
- conn_clear_vuid_caches(sconn, vuid);
+ conn_clear_vuid_caches(vuid);
TALLOC_FREE(vuser);
- sconn->smb1.sessions.num_validated_vuids--;
+ num_validated_vuids--;
}
/****************************************************************************
Invalidate all vuid entries for this process.
****************************************************************************/
-void invalidate_all_vuids(struct smbd_server_connection *sconn)
+void invalidate_all_vuids(void)
{
- if (sconn->allow_smb2) {
- return;
- }
-
- while (sconn->smb1.sessions.validated_users != NULL) {
- invalidate_vuid(sconn,
- sconn->smb1.sessions.validated_users->vuid);
+ while (validated_users != NULL) {
+ invalidate_vuid(validated_users->vuid);
}
}
@@ -152,7 +141,7 @@ static void increment_next_vuid(uint16_t *vuid)
Create a new partial auth user struct.
*****************************************************/
-int register_initial_vuid(struct smbd_server_connection *sconn)
+int register_initial_vuid(void)
{
user_struct *vuser;
@@ -163,7 +152,7 @@ int register_initial_vuid(struct smbd_server_connection *sconn)
}
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
- if (sconn->smb1.sessions.num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
+ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
return UID_FIELD_INVALID;
}
@@ -174,26 +163,25 @@ int register_initial_vuid(struct smbd_server_connection *sconn)
}
/* Allocate a free vuid. Yes this is a linear search... */
- while( get_valid_user_struct_internal(sconn,
- sconn->smb1.sessions.next_vuid,
+ while( get_valid_user_struct_internal(next_vuid,
SERVER_ALLOCATED_REQUIRED_ANY) != NULL ) {
- increment_next_vuid(&sconn->smb1.sessions.next_vuid);
+ increment_next_vuid(&next_vuid);
}
DEBUG(10,("register_initial_vuid: allocated vuid = %u\n",
- (unsigned int)sconn->smb1.sessions.next_vuid ));
+ (unsigned int)next_vuid ));
- vuser->vuid = sconn->smb1.sessions.next_vuid;
+ vuser->vuid = next_vuid;
/*
* This happens in an unfinished NTLMSSP session setup. We
* need to allocate a vuid between the first and second calls
* to NTLMSSP.
*/
- increment_next_vuid(&sconn->smb1.sessions.next_vuid);
- sconn->smb1.sessions.num_validated_vuids++;
+ increment_next_vuid(&next_vuid);
+ num_validated_vuids++;
- DLIST_ADD(sconn->smb1.sessions.validated_users, vuser);
+ DLIST_ADD(validated_users, vuser);
return vuser->vuid;
}
@@ -246,8 +234,7 @@ static int register_homes_share(const char *username)
*
*/
-int register_existing_vuid(struct smbd_server_connection *sconn,
- uint16 vuid,
+int register_existing_vuid(uint16 vuid,
auth_serversupplied_info *server_info,
DATA_BLOB response_blob,
const char *smb_name)
@@ -255,7 +242,7 @@ int register_existing_vuid(struct smbd_server_connection *sconn,
fstring tmp;
user_struct *vuser;
- vuser = get_partial_auth_user_struct(sconn, vuid);
+ vuser = get_partial_auth_user_struct(vuid);
if (!vuser) {
goto fail;
}
@@ -311,13 +298,11 @@ int register_existing_vuid(struct smbd_server_connection *sconn,
vuser->server_info->unix_name);
}
- if (srv_is_signing_negotiated(smbd_server_conn) &&
- !vuser->server_info->guest) {
+ if (srv_is_signing_negotiated() && !vuser->server_info->guest &&
+ !srv_signing_started()) {
/* Try and turn on server signing on the first non-guest
* sessionsetup. */
- srv_set_signing(smbd_server_conn,
- vuser->server_info->user_session_key,
- response_blob);
+ srv_set_signing(vuser->server_info->user_session_key, response_blob);
}
/* fill in the current_user_info struct */
@@ -331,7 +316,7 @@ int register_existing_vuid(struct smbd_server_connection *sconn,
fail:
if (vuser) {
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
}
return UID_FIELD_INVALID;
}
@@ -340,8 +325,7 @@ int register_existing_vuid(struct smbd_server_connection *sconn,
Add a name to the session users list.
****************************************************************************/
-void add_session_user(struct smbd_server_connection *sconn,
- const char *user)
+void add_session_user(const char *user)
{
struct passwd *pw;
char *tmp;
@@ -352,29 +336,28 @@ void add_session_user(struct smbd_server_connection *sconn,
return;
}
- if (sconn->smb1.sessions.session_userlist == NULL) {
- sconn->smb1.sessions.session_userlist = SMB_STRDUP(pw->pw_name);
+ if (session_userlist == NULL) {
+ session_userlist = SMB_STRDUP(pw->pw_name);
goto done;
}
- if (in_list(pw->pw_name,sconn->smb1.sessions.session_userlist,false)) {
+ if (in_list(pw->pw_name,session_userlist,False) ) {
goto done;
}
- if (strlen(sconn->smb1.sessions.session_userlist) > 128 * 1024) {
+ if (strlen(session_userlist) > 128 * 1024) {
DEBUG(3,("add_session_user: session userlist already "
"too large.\n"));
goto done;
}
- if (asprintf(&tmp, "%s %s",
- sconn->smb1.sessions.session_userlist, pw->pw_name) == -1) {
+ if (asprintf(&tmp, "%s %s", session_userlist, pw->pw_name) == -1) {
DEBUG(3, ("asprintf failed\n"));
goto done;
}
- SAFE_FREE(sconn->smb1.sessions.session_userlist);
- sconn->smb1.sessions.session_userlist = tmp;
+ SAFE_FREE(session_userlist);
+ session_userlist = tmp;
done:
TALLOC_FREE(pw);
}
@@ -384,13 +367,12 @@ void add_session_user(struct smbd_server_connection *sconn,
what Vista uses for the NTLMv2 calculation.
****************************************************************************/
-void add_session_workgroup(struct smbd_server_connection *sconn,
- const char *workgroup)
+void add_session_workgroup(const char *workgroup)
{
- if (sconn->smb1.sessions.session_workgroup) {
- SAFE_FREE(sconn->smb1.sessions.session_workgroup);
+ if (session_workgroup) {
+ SAFE_FREE(session_workgroup);
}
- sconn->smb1.sessions.session_workgroup = smb_xstrdup(workgroup);
+ session_workgroup = smb_xstrdup(workgroup);
}
/****************************************************************************
@@ -398,9 +380,9 @@ void add_session_workgroup(struct smbd_server_connection *sconn,
what Vista uses for the NTLMv2 calculation.
****************************************************************************/
-const char *get_session_workgroup(struct smbd_server_connection *sconn)
+const char *get_session_workgroup(void)
{
- return sconn->smb1.sessions.session_workgroup;
+ return session_workgroup;
}
/****************************************************************************
@@ -408,57 +390,45 @@ const char *get_session_workgroup(struct smbd_server_connection *sconn)
try lower case.
****************************************************************************/
-bool user_in_netgroup(struct smbd_server_connection *sconn,
- const char *user, const char *ngname)
+bool user_in_netgroup(const char *user, const char *ngname)
{
#ifdef HAVE_NETGROUP
fstring lowercase_user;
- if (sconn->smb1.sessions.my_yp_domain == NULL) {
- yp_get_default_domain(&sconn->smb1.sessions.my_yp_domain);
- }
+ if (my_yp_domain == NULL)
+ yp_get_default_domain(&my_yp_domain);
- if (sconn->smb1.sessions.my_yp_domain == NULL) {
+ if(my_yp_domain == NULL) {
DEBUG(5,("Unable to get default yp domain, "
"let's try without specifying it\n"));
}
DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- user,
- sconn->smb1.sessions.my_yp_domain?
- sconn->smb1.sessions.my_yp_domain:"(ANY)",
- ngname));
+ user, my_yp_domain?my_yp_domain:"(ANY)", ngname));
- if (innetgr(ngname, NULL, user, sconn->smb1.sessions.my_yp_domain)) {
+ if (innetgr(ngname, NULL, user, my_yp_domain)) {
DEBUG(5,("user_in_netgroup: Found\n"));
- return true;
- }
+ return (True);
+ } else {
- /*
- * Ok, innetgr is case sensitive. Try once more with lowercase
- * just in case. Attempt to fix #703. JRA.
- */
- fstrcpy(lowercase_user, user);
- strlower_m(lowercase_user);
+ /*
+ * Ok, innetgr is case sensitive. Try once more with lowercase
+ * just in case. Attempt to fix #703. JRA.
+ */
- if (strcmp(user,lowercase_user) == 0) {
- /* user name was already lower case! */
- return false;
- }
+ fstrcpy(lowercase_user, user);
+ strlower_m(lowercase_user);
- DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- lowercase_user,
- sconn->smb1.sessions.my_yp_domain?
- sconn->smb1.sessions.my_yp_domain:"(ANY)",
- ngname));
+ DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
+ lowercase_user, my_yp_domain?my_yp_domain:"(ANY)", ngname));
- if (innetgr(ngname, NULL, lowercase_user,
- sconn->smb1.sessions.my_yp_domain)) {
- DEBUG(5,("user_in_netgroup: Found\n"));
- return true;
+ if (innetgr(ngname, NULL, lowercase_user, my_yp_domain)) {
+ DEBUG(5,("user_in_netgroup: Found\n"));
+ return (True);
+ }
}
#endif /* HAVE_NETGROUP */
- return false;
+ return False;
}
/****************************************************************************
@@ -466,8 +436,7 @@ bool user_in_netgroup(struct smbd_server_connection *sconn,
and netgroup lists.
****************************************************************************/
-bool user_in_list(struct smbd_server_connection *sconn,
- const char *user,const char **list)
+bool user_in_list(const char *user,const char **list)
{
if (!list || !*list)
return False;
@@ -495,7 +464,7 @@ bool user_in_list(struct smbd_server_connection *sconn,
* Old behaviour. Check netgroup list
* followed by UNIX list.
*/
- if(user_in_netgroup(sconn, user, *list +1))
+ if(user_in_netgroup(user, *list +1))
return True;
if(user_in_group(user, *list +1))
return True;
@@ -507,7 +476,7 @@ bool user_in_list(struct smbd_server_connection *sconn,
*/
if(user_in_group(user, *list +2))
return True;
- if(user_in_netgroup(sconn, user, *list +2))
+ if(user_in_netgroup(user, *list +2))
return True;
} else {
@@ -526,7 +495,7 @@ bool user_in_list(struct smbd_server_connection *sconn,
/*
* Search netgroup list followed by UNIX list.
*/
- if(user_in_netgroup(sconn, user, *list +2))
+ if(user_in_netgroup(user, *list +2))
return True;
if(user_in_group(user, *list +2))
return True;
@@ -534,7 +503,7 @@ bool user_in_list(struct smbd_server_connection *sconn,
/*
* Just search netgroup list.
*/
- if(user_in_netgroup(sconn, user, *list +1))
+ if(user_in_netgroup(user, *list +1))
return True;
}
}
@@ -548,16 +517,16 @@ bool user_in_list(struct smbd_server_connection *sconn,
Check if a username is valid.
****************************************************************************/
-static bool user_ok(struct smbd_server_connection *sconn,
- const char *user, int snum)
+static bool user_ok(const char *user, int snum)
{
+ char **valid, **invalid;
bool ret;
+ valid = invalid = NULL;
ret = True;
if (lp_invalid_users(snum)) {
- char **invalid = str_list_copy(talloc_tos(),
- lp_invalid_users(snum));
+ invalid = str_list_copy(talloc_tos(), lp_invalid_users(snum));
if (invalid &&
str_list_substitute(invalid, "%S", lp_servicename(snum))) {
@@ -565,16 +534,15 @@ static bool user_ok(struct smbd_server_connection *sconn,
* around to pass to str_list_sub_basic() */
if ( invalid && str_list_sub_basic(invalid, "", "") ) {
- ret = !user_in_list(sconn, user,
+ ret = !user_in_list(user,
(const char **)invalid);
}
}
- TALLOC_FREE(invalid);
}
+ TALLOC_FREE(invalid);
if (ret && lp_valid_users(snum)) {
- char **valid = str_list_copy(talloc_tos(),
- lp_valid_users(snum));
+ valid = str_list_copy(talloc_tos(), lp_valid_users(snum));
if ( valid &&
str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
@@ -582,12 +550,11 @@ static bool user_ok(struct smbd_server_connection *sconn,
* around to pass to str_list_sub_basic() */
if ( valid && str_list_sub_basic(valid, "", "") ) {
- ret = user_in_list(sconn, user,
- (const char **)valid);
+ ret = user_in_list(user, (const char **)valid);
}
}
- TALLOC_FREE(valid);
}
+ TALLOC_FREE(valid);
if (ret && lp_onlyuser(snum)) {
char **user_list = str_list_make_v3(
@@ -595,8 +562,7 @@ static bool user_ok(struct smbd_server_connection *sconn,
if (user_list &&
str_list_substitute(user_list, "%S",
lp_servicename(snum))) {
- ret = user_in_list(sconn, user,
- (const char **)user_list);
+ ret = user_in_list(user, (const char **)user_list);
}
TALLOC_FREE(user_list);
}
@@ -608,21 +574,16 @@ static bool user_ok(struct smbd_server_connection *sconn,
Validate a group username entry. Return the username or NULL.
****************************************************************************/
-static char *validate_group(struct smbd_server_connection *sconn,
- char *group, DATA_BLOB password,int snum)
+static char *validate_group(char *group, DATA_BLOB password,int snum)
{
#ifdef HAVE_NETGROUP
{
char *host, *user, *domain;
- struct auth_context *actx = sconn->smb1.negprot.auth_context;
- bool enc = sconn->smb1.negprot.encrypted_passwords;
setnetgrent(group);
while (getnetgrent(&host, &user, &domain)) {
if (user) {
- if (user_ok(sconn, user, snum) &&
- password_ok(actx, enc,
- get_session_workgroup(sconn),
- user,password)) {
+ if (user_ok(user, snum) &&
+ password_ok(user,password)) {
endnetgrent();
return(user);
}
@@ -635,9 +596,6 @@ static char *validate_group(struct smbd_server_connection *sconn,
#ifdef HAVE_GETGRENT
{
struct group *gptr;
- struct auth_context *actx = sconn->smb1.negprot.auth_context;
- bool enc = sconn->smb1.negprot.encrypted_passwords;
-
setgrent();
while ((gptr = (struct group *)getgrent())) {
if (strequal(gptr->gr_name,group))
@@ -685,10 +643,8 @@ static char *validate_group(struct smbd_server_connection *sconn,
member = member_list;
while (*member) {
- if (user_ok(sconn, member,snum) &&
- password_ok(actx, enc,
- get_session_workgroup(sconn),
- member,password)) {
+ if (user_ok(member,snum) &&
+ password_ok(member,password)) {
char *name = talloc_strdup(talloc_tos(),
member);
SAFE_FREE(member_list);
@@ -716,13 +672,10 @@ static char *validate_group(struct smbd_server_connection *sconn,
Note this is *NOT* used when logging on using sessionsetup_and_X.
****************************************************************************/
-bool authorise_login(struct smbd_server_connection *sconn,
- int snum, fstring user, DATA_BLOB password,
+bool authorise_login(int snum, fstring user, DATA_BLOB password,
bool *guest)
{
bool ok = False;
- struct auth_context *actx = sconn->smb1.negprot.auth_context;
- bool enc = sconn->smb1.negprot.encrypted_passwords;
#ifdef DEBUG_PASSWORD
DEBUG(100,("authorise_login: checking authorisation on "
@@ -751,8 +704,8 @@ bool authorise_login(struct smbd_server_connection *sconn,
char *user_list = NULL;
char *saveptr;
- if (sconn->smb1.sessions.session_userlist)
- user_list = SMB_STRDUP(sconn->smb1.sessions.session_userlist);
+ if ( session_userlist )
+ user_list = SMB_STRDUP(session_userlist);
else
user_list = SMB_STRDUP("");
@@ -764,12 +717,10 @@ bool authorise_login(struct smbd_server_connection *sconn,
auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
fstring user2;
fstrcpy(user2,auser);
- if (!user_ok(sconn,user2,snum))
+ if (!user_ok(user2,snum))
continue;
- if (password_ok(actx, enc,
- get_session_workgroup(sconn),
- user2,password)) {
+ if (password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("authorise_login: ACCEPTED: session "
@@ -805,8 +756,7 @@ bool authorise_login(struct smbd_server_connection *sconn,
auser && !ok;
auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
if (*auser == '@') {
- auser = validate_group(sconn,auser+1,
- password,snum);
+ auser = validate_group(auser+1,password,snum);
if (auser) {
ok = True;
fstrcpy(user,auser);
@@ -817,10 +767,8 @@ bool authorise_login(struct smbd_server_connection *sconn,
} else {
fstring user2;
fstrcpy(user2,auser);
- if (user_ok(sconn,user2,snum) &&
- password_ok(actx, enc,
- get_session_workgroup(sconn),
- user2,password)) {
+ if (user_ok(user2,snum) &&
+ password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("authorise_login: ACCEPTED: "
@@ -853,7 +801,7 @@ bool authorise_login(struct smbd_server_connection *sconn,
*guest = True;
}
- if (ok && !user_ok(sconn, user, snum)) {
+ if (ok && !user_ok(user, snum)) {
DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
ok = False;
}
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 9bc3fdfdf6..878d171073 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -37,7 +37,6 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
{
struct connection_struct *conn = smb_req->conn;
struct files_struct *fsp;
- struct smb_filename *smb_fname = NULL;
NTSTATUS status;
status = file_new(smb_req, conn, &fsp);
@@ -51,19 +50,7 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
fsp->vuid = smb_req->vuid;
fsp->can_lock = false;
fsp->access_mask = FILE_READ_DATA | FILE_WRITE_DATA;
-
- status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- file_free(smb_req, fsp);
- return status;
- }
- status = fsp_set_smb_fname(fsp, smb_fname);
- TALLOC_FREE(smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- file_free(smb_req, fsp);
- return status;
- }
+ string_set(&fsp->fsp_name, name);
status = np_open(NULL, name, conn->client_address,
conn->server_info, &fsp->fake_file_handle);
@@ -105,7 +92,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
/* at a mailslot or something we really, really don't understand, */
/* not just something we really don't understand. */
if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return;
}
@@ -119,7 +106,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req)
* Hack for NT printers... JRA.
*/
if(should_fail_next_srvsvc_open(fname)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return;
}
#endif
@@ -171,7 +158,7 @@ void reply_pipe_write(struct smb_request *req)
struct tevent_req *subreq;
if (!fsp_is_np(fsp)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
@@ -192,7 +179,7 @@ void reply_pipe_write(struct smb_request *req)
data = req->buf + 3;
DEBUG(6, ("reply_pipe_write: %x name: %s len: %d\n", (int)fsp->fnum,
- fsp_str_dbg(fsp), (int)state->numtowrite));
+ fsp->fsp_name, (int)state->numtowrite));
subreq = np_write_send(state, smbd_event_context(),
fsp->fake_file_handle, data, state->numtowrite);
@@ -216,14 +203,8 @@ static void pipe_write_done(struct tevent_req *subreq)
status = np_write_recv(subreq, &nwritten);
TALLOC_FREE(subreq);
- if (nwritten < 0) {
- reply_nterror(req, status);
- goto send;
- }
-
- /* Looks bogus to me now. Needs to be removed ? JRA. */
- if ((nwritten == 0 && state->numtowrite != 0)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ if ((nwritten == 0 && state->numtowrite != 0) || (nwritten < 0)) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
goto send;
}
@@ -235,7 +216,6 @@ static void pipe_write_done(struct tevent_req *subreq)
send:
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -266,7 +246,7 @@ void reply_pipe_write_and_X(struct smb_request *req)
struct tevent_req *subreq;
if (!fsp_is_np(fsp)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
@@ -288,7 +268,7 @@ void reply_pipe_write_and_X(struct smb_request *req)
== (PIPE_START_MESSAGE|PIPE_RAW_MODE));
DEBUG(6, ("reply_pipe_write_and_X: %x name: %s len: %d\n",
- (int)fsp->fnum, fsp_str_dbg(fsp), (int)state->numtowrite));
+ (int)fsp->fnum, fsp->fsp_name, (int)state->numtowrite));
data = (uint8_t *)smb_base(req->inbuf) + smb_doff;
@@ -302,7 +282,7 @@ void reply_pipe_write_and_X(struct smb_request *req)
DEBUG(0,("reply_pipe_write_and_X: start of message "
"set and not enough data sent.(%u)\n",
(unsigned int)state->numtowrite ));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -332,15 +312,8 @@ static void pipe_write_andx_done(struct tevent_req *subreq)
status = np_write_recv(subreq, &nwritten);
TALLOC_FREE(subreq);
-
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto done;
- }
-
- /* Looks bogus to me now. Is this error message correct ? JRA. */
- if (nwritten != state->numtowrite) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ if (!NT_STATUS_IS_OK(status) || (nwritten != state->numtowrite)) {
+ reply_unixerror(req, ERRDOS,ERRnoaccess);
goto done;
}
@@ -389,7 +362,7 @@ void reply_pipe_read_and_X(struct smb_request *req)
#endif
if (!fsp_is_np(fsp)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 7342420a89..43edf21f7d 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -273,16 +273,15 @@ static void store_inheritance_attributes(files_struct *fsp,
ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
} else {
- ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
- SAMBA_POSIX_INHERITANCE_EA_NAME,
- pai_buf, store_size, 0);
+ ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,
+ pai_buf, store_size, 0);
}
SAFE_FREE(pai_buf);
DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n",
(unsigned int)sd_type,
- fsp_str_dbg(fsp)));
+ fsp->fsp_name));
if (ret == -1 && !no_acl_syscall_error(errno)) {
DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
@@ -621,10 +620,8 @@ static struct pai_val *fload_inherited_info(files_struct *fsp)
ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
} else {
- ret = SMB_VFS_GETXATTR(fsp->conn,
- fsp->fsp_name->base_name,
- SAMBA_POSIX_INHERITANCE_EA_NAME,
- pai_buf, pai_buf_size);
+ ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,
+ pai_buf, pai_buf_size);
}
if (ret == -1) {
@@ -642,8 +639,7 @@ static struct pai_val *fload_inherited_info(files_struct *fsp)
}
} while (ret == -1);
- DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
- (unsigned long)ret, fsp_str_dbg(fsp)));
+ DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name));
if (ret == -1) {
/* No attribute or not supported. */
@@ -662,7 +658,8 @@ static struct pai_val *fload_inherited_info(files_struct *fsp)
if (paiv) {
DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n",
- (unsigned int)paiv->sd_type, fsp_str_dbg(fsp)));
+ (unsigned int)paiv->sd_type,
+ fsp->fsp_name));
}
SAFE_FREE(pai_buf);
@@ -908,8 +905,29 @@ static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_AC
void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
{
- uid_to_sid( powner_sid, psbuf->st_ex_uid );
- gid_to_sid( pgroup_sid, psbuf->st_ex_gid );
+ uid_to_sid( powner_sid, psbuf->st_uid );
+ gid_to_sid( pgroup_sid, psbuf->st_gid );
+}
+
+/****************************************************************************
+ Is the identity in two ACEs equal ? Check both SID and uid/gid.
+****************************************************************************/
+
+static bool identity_in_ace_equal(canon_ace *ace1, canon_ace *ace2)
+{
+ if (sid_equal(&ace1->trustee, &ace2->trustee)) {
+ return True;
+ }
+ if (ace1->owner_type == ace2->owner_type) {
+ if (ace1->owner_type == UID_ACE &&
+ ace1->unix_ug.uid == ace2->unix_ug.uid) {
+ return True;
+ } else if (ace1->owner_type == GID_ACE &&
+ ace1->unix_ug.gid == ace2->unix_ug.gid) {
+ return True;
+ }
+ }
+ return False;
}
/****************************************************************************
@@ -918,7 +936,7 @@ void create_file_sids(const SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID
if the permissions become zero, delete the deny if the permissions are non zero.
****************************************************************************/
-static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
+static void merge_aces( canon_ace **pp_list_head )
{
canon_ace *l_head = *pp_list_head;
canon_ace *curr_ace_outer;
@@ -936,24 +954,12 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
- bool can_merge = false;
curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
- /* For file ACLs we can merge if the SIDs and ALLOW/DENY
- * types are the same. For directory acls we must also
- * ensure the POSIX ACL types are the same. */
+ if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
+ (curr_ace->attr == curr_ace_outer->attr)) {
- if (!dir_acl) {
- can_merge = (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
- (curr_ace->attr == curr_ace_outer->attr));
- } else {
- can_merge = (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
- (curr_ace->type == curr_ace_outer->type) &&
- (curr_ace->attr == curr_ace_outer->attr));
- }
-
- if (can_merge) {
if( DEBUGLVL( 10 )) {
dbgtext("merge_aces: Merging ACE's\n");
print_canon_ace( curr_ace_outer, 0);
@@ -962,13 +968,7 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
/* Merge two allow or two deny ACE's. */
- /* Theoretically we shouldn't merge a dir ACE if
- * one ACE has the CI flag set, and the other
- * ACE has the OI flag set, but this is rare
- * enough we can ignore it. */
-
curr_ace_outer->perms |= curr_ace->perms;
- curr_ace_outer->ace_flags |= curr_ace->ace_flags;
DLIST_REMOVE(l_head, curr_ace);
SAFE_FREE(curr_ace);
curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
@@ -997,7 +997,7 @@ static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
* we've put on the ACL, we know the deny must be the first one.
*/
- if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
+ if (identity_in_ace_equal(curr_ace, curr_ace_outer) &&
(curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
if( DEBUGLVL( 10 )) {
@@ -1068,7 +1068,7 @@ bool nt4_compatible_acls(void)
not get. Deny entries are implicit on get with ace->perms = 0.
****************************************************************************/
-uint32_t map_canon_ace_perms(int snum,
+static uint32_t map_canon_ace_perms(int snum,
enum security_ace_type *pacl_type,
mode_t perms,
bool directory_ace)
@@ -1107,10 +1107,9 @@ uint32_t map_canon_ace_perms(int snum,
nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
}
- }
-
- if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
- nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|DELETE_ACCESS);
+ if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
+ nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER);
+ }
}
DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
@@ -1394,7 +1393,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace,
ZERO_STRUCTP(pace);
pace->type = SMB_ACL_USER_OBJ;
pace->owner_type = UID_ACE;
- pace->unix_ug.uid = pst->st_ex_uid;
+ pace->unix_ug.uid = pst->st_uid;
pace->trustee = *pfile_owner_sid;
pace->attr = ALLOW_ACE;
@@ -1424,7 +1423,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace,
apply_default_perms(params, is_directory, pace, S_IRUSR);
} else {
- pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
}
DLIST_ADD(*pp_ace, pace);
@@ -1439,7 +1438,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace,
ZERO_STRUCTP(pace);
pace->type = SMB_ACL_GROUP_OBJ;
pace->owner_type = GID_ACE;
- pace->unix_ug.uid = pst->st_ex_gid;
+ pace->unix_ug.uid = pst->st_gid;
pace->trustee = *pfile_grp_sid;
pace->attr = ALLOW_ACE;
if (setting_acl) {
@@ -1450,7 +1449,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace,
pace->perms = 0;
apply_default_perms(params, is_directory, pace, S_IRGRP);
} else {
- pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP);
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
}
DLIST_ADD(*pp_ace, pace);
@@ -1472,7 +1471,7 @@ static bool ensure_canon_entry_valid(canon_ace **pp_ace,
pace->perms = 0;
apply_default_perms(params, is_directory, pace, S_IROTH);
} else
- pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH);
+ pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
DLIST_ADD(*pp_ace, pace);
}
@@ -1526,55 +1525,11 @@ static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID
}
/****************************************************************************
- If an ACE entry is SMB_ACL_USER_OBJ and not CREATOR_OWNER, map to SMB_ACL_USER.
- If an ACE entry is SMB_ACL_GROUP_OBJ and not CREATOR_GROUP, map to SMB_ACL_GROUP
-****************************************************************************/
-
-static bool dup_owning_ace(canon_ace *dir_ace, canon_ace *ace)
-{
- /* dir ace must be followings.
- SMB_ACL_USER_OBJ : trustee(CREATOR_OWNER) -> Posix ACL d:u::perm
- SMB_ACL_USER : not trustee -> Posix ACL u:user:perm
- SMB_ACL_USER_OBJ : trustee -> convert to SMB_ACL_USER : trustee
- Posix ACL u:trustee:perm
-
- SMB_ACL_GROUP_OBJ: trustee(CREATOR_GROUP) -> Posix ACL d:g::perm
- SMB_ACL_GROUP : not trustee -> Posix ACL g:group:perm
- SMB_ACL_GROUP_OBJ: trustee -> convert to SMB_ACL_GROUP : trustee
- Posix ACL g:trustee:perm
- */
-
- if (ace->type == SMB_ACL_USER_OBJ &&
- !(sid_equal(&ace->trustee, &global_sid_Creator_Owner))) {
- canon_ace *dup_ace = dup_canon_ace(ace);
-
- if (dup_ace == NULL) {
- return false;
- }
- dup_ace->type = SMB_ACL_USER;
- DLIST_ADD_END(dir_ace, dup_ace, canon_ace *);
- }
-
- if (ace->type == SMB_ACL_GROUP_OBJ &&
- !(sid_equal(&ace->trustee, &global_sid_Creator_Group))) {
- canon_ace *dup_ace = dup_canon_ace(ace);
-
- if (dup_ace == NULL) {
- return false;
- }
- dup_ace->type = SMB_ACL_GROUP;
- DLIST_ADD_END(dir_ace, dup_ace, canon_ace *);
- }
-
- return true;
-}
-
-/****************************************************************************
Unpack a SEC_DESC into two canonical ace lists.
****************************************************************************/
static bool create_canon_ace_lists(files_struct *fsp,
- const SMB_STRUCT_STAT *pst,
+ SMB_STRUCT_STAT *pst,
DOM_SID *pfile_owner_sid,
DOM_SID *pfile_grp_sid,
canon_ace **ppfile_ace,
@@ -1694,34 +1649,35 @@ static bool create_canon_ace_lists(files_struct *fsp,
current_ace->type = SMB_ACL_OTHER;
} else if (sid_equal(&current_ace->trustee, &global_sid_Creator_Owner)) {
current_ace->owner_type = UID_ACE;
- current_ace->unix_ug.uid = pst->st_ex_uid;
+ current_ace->unix_ug.uid = pst->st_uid;
current_ace->type = SMB_ACL_USER_OBJ;
/*
* The Creator Owner entry only specifies inheritable permissions,
* never access permissions. WinNT doesn't always set the ACE to
- * INHERIT_ONLY, though.
+ *INHERIT_ONLY, though.
*/
- psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
-
+ if (nt4_compatible_acls())
+ psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
} else if (sid_equal(&current_ace->trustee, &global_sid_Creator_Group)) {
current_ace->owner_type = GID_ACE;
- current_ace->unix_ug.gid = pst->st_ex_gid;
+ current_ace->unix_ug.gid = pst->st_gid;
current_ace->type = SMB_ACL_GROUP_OBJ;
/*
* The Creator Group entry only specifies inheritable permissions,
* never access permissions. WinNT doesn't always set the ACE to
- * INHERIT_ONLY, though.
+ *INHERIT_ONLY, though.
*/
- psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
+ if (nt4_compatible_acls())
+ psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
} else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid)) {
current_ace->owner_type = UID_ACE;
/* If it's the owning user, this is a user_obj, not
* a user. */
- if (current_ace->unix_ug.uid == pst->st_ex_uid) {
+ if (current_ace->unix_ug.uid == pst->st_uid) {
current_ace->type = SMB_ACL_USER_OBJ;
} else {
current_ace->type = SMB_ACL_USER;
@@ -1730,7 +1686,7 @@ static bool create_canon_ace_lists(files_struct *fsp,
current_ace->owner_type = GID_ACE;
/* If it's the primary group, this is a group_obj, not
* a group. */
- if (current_ace->unix_ug.gid == pst->st_ex_gid) {
+ if (current_ace->unix_ug.gid == pst->st_gid) {
current_ace->type = SMB_ACL_GROUP_OBJ;
} else {
current_ace->type = SMB_ACL_GROUP;
@@ -1795,12 +1751,8 @@ static bool create_canon_ace_lists(files_struct *fsp,
got_dir_allow = True;
if ((current_ace->attr == DENY_ACE) && got_dir_allow) {
- DEBUG(0,("create_canon_ace_lists: "
- "malformed ACL in "
- "inheritable ACL! Deny entry "
- "after Allow entry. Failing "
- "to set on file %s.\n",
- fsp_str_dbg(fsp)));
+ DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \
+Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
free_canon_ace_list(file_ace);
free_canon_ace_list(dir_ace);
return False;
@@ -1812,34 +1764,6 @@ static bool create_canon_ace_lists(files_struct *fsp,
}
/*
- * We have a lossy mapping: directory ACE entries
- * CREATOR_OWNER ------\
- * (map to) +---> SMB_ACL_USER_OBJ
- * owning sid ------/
- *
- * CREATOR_GROUP ------\
- * (map to) +---> SMB_ACL_GROUP_OBJ
- * primary group sid --/
- *
- * on set. And on read of a directory ACL
- *
- * SMB_ACL_USER_OBJ ----> CREATOR_OWNER
- * SMB_ACL_GROUP_OBJ ---> CREATOR_GROUP.
- *
- * Deal with this on set by duplicating
- * owning sid and primary group sid ACE
- * entries into the directory ACL.
- * Fix from Tsukasa Hamano <hamano@osstech.co.jp>.
- */
-
- if (!dup_owning_ace(dir_ace, current_ace)) {
- DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
- free_canon_ace_list(file_ace);
- free_canon_ace_list(dir_ace);
- return false;
- }
-
- /*
* If this is not an inherit only ACE we need to add a duplicate
* to the file acl.
*/
@@ -1859,13 +1783,6 @@ static bool create_canon_ace_lists(files_struct *fsp,
* pointer is now owned by the dir_ace list.
*/
current_ace = dup_ace;
- /* We've essentially split this ace into two,
- * and added the ace with inheritance request
- * bits to the directory ACL. Drop those bits for
- * the ACE we're adding to the file list. */
- current_ace->ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
- SEC_ACE_FLAG_CONTAINER_INHERIT|
- SEC_ACE_FLAG_INHERIT_ONLY);
} else {
/*
* We must not free current_ace here as its
@@ -1892,10 +1809,8 @@ static bool create_canon_ace_lists(files_struct *fsp,
got_file_allow = True;
if ((current_ace->attr == DENY_ACE) && got_file_allow) {
- DEBUG(0,("create_canon_ace_lists: malformed "
- "ACL in file ACL ! Deny entry after "
- "Allow entry. Failing to set on file "
- "%s.\n", fsp_str_dbg(fsp)));
+ DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \
+Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
free_canon_ace_list(file_ace);
free_canon_ace_list(dir_ace);
return False;
@@ -2275,14 +2190,10 @@ static mode_t create_default_mode(files_struct *fsp, bool interitable_mode)
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
mode_t or_bits = (mode_t)0;
- mode_t mode;
-
- if (interitable_mode) {
- mode = unix_mode(fsp->conn, FILE_ATTRIBUTE_ARCHIVE,
- fsp->fsp_name, NULL);
- } else {
- mode = S_IRUSR;
- }
+ mode_t mode = interitable_mode
+ ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name,
+ NULL )
+ : S_IRUSR;
if (fsp->is_directory)
mode |= (S_IWUSR|S_IXUSR);
@@ -2309,7 +2220,7 @@ static mode_t create_default_mode(files_struct *fsp, bool interitable_mode)
****************************************************************************/
static bool unpack_canon_ace(files_struct *fsp,
- const SMB_STRUCT_STAT *pst,
+ SMB_STRUCT_STAT *pst,
DOM_SID *pfile_owner_sid,
DOM_SID *pfile_grp_sid,
canon_ace **ppfile_ace,
@@ -2317,7 +2228,6 @@ static bool unpack_canon_ace(files_struct *fsp,
uint32 security_info_sent,
const SEC_DESC *psd)
{
- SMB_STRUCT_STAT st;
canon_ace *file_ace = NULL;
canon_ace *dir_ace = NULL;
@@ -2357,10 +2267,10 @@ static bool unpack_canon_ace(files_struct *fsp,
*/
print_canon_ace_list( "file ace - before merge", file_ace);
- merge_aces( &file_ace, false);
+ merge_aces( &file_ace );
print_canon_ace_list( "dir ace - before merge", dir_ace);
- merge_aces( &dir_ace, true);
+ merge_aces( &dir_ace );
/*
* NT ACLs are order dependent. Go through the acl lists and
@@ -2381,17 +2291,14 @@ static bool unpack_canon_ace(files_struct *fsp,
print_canon_ace_list( "file ace - before valid", file_ace);
- st = *pst;
-
/*
* A default 3 element mode entry for a file should be r-- --- ---.
* A default 3 element mode entry for a directory should be rwx --- ---.
*/
- st.st_ex_mode = create_default_mode(fsp, False);
+ pst->st_mode = create_default_mode(fsp, False);
- if (!ensure_canon_entry_valid(&file_ace, fsp->conn->params,
- fsp->is_directory, pfile_owner_sid, pfile_grp_sid, &st, True)) {
+ if (!ensure_canon_entry_valid(&file_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
free_canon_ace_list(file_ace);
free_canon_ace_list(dir_ace);
return False;
@@ -2405,10 +2312,9 @@ static bool unpack_canon_ace(files_struct *fsp,
* it's a directory.
*/
- st.st_ex_mode = create_default_mode(fsp, True);
+ pst->st_mode = create_default_mode(fsp, True);
- if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp->conn->params,
- fsp->is_directory, pfile_owner_sid, pfile_grp_sid, &st, True)) {
+ if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp->conn->params, fsp->is_directory, pfile_owner_sid, pfile_grp_sid, pst, True)) {
free_canon_ace_list(file_ace);
free_canon_ace_list(dir_ace);
return False;
@@ -2520,7 +2426,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
case SMB_ACL_USER_OBJ:
/* Get the SID from the owner. */
sid_copy(&sid, powner);
- unix_ug.uid = psbuf->st_ex_uid;
+ unix_ug.uid = psbuf->st_uid;
owner_type = UID_ACE;
break;
case SMB_ACL_USER:
@@ -2530,6 +2436,17 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
continue;
}
+ /*
+ * A SMB_ACL_USER entry for the owner is shadowed by the
+ * SMB_ACL_USER_OBJ entry and Windows also cannot represent
+ * that entry, so we ignore it. We also don't create such
+ * entries out of the blue when setting ACLs, so a get/set
+ * cycle will drop them.
+ */
+ if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) {
+ SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
+ continue;
+ }
uid_to_sid( &sid, *puid);
unix_ug.uid = *puid;
owner_type = UID_ACE;
@@ -2539,7 +2456,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
case SMB_ACL_GROUP_OBJ:
/* Get the SID from the owning group. */
sid_copy(&sid, pgroup);
- unix_ug.gid = psbuf->st_ex_gid;
+ unix_ug.gid = psbuf->st_gid;
owner_type = GID_ACE;
break;
case SMB_ACL_GROUP:
@@ -2593,7 +2510,7 @@ static canon_ace *canonicalise_acl(struct connection_struct *conn,
*/
if (!ensure_canon_entry_valid(&l_head, conn->params,
- S_ISDIR(psbuf->st_ex_mode), powner, pgroup,
+ S_ISDIR(psbuf->st_mode), powner, pgroup,
psbuf, False))
goto fail;
@@ -2654,7 +2571,8 @@ static bool current_user_in_group(gid_t gid)
****************************************************************************/
static bool acl_group_override(connection_struct *conn,
- const struct smb_filename *smb_fname)
+ SMB_STRUCT_STAT *psbuf,
+ const char *fname)
{
if ((errno != EPERM) && (errno != EACCES)) {
return false;
@@ -2662,13 +2580,13 @@ static bool acl_group_override(connection_struct *conn,
/* file primary group == user primary or supplementary group */
if (lp_acl_group_control(SNUM(conn)) &&
- current_user_in_group(smb_fname->st.st_ex_gid)) {
+ current_user_in_group(psbuf->st_gid)) {
return true;
}
/* user has writeable permission */
if (lp_dos_filemode(SNUM(conn)) &&
- can_write_to_file(conn, smb_fname)) {
+ can_write_to_file(conn, fname, psbuf)) {
return true;
}
@@ -2679,11 +2597,7 @@ static bool acl_group_override(connection_struct *conn,
Attempt to apply an ACL to a file or directory.
****************************************************************************/
-static bool set_canon_ace_list(files_struct *fsp,
- canon_ace *the_ace,
- bool default_ace,
- const SMB_STRUCT_STAT *psbuf,
- bool *pacl_set_support)
+static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool default_ace, SMB_STRUCT_STAT *psbuf, bool *pacl_set_support)
{
connection_struct *conn = fsp->conn;
bool ret = False;
@@ -2697,9 +2611,6 @@ static bool set_canon_ace_list(files_struct *fsp,
bool needs_mask = False;
mode_t mask_perms = 0;
- /* Use the psbuf that was passed in. */
- fsp->fsp_name->st = *psbuf;
-
#if defined(POSIX_ACL_NEEDS_MASK)
/* HP-UX always wants to have a mask (called "class" there). */
needs_mask = True;
@@ -2716,7 +2627,7 @@ static bool set_canon_ace_list(files_struct *fsp,
default_ace ? "default" : "file", strerror(errno) ));
}
*pacl_set_support = False;
- goto fail;
+ return False;
}
if( DEBUGLVL( 10 )) {
@@ -2856,8 +2767,7 @@ static bool set_canon_ace_list(files_struct *fsp,
*/
if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
- if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name->base_name,
- the_acl_type, the_acl) == -1) {
+ if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
/*
* Some systems allow all the above calls and only fail with no ACL support
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
@@ -2866,18 +2776,14 @@ static bool set_canon_ace_list(files_struct *fsp,
*pacl_set_support = False;
}
- if (acl_group_override(conn, fsp->fsp_name)) {
+ if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
int sret;
- DEBUG(5,("set_canon_ace_list: acl group "
- "control on and current user in file "
- "%s primary group.\n",
- fsp_str_dbg(fsp)));
+ DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
+ fsp->fsp_name ));
become_root();
- sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
- fsp->fsp_name->base_name, the_acl_type,
- the_acl);
+ sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
unbecome_root();
if (sret == 0) {
ret = True;
@@ -2885,12 +2791,9 @@ static bool set_canon_ace_list(files_struct *fsp,
}
if (ret == False) {
- DEBUG(2,("set_canon_ace_list: "
- "sys_acl_set_file type %s failed for "
- "file %s (%s).\n",
- the_acl_type == SMB_ACL_TYPE_DEFAULT ?
- "directory default" : "file",
- fsp_str_dbg(fsp), strerror(errno)));
+ DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
+ the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
+ fsp->fsp_name, strerror(errno) ));
goto fail;
}
}
@@ -2904,13 +2807,11 @@ static bool set_canon_ace_list(files_struct *fsp,
*pacl_set_support = False;
}
- if (acl_group_override(conn, fsp->fsp_name)) {
+ if (acl_group_override(conn, psbuf, fsp->fsp_name)) {
int sret;
- DEBUG(5,("set_canon_ace_list: acl group "
- "control on and current user in file "
- "%s primary group.\n",
- fsp_str_dbg(fsp)));
+ DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
+ fsp->fsp_name ));
become_root();
sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl);
@@ -2921,10 +2822,8 @@ static bool set_canon_ace_list(files_struct *fsp,
}
if (ret == False) {
- DEBUG(2,("set_canon_ace_list: "
- "sys_acl_set_file failed for file %s "
- "(%s).\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
goto fail;
}
}
@@ -2992,9 +2891,8 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
mode_t or_bits;
if (ace_count != 3) {
- DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
- "entries for file %s to convert to posix perms.\n",
- fsp_str_dbg(fsp)));
+ DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \
+posix perms.\n", fsp->fsp_name ));
return False;
}
@@ -3008,8 +2906,8 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
}
if (!owner_ace || !group_ace || !other_ace) {
- DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get "
- "standard entries for file %s.\n", fsp_str_dbg(fsp)));
+ DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n",
+ fsp->fsp_name ));
return False;
}
@@ -3043,10 +2941,9 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file
*posix_perms = (((*posix_perms) & and_bits)|or_bits);
- DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o "
- "to perm=0%o for file %s.\n", (int)owner_ace->perms,
- (int)group_ace->perms, (int)other_ace->perms,
- (int)*posix_perms, fsp_str_dbg(fsp)));
+ DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n",
+ (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms,
+ fsp->fsp_name ));
return True;
}
@@ -3222,7 +3119,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
goto done;
}
- if (S_ISDIR(sbuf->st_ex_mode) && def_acl) {
+ if (S_ISDIR(sbuf->st_mode) && def_acl) {
dir_ace = canonicalise_acl(conn, name, def_acl,
sbuf,
&global_sid_Creator_Owner,
@@ -3306,7 +3203,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
uint32_t acc = map_canon_ace_perms(SNUM(conn),
&nt_acl_type,
ace->perms,
- S_ISDIR(sbuf->st_ex_mode));
+ S_ISDIR(sbuf->st_mode));
init_sec_ace(&nt_ace_list[num_aces++],
&ace->trustee,
nt_acl_type,
@@ -3327,7 +3224,7 @@ static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
uint32_t acc = map_canon_ace_perms(SNUM(conn),
&nt_acl_type,
ace->perms,
- S_ISDIR(sbuf->st_ex_mode));
+ S_ISDIR(sbuf->st_mode));
init_sec_ace(&nt_ace_list[num_aces++],
&ace->trustee,
nt_acl_type,
@@ -3439,12 +3336,11 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
*ppdesc = NULL;
- DEBUG(10,("posix_fget_nt_acl: called for file %s\n",
- fsp_str_dbg(fsp)));
+ DEBUG(10,("posix_fget_nt_acl: called for file %s\n", fsp->fsp_name ));
/* can it happen that fsp_name == NULL ? */
if (fsp->is_directory || fsp->fh->fd == -1) {
- return posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name,
+ return posix_get_nt_acl(fsp->conn, fsp->fsp_name,
security_info, ppdesc);
}
@@ -3458,35 +3354,30 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
pal = fload_inherited_info(fsp);
- return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name,
- &sbuf, pal, posix_acl, NULL,
- security_info, ppdesc);
+ return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name, &sbuf, pal,
+ posix_acl, NULL, security_info, ppdesc);
}
NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
uint32_t security_info, SEC_DESC **ppdesc)
{
+ SMB_STRUCT_STAT sbuf;
SMB_ACL_T posix_acl = NULL;
SMB_ACL_T def_acl = NULL;
struct pai_val *pal;
- struct smb_filename smb_fname;
int ret;
*ppdesc = NULL;
DEBUG(10,("posix_get_nt_acl: called for file %s\n", name ));
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = discard_const_p(char, name);
-
/* Get the stat struct for the owner info. */
if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, &smb_fname);
+ ret = SMB_VFS_LSTAT(conn, name, &sbuf);
} else {
- ret = SMB_VFS_STAT(conn, &smb_fname);
+ ret = SMB_VFS_STAT(conn, name, &sbuf);
}
-
- if (ret == -1) {
+ if(ret != 0) {
return map_nt_error_from_unix(errno);
}
@@ -3494,16 +3385,15 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS);
/* If it's a directory get the default POSIX ACL. */
- if(S_ISDIR(smb_fname.st.st_ex_mode)) {
+ if(S_ISDIR(sbuf.st_mode)) {
def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT);
def_acl = free_empty_sys_acl(conn, def_acl);
}
pal = load_inherited_info(conn, name);
- return posix_get_nt_acl_common(conn, name, &smb_fname.st, pal,
- posix_acl, def_acl, security_info,
- ppdesc);
+ return posix_get_nt_acl_common(conn, name, &sbuf, pal, posix_acl,
+ def_acl, security_info, ppdesc);
}
/****************************************************************************
@@ -3516,11 +3406,12 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name,
then allow chown to the currently authenticated user.
****************************************************************************/
-int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
- uid_t uid, gid_t gid)
+int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
{
int ret;
files_struct *fsp;
+ SMB_STRUCT_STAT st;
+ bool posix_paths = lp_posix_pathnames();
if(!CAN_WRITE(conn)) {
return -1;
@@ -3528,12 +3419,11 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
/* Case (1). */
/* try the direct way first */
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid, gid);
+ if (posix_paths) {
+ ret = SMB_VFS_LCHOWN(conn, fname, uid, gid);
} else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid);
+ ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
}
-
if (ret == 0)
return 0;
@@ -3552,13 +3442,7 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
become_root();
/* Keep the current file gid the same - take ownership doesn't imply group change. */
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- } else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- }
+ ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
unbecome_root();
return ret;
}
@@ -3579,33 +3463,22 @@ int try_chown(connection_struct *conn, struct smb_filename *smb_fname,
return -1;
}
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ if (posix_paths) {
+ ret = SMB_VFS_LSTAT(conn,fname,&st);
} else {
- ret = SMB_VFS_STAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn,fname,&st);
}
-
- if (ret == -1) {
+ if (ret != 0) {
return -1;
}
- if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) {
+ if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, &st, &fsp))) {
return -1;
}
become_root();
/* Keep the current file gid the same. */
- if (fsp->fh->fd == -1) {
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- } else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid,
- (gid_t)-1);
- }
- } else {
- ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
- }
+ ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
unbecome_root();
close_file_fchmod(NULL, fsp);
@@ -3624,39 +3497,35 @@ NTSTATUS append_parent_acl(files_struct *fsp,
const SEC_DESC *pcsd,
SEC_DESC **pp_new_sd)
{
- struct smb_filename *smb_dname = NULL;
SEC_DESC *parent_sd = NULL;
files_struct *parent_fsp = NULL;
TALLOC_CTX *mem_ctx = talloc_tos();
char *parent_name = NULL;
SEC_ACE *new_ace = NULL;
unsigned int num_aces = pcsd->dacl->num_aces;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
int info;
unsigned int i, j;
SEC_DESC *psd = dup_sec_desc(talloc_tos(), pcsd);
bool is_dacl_protected = (pcsd->type & SEC_DESC_DACL_PROTECTED);
+ ZERO_STRUCT(sbuf);
+
if (psd == NULL) {
return NT_STATUS_NO_MEMORY;
}
- if (!parent_dirname(mem_ctx, fsp->fsp_name->base_name, &parent_name,
- NULL)) {
+ if (!parent_dirname(mem_ctx, fsp->fsp_name, &parent_name, NULL)) {
return NT_STATUS_NO_MEMORY;
}
- status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL,
- &smb_dname);
- if (!NT_STATUS_IS_OK(status)) {
- goto fail;
- }
-
status = SMB_VFS_CREATE_FILE(
fsp->conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- smb_dname, /* fname */
+ parent_name, /* fname */
+ 0, /* create_file_flags */
FILE_READ_ATTRIBUTES, /* access_mask */
FILE_SHARE_NONE, /* share_access */
FILE_OPEN, /* create_disposition*/
@@ -3667,18 +3536,17 @@ NTSTATUS append_parent_acl(files_struct *fsp,
NULL, /* sd */
NULL, /* ea_list */
&parent_fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(smb_dname);
return status;
}
- status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name,
+ status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name,
DACL_SECURITY_INFORMATION, &parent_sd );
close_file(NULL, parent_fsp, NORMAL_CLOSE);
- TALLOC_FREE(smb_dname);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -3724,7 +3592,7 @@ NTSTATUS append_parent_acl(files_struct *fsp,
"ignoring non container "
"inherit flags %u on ACE with sid %s "
"from parent %s\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
(unsigned int)se->flags,
sid_string_dbg(&se->trustee),
parent_name));
@@ -3737,7 +3605,7 @@ NTSTATUS append_parent_acl(files_struct *fsp,
"ignoring non object "
"inherit flags %u on ACE with sid %s "
"from parent %s\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
(unsigned int)se->flags,
sid_string_dbg(&se->trustee),
parent_name));
@@ -3761,7 +3629,7 @@ NTSTATUS append_parent_acl(files_struct *fsp,
DEBUG(10,("append_parent_acl: path %s "
"ignoring ACE with protected sid %s "
"from parent %s\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
sid_string_dbg(&se->trustee),
parent_name));
continue;
@@ -3799,7 +3667,7 @@ NTSTATUS append_parent_acl(files_struct *fsp,
DEBUG(10,("append_parent_acl: path %s "
"inheriting ACE with sid %s "
"from parent %s\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
sid_string_dbg(&se->trustee),
parent_name));
}
@@ -3825,6 +3693,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
gid_t grp = (gid_t)-1;
+ SMB_STRUCT_STAT sbuf;
DOM_SID file_owner_sid;
DOM_SID file_grp_sid;
canon_ace *file_ace_list = NULL;
@@ -3835,9 +3704,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
bool set_acl_as_root = false;
bool acl_set_support = false;
bool ret = false;
+ bool posix_paths = lp_posix_pathnames();
+ int sret;
- DEBUG(10,("set_nt_acl: called for file %s\n",
- fsp_str_dbg(fsp)));
+ DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
if (!CAN_WRITE(conn)) {
DEBUG(10,("set acl rejected on read-only share\n"));
@@ -3848,13 +3718,22 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
* Get the current state of the file.
*/
- status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if(fsp->is_directory || fsp->fh->fd == -1) {
+ if (posix_paths) {
+ sret = SMB_VFS_LSTAT(fsp->conn,fsp->fsp_name, &sbuf);
+ } else {
+ sret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
+ }
+ if (sret != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ if(SMB_VFS_FSTAT(fsp, &sbuf) != 0)
+ return map_nt_error_from_unix(errno);
}
/* Save the original element we check against. */
- orig_mode = fsp->fsp_name->st.st_ex_mode;
+ orig_mode = sbuf.st_mode;
/*
* Unpack the user/group/world id's.
@@ -3871,18 +3750,14 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
* Noticed by Simo.
*/
- if (((user != (uid_t)-1) && (fsp->fsp_name->st.st_ex_uid != user)) ||
- (( grp != (gid_t)-1) && (fsp->fsp_name->st.st_ex_gid != grp))) {
+ if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
- fsp_str_dbg(fsp), (unsigned int)user,
- (unsigned int)grp));
-
- if(try_chown(fsp->conn, fsp->fsp_name, user, grp) == -1) {
- DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error "
- "= %s.\n", fsp_str_dbg(fsp),
- (unsigned int)user, (unsigned int)grp,
- strerror(errno)));
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
+
+ if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
if (errno == EPERM) {
return NT_STATUS_INVALID_OWNER;
}
@@ -3894,13 +3769,32 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
* (suid/sgid bits, for instance)
*/
- status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if(fsp->is_directory) {
+ if (posix_paths) {
+ sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name, &sbuf);
+ } else {
+ sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
+ }
+ if (sret != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ if(fsp->fh->fd == -1) {
+ if (posix_paths) {
+ sret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name, &sbuf);
+ } else {
+ sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
+ }
+ } else {
+ sret = SMB_VFS_FSTAT(fsp, &sbuf);
+ }
+
+ if(sret != 0)
+ return map_nt_error_from_unix(errno);
}
/* Save the original element we check against. */
- orig_mode = fsp->fsp_name->st.st_ex_mode;
+ orig_mode = sbuf.st_mode;
/* If we successfully chowned, we know we must
* be able to set the acl, so do it as root.
@@ -3908,11 +3802,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
set_acl_as_root = true;
}
- create_file_sids(&fsp->fsp_name->st, &file_owner_sid, &file_grp_sid);
+ create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
- acl_perms = unpack_canon_ace(fsp, &fsp->fsp_name->st, &file_owner_sid,
- &file_grp_sid, &file_ace_list,
- &dir_ace_list, security_info_sent, psd);
+ acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
+ &file_ace_list, &dir_ace_list, security_info_sent, psd);
/* Ignore W2K traverse DACL set. */
if (!file_ace_list && !dir_ace_list) {
@@ -3945,15 +3838,12 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- ret = set_canon_ace_list(fsp, file_ace_list, false,
- &fsp->fsp_name->st, &acl_set_support);
+ ret = set_canon_ace_list(fsp, file_ace_list, False, &sbuf, &acl_set_support);
if (set_acl_as_root) {
unbecome_root();
}
if (acl_set_support && ret == false) {
- DEBUG(3,("set_nt_acl: failed to set file acl on file "
- "%s (%s).\n", fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
return map_nt_error_from_unix(errno);
@@ -3965,23 +3855,17 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- ret = set_canon_ace_list(fsp, dir_ace_list, true,
- &fsp->fsp_name->st,
- &acl_set_support);
+ ret = set_canon_ace_list(fsp, dir_ace_list, True, &sbuf, &acl_set_support);
if (set_acl_as_root) {
unbecome_root();
}
if (ret == false) {
- DEBUG(3,("set_nt_acl: failed to set default "
- "acl on directory %s (%s).\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
return map_nt_error_from_unix(errno);
}
} else {
- int sret = -1;
-
/*
* No default ACL - delete one if it exists.
*/
@@ -3989,24 +3873,18 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (set_acl_as_root) {
become_root();
}
- sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn,
- fsp->fsp_name->base_name);
+ sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
if (set_acl_as_root) {
unbecome_root();
}
if (sret == -1) {
- if (acl_group_override(conn, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group "
- "control on and current user "
- "in file %s primary group. "
- "Override delete_def_acl\n",
- fsp_str_dbg(fsp)));
+ if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
+ DEBUG(5,("set_nt_acl: acl group control on and "
+ "current user in file %s primary group. Override delete_def_acl\n",
+ fsp->fsp_name ));
become_root();
- sret =
- SMB_VFS_SYS_ACL_DELETE_DEF_FILE(
- conn,
- fsp->fsp_name->base_name);
+ sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
unbecome_root();
}
@@ -4043,47 +3921,36 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- DEBUG(3,("set_nt_acl: failed to convert file acl to "
- "posix permissions for file %s.\n",
- fsp_str_dbg(fsp)));
+ DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
+ fsp->fsp_name ));
return NT_STATUS_ACCESS_DENIED;
}
if (orig_mode != posix_perms) {
- int sret = -1;
-
DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
- fsp_str_dbg(fsp), (unsigned int)posix_perms));
+ fsp->fsp_name, (unsigned int)posix_perms ));
if (set_acl_as_root) {
become_root();
}
- sret = SMB_VFS_CHMOD(conn, fsp->fsp_name->base_name,
- posix_perms);
+ sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
if (set_acl_as_root) {
unbecome_root();
}
if(sret == -1) {
- if (acl_group_override(conn, fsp->fsp_name)) {
- DEBUG(5,("set_nt_acl: acl group "
- "control on and current user "
- "in file %s primary group. "
- "Override chmod\n",
- fsp_str_dbg(fsp)));
+ if (acl_group_override(conn, &sbuf, fsp->fsp_name)) {
+ DEBUG(5,("set_nt_acl: acl group control on and "
+ "current user in file %s primary group. Override chmod\n",
+ fsp->fsp_name ));
become_root();
- sret = SMB_VFS_CHMOD(conn,
- fsp->fsp_name->base_name,
- posix_perms);
+ sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
unbecome_root();
}
if (sret == -1) {
- DEBUG(3,("set_nt_acl: chmod %s, 0%o "
- "failed. Error = %s.\n",
- fsp_str_dbg(fsp),
- (unsigned int)posix_perms,
- strerror(errno)));
+ DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
return map_nt_error_from_unix(errno);
@@ -4095,9 +3962,6 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- /* Ensure the stat struct in the fsp is correct. */
- status = vfs_stat_fsp(fsp);
-
return NT_STATUS_OK;
}
@@ -4465,12 +4329,12 @@ static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_
on the directory.
****************************************************************************/
-bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf,
+bool set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
uint16 num_def_acls, const char *pdata)
{
SMB_ACL_T def_acl = NULL;
- if (!S_ISDIR(psbuf->st_ex_mode)) {
+ if (!S_ISDIR(psbuf->st_mode)) {
if (num_def_acls) {
DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
errno = EISDIR;
@@ -4701,7 +4565,6 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
connection_struct *conn;
files_struct finfo;
struct fd_handle fh;
- NTSTATUS status;
conn = TALLOC_ZERO_P(ctx, connection_struct);
if (conn == NULL) {
@@ -4721,7 +4584,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
if (!smbd_vfs_init(conn)) {
DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
- conn_free(conn);
+ conn_free_internal( conn );
return NULL;
}
@@ -4732,25 +4595,17 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
finfo.conn = conn;
finfo.fh = &fh;
finfo.fh->fd = -1;
-
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL,
- &finfo.fsp_name);
- if (!NT_STATUS_IS_OK(status)) {
- conn_free(conn);
- return NULL;
- }
+ finfo.fsp_name = CONST_DISCARD(char *,fname);
if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) {
DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
- TALLOC_FREE(finfo.fsp_name);
- conn_free(conn);
+ conn_free_internal( conn );
return NULL;
}
ret_sd = dup_sec_desc( ctx, psd );
- TALLOC_FREE(finfo.fsp_name);
- conn_free(conn);
+ conn_free_internal( conn );
return ret_sd;
}
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 572f37dbbe..b4976f77f8 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -20,20 +20,6 @@
#include "includes.h"
#include "smbd/globals.h"
-#include "../librpc/gen_ndr/srv_dfs.h"
-#include "../librpc/gen_ndr/srv_dssetup.h"
-#include "../librpc/gen_ndr/srv_echo.h"
-#include "../librpc/gen_ndr/srv_eventlog.h"
-#include "../librpc/gen_ndr/srv_initshutdown.h"
-#include "../librpc/gen_ndr/srv_lsa.h"
-#include "../librpc/gen_ndr/srv_netlogon.h"
-#include "../librpc/gen_ndr/srv_ntsvcs.h"
-#include "../librpc/gen_ndr/srv_samr.h"
-#include "../librpc/gen_ndr/srv_spoolss.h"
-#include "../librpc/gen_ndr/srv_srvsvc.h"
-#include "../librpc/gen_ndr/srv_svcctl.h"
-#include "../librpc/gen_ndr/srv_winreg.h"
-#include "../librpc/gen_ndr/srv_wkssvc.h"
extern bool global_machine_password_needs_changing;
@@ -46,20 +32,16 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf,
Send an smb to a fd.
****************************************************************************/
-bool srv_send_smb(int fd, char *buffer,
- bool do_signing, uint32_t seqnum,
- bool do_encrypt,
- struct smb_perfcount_data *pcd)
+bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
+ struct smb_perfcount_data *pcd)
{
size_t len = 0;
size_t nwritten=0;
ssize_t ret;
char *buf_out = buffer;
- if (do_signing) {
- /* Sign the outgoing packet if required. */
- srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum);
- }
+ /* Sign the outgoing packet if required. */
+ srv_calculate_sign_mac(buf_out);
if (do_encrypt) {
NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
@@ -73,12 +55,15 @@ bool srv_send_smb(int fd, char *buffer,
len = smb_len(buf_out) + 4;
- ret = write_data(fd,buf_out+nwritten,len - nwritten);
- if (ret <= 0) {
- DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
- (int)len,(int)ret, strerror(errno) ));
- srv_free_enc_buffer(buf_out);
- goto out;
+ while (nwritten < len) {
+ ret = write_data(fd,buf_out+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ srv_free_enc_buffer(buf_out);
+ goto out;
+ }
+ nwritten += ret;
}
SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
@@ -290,7 +275,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
if (CVAL(lenbuf,0) == 0 && min_recv_size &&
(smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
(min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
- !srv_is_signing_active(smbd_server_conn)) {
+ !srv_is_signing_active()) {
return receive_smb_raw_talloc_partial_read(
mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
@@ -326,8 +311,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
char **buffer, unsigned int timeout,
size_t *p_unread, bool *p_encrypted,
- size_t *p_len,
- uint32_t *seqnum)
+ size_t *p_len)
{
size_t len = 0;
NTSTATUS status;
@@ -352,7 +336,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
}
/* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) {
+ if (!srv_check_sign_mac(*buffer, true)) {
DEBUG(0, ("receive_smb: SMB Signature verification failed on "
"incoming packet!\n"));
return NT_STATUS_INVALID_NETWORK_RESPONSE;
@@ -371,7 +355,6 @@ void init_smb_request(struct smb_request *req,
size_t unread_bytes,
bool encrypted)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
size_t req_size = smb_len(inbuf) + 4;
/* Ensure we have at least smb_size bytes. */
if (req_size < smb_size) {
@@ -383,7 +366,6 @@ void init_smb_request(struct smb_request *req,
req->flags2 = SVAL(inbuf, smb_flg2);
req->smbpid = SVAL(inbuf, smb_pid);
req->mid = SVAL(inbuf, smb_mid);
- req->seqnum = 0;
req->vuid = SVAL(inbuf, smb_uid);
req->tid = SVAL(inbuf, smb_tid);
req->wct = CVAL(inbuf, smb_wct);
@@ -392,7 +374,7 @@ void init_smb_request(struct smb_request *req,
req->buf = (const uint8_t *)smb_buf(inbuf);
req->unread_bytes = unread_bytes;
req->encrypted = encrypted;
- req->conn = conn_find(sconn,req->tid);
+ req->conn = conn_find(req->tid);
req->chain_fsp = NULL;
req->chain_outbuf = NULL;
req->done = false;
@@ -420,8 +402,7 @@ void init_smb_request(struct smb_request *req,
static void process_smb(struct smbd_server_connection *conn,
uint8_t *inbuf, size_t nread, size_t unread_bytes,
- uint32_t seqnum, bool encrypted,
- struct smb_perfcount_data *deferred_pcd);
+ bool encrypted, struct smb_perfcount_data *deferred_pcd);
static void smbd_deferred_open_timer(struct event_context *ev,
struct timed_event *te,
@@ -444,7 +425,7 @@ static void smbd_deferred_open_timer(struct event_context *ev,
/* We leave this message on the queue so the open code can
know this is a retry. */
DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
- (unsigned int)mid ));
+ (unsigned int)mid));
/* Mark the message as processed so this is not
* re-processed in error. */
@@ -452,7 +433,7 @@ static void smbd_deferred_open_timer(struct event_context *ev,
process_smb(smbd_server_conn, inbuf,
msg->buf.length, 0,
- msg->seqnum, msg->encrypted, &msg->pcd);
+ msg->encrypted, &msg->pcd);
/* If it's still there and was processed, remove it. */
msg = get_open_deferred_message(mid);
@@ -489,7 +470,6 @@ static bool push_queued_message(struct smb_request *req,
}
msg->request_time = request_time;
- msg->seqnum = req->seqnum;
msg->encrypted = req->encrypted;
msg->processed = false;
SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
@@ -1263,7 +1243,6 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
int flags;
uint16 session_tag;
connection_struct *conn = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
errno = 0;
@@ -1307,12 +1286,12 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
* JRA.
*/
- if (session_tag != sconn->smb1.sessions.last_session_tag) {
+ if (session_tag != last_session_tag) {
user_struct *vuser = NULL;
- sconn->smb1.sessions.last_session_tag = session_tag;
+ last_session_tag = session_tag;
if(session_tag != UID_FIELD_INVALID) {
- vuser = get_valid_user_struct(sconn, session_tag);
+ vuser = get_valid_user_struct(session_tag);
if (vuser) {
set_current_user_info(
vuser->server_info->sanitized_username,
@@ -1335,15 +1314,13 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
if (type == SMBntcreateX) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
} else {
- reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
+ reply_doserror(req, ERRSRV, ERRinvnid);
}
return NULL;
}
if (!change_to_user(conn,session_tag)) {
- DEBUG(0, ("Error: Could not change to user. Removing "
- "deferred open, mid=%d.\n", req->mid));
- reply_force_doserror(req, ERRSRV, ERRbaduid);
+ reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
return conn;
}
@@ -1357,7 +1334,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
/* IPC services are limited */
if (IS_IPC(conn) && !(flags & CAN_IPC)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV,ERRaccess);
return conn;
}
} else {
@@ -1382,7 +1359,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
(flags & (AS_USER|DO_CHDIR)
?True:False))) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return conn;
}
conn->num_smb_operations++;
@@ -1393,7 +1370,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
&& (!change_to_guest() ||
!check_access(smbd_server_fd(), lp_hostsallow(-1),
lp_hostsdeny(-1)))) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return conn;
}
@@ -1406,7 +1383,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
****************************************************************************/
static void construct_reply(char *inbuf, int size, size_t unread_bytes,
- uint32_t seqnum, bool encrypted,
+ bool encrypted,
struct smb_perfcount_data *deferred_pcd)
{
connection_struct *conn;
@@ -1418,7 +1395,6 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
- req->seqnum = seqnum;
/* we popped this message off the queue - keep original perf data */
if (deferred_pcd)
@@ -1455,7 +1431,6 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -1471,8 +1446,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
****************************************************************************/
static void process_smb(struct smbd_server_connection *conn,
uint8_t *inbuf, size_t nread, size_t unread_bytes,
- uint32_t seqnum, bool encrypted,
- struct smb_perfcount_data *deferred_pcd)
+ bool encrypted, struct smb_perfcount_data *deferred_pcd)
{
int msg_type = CVAL(inbuf,0);
@@ -1492,21 +1466,13 @@ static void process_smb(struct smbd_server_connection *conn,
goto done;
}
- if (smbd_server_conn->allow_smb2) {
- if (smbd_is_smb2_header(inbuf, nread)) {
- smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
- return;
- }
- smbd_server_conn->allow_smb2 = false;
- }
-
show_msg((char *)inbuf);
- construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
+ construct_reply((char *)inbuf,nread,unread_bytes,encrypted,deferred_pcd);
trans_num++;
done:
- conn->smb1.num_requests++;
+ conn->num_requests++;
/* The timeout_processing function isn't run nearly
often enough to implement 'max log size' without
@@ -1515,7 +1481,7 @@ done:
level 10. Checking every 50 SMBs is a nice
tradeoff of performance vs log file size overrun. */
- if ((conn->smb1.num_requests % 50) == 0 &&
+ if ((conn->num_requests % 50) == 0 &&
need_to_check_log_size()) {
change_to_root_user();
check_log_size();
@@ -1608,180 +1574,6 @@ static void fixup_chain_error_packet(struct smb_request *req)
SCVAL(req->outbuf, smb_vwv0, 0xff);
}
-/**
- * @brief Find the smb_cmd offset of the last command pushed
- * @param[in] buf The buffer we're building up
- * @retval Where can we put our next andx cmd?
- *
- * While chaining requests, the "next" request we're looking at needs to put
- * its SMB_Command before the data the previous request already built up added
- * to the chain. Find the offset to the place where we have to put our cmd.
- */
-
-static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
-{
- uint8_t cmd;
- size_t ofs;
-
- cmd = CVAL(buf, smb_com);
-
- SMB_ASSERT(is_andx_req(cmd));
-
- ofs = smb_vwv0;
-
- while (CVAL(buf, ofs) != 0xff) {
-
- if (!is_andx_req(CVAL(buf, ofs))) {
- return false;
- }
-
- /*
- * ofs is from start of smb header, so add the 4 length
- * bytes. The next cmd is right after the wct field.
- */
- ofs = SVAL(buf, ofs+2) + 4 + 1;
-
- SMB_ASSERT(ofs+4 < talloc_get_size(buf));
- }
-
- *pofs = ofs;
- return true;
-}
-
-/**
- * @brief Do the smb chaining at a buffer level
- * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
- * @param[in] smb_command The command that we want to issue
- * @param[in] wct How many words?
- * @param[in] vwv The words, already in network order
- * @param[in] bytes_alignment How shall we align "bytes"?
- * @param[in] num_bytes How many bytes?
- * @param[in] bytes The data the request ships
- *
- * smb_splice_chain() adds the vwv and bytes to the request already present in
- * *poutbuf.
- */
-
-static bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
- uint8_t wct, const uint16_t *vwv,
- size_t bytes_alignment,
- uint32_t num_bytes, const uint8_t *bytes)
-{
- uint8_t *outbuf;
- size_t old_size, new_size;
- size_t ofs;
- size_t chain_padding = 0;
- size_t bytes_padding = 0;
- bool first_request;
-
- old_size = talloc_get_size(*poutbuf);
-
- /*
- * old_size == smb_wct means we're pushing the first request in for
- * libsmb/
- */
-
- first_request = (old_size == smb_wct);
-
- if (!first_request && ((old_size % 4) != 0)) {
- /*
- * Align the wct field of subsequent requests to a 4-byte
- * boundary
- */
- chain_padding = 4 - (old_size % 4);
- }
-
- /*
- * After the old request comes the new wct field (1 byte), the vwv's
- * and the num_bytes field. After at we might need to align the bytes
- * given to us to "bytes_alignment", increasing the num_bytes value.
- */
-
- new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
-
- if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) {
- bytes_padding = bytes_alignment - (new_size % bytes_alignment);
- }
-
- new_size += bytes_padding + num_bytes;
-
- if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
- DEBUG(1, ("splice_chain: %u bytes won't fit\n",
- (unsigned)new_size));
- return false;
- }
-
- outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size);
- if (outbuf == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return false;
- }
- *poutbuf = outbuf;
-
- if (first_request) {
- SCVAL(outbuf, smb_com, smb_command);
- } else {
- size_t andx_cmd_ofs;
-
- if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
- DEBUG(1, ("invalid command chain\n"));
- *poutbuf = TALLOC_REALLOC_ARRAY(
- NULL, *poutbuf, uint8_t, old_size);
- return false;
- }
-
- if (chain_padding != 0) {
- memset(outbuf + old_size, 0, chain_padding);
- old_size += chain_padding;
- }
-
- SCVAL(outbuf, andx_cmd_ofs, smb_command);
- SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
- }
-
- ofs = old_size;
-
- /*
- * Push the chained request:
- *
- * wct field
- */
-
- SCVAL(outbuf, ofs, wct);
- ofs += 1;
-
- /*
- * vwv array
- */
-
- memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
- ofs += sizeof(uint16_t) * wct;
-
- /*
- * bcc (byte count)
- */
-
- SSVAL(outbuf, ofs, num_bytes + bytes_padding);
- ofs += sizeof(uint16_t);
-
- /*
- * padding
- */
-
- if (bytes_padding != 0) {
- memset(outbuf + ofs, 0, bytes_padding);
- ofs += bytes_padding;
- }
-
- /*
- * The bytes field
- */
-
- memcpy(outbuf + ofs, bytes, num_bytes);
-
- return true;
-}
-
/****************************************************************************
Construct a chained reply and add it to the already made reply
****************************************************************************/
@@ -1878,7 +1670,6 @@ void chain_reply(struct smb_request *req)
talloc_get_size(req->chain_outbuf) - 4);
if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)
||req->encrypted,
&req->pcd)) {
@@ -1983,25 +1774,10 @@ void chain_reply(struct smb_request *req)
* We end up here if there's any error in the chain syntax. Report a
* DOS error, just like Windows does.
*/
- reply_force_doserror(req, ERRSRV, ERRerror);
+ reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
fixup_chain_error_packet(req);
done:
- /*
- * This scary statement intends to set the
- * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
- * to the value req->outbuf carries
- */
- SSVAL(req->chain_outbuf, smb_flg2,
- (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
- | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
-
- /*
- * Transfer the error codes from the subrequest to the main one
- */
- SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
- SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
-
if (!smb_splice_chain(&req->chain_outbuf,
CVAL(req->outbuf, smb_com),
CVAL(req->outbuf, smb_wct),
@@ -2018,7 +1794,6 @@ void chain_reply(struct smb_request *req)
show_msg((char *)(req->chain_outbuf));
if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -2089,7 +1864,6 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
bool encrypted = false;
TALLOC_CTX *mem_ctx = talloc_tos();
NTSTATUS status;
- uint32_t seqnum;
/* TODO: make this completely nonblocking */
@@ -2098,7 +1872,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
0, /* timeout */
&unread_bytes,
&encrypted,
- &inbuf_len, &seqnum);
+ &inbuf_len);
if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
goto process;
}
@@ -2110,8 +1884,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
}
process:
- process_smb(conn, inbuf, inbuf_len, unread_bytes,
- seqnum, encrypted, NULL);
+ process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted, NULL);
}
static void smbd_server_connection_handler(struct event_context *ev,
@@ -2201,9 +1974,8 @@ static bool keepalive_fn(const struct timeval *now, void *private_data)
*/
static bool deadtime_fn(const struct timeval *now, void *private_data)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
- if ((conn_num_open(sconn) == 0)
- || (conn_idle_all(sconn, now->tv_sec))) {
+ if ((conn_num_open() == 0)
+ || (conn_idle_all(now->tv_sec))) {
DEBUG( 2, ( "Closing idle connection\n" ) );
messaging_send(smbd_messaging_context(), procid_self(),
MSG_SHUTDOWN, &data_blob_null);
@@ -2247,9 +2019,9 @@ void smbd_process(void)
TALLOC_CTX *frame = talloc_stackframe();
char remaddr[INET6_ADDRSTRLEN];
- if (lp_maxprotocol() == PROTOCOL_SMB2 &&
- lp_security() != SEC_SHARE) {
- smbd_server_conn->allow_smb2 = true;
+ smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
+ if (!smbd_server_conn) {
+ exit_server("failed to create smbd_server_connection");
}
/* Ensure child is set to blocking mode */
@@ -2284,8 +2056,7 @@ void smbd_process(void)
unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ("Connection denied from %s\n",
client_addr(get_client_fd(),addr,sizeof(addr)) ) );
- (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
- 0, false, NULL);
+ (void)srv_send_smb(smbd_server_fd(),(char *)buf,false, NULL);
exit_server_cleanly("connection denied");
}
@@ -2311,10 +2082,6 @@ void smbd_process(void)
DEBUG(0,("Changed root to %s\n", lp_rootdir()));
}
- if (!srv_init_signing(smbd_server_conn)) {
- exit_server("Failed to init smb_signing");
- }
-
/* Setup oplocks */
if (!init_oplocks(smbd_messaging_context()))
exit_server("Failed to init oplocks");
@@ -2330,15 +2097,6 @@ void smbd_process(void)
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_CLOSE_FILE, msg_close_file);
- /*
- * Use the default MSG_DEBUG handler to avoid rebroadcasting
- * MSGs to all child processes
- */
- messaging_deregister(smbd_messaging_context(),
- MSG_DEBUG, NULL);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_DEBUG, debug_message);
-
if ((lp_keepalive() != 0)
&& !(event_add_idle(smbd_event_context(), NULL,
timeval_set(lp_keepalive(), 0),
@@ -2396,37 +2154,15 @@ void smbd_process(void)
#endif
- smbd_server_conn->nbt.got_session = false;
-
- smbd_server_conn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
-
- smbd_server_conn->smb1.sessions.done_sesssetup = false;
- smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
- smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
- /* users from session setup */
- smbd_server_conn->smb1.sessions.session_userlist = NULL;
- /* workgroup from session setup. */
- smbd_server_conn->smb1.sessions.session_workgroup = NULL;
- /* this holds info on user ids that are already validated for this VC */
- smbd_server_conn->smb1.sessions.validated_users = NULL;
- smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
- smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
-#ifdef HAVE_NETGROUP
- smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
-#endif
-
- conn_init(smbd_server_conn);
- if (!init_dptrs(smbd_server_conn)) {
- exit_server("init_dptrs() failed");
- }
+ max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
- smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
- smbd_server_conn,
- smbd_server_fd(),
- EVENT_FD_READ,
- smbd_server_connection_handler,
- smbd_server_conn);
- if (!smbd_server_conn->smb1.fde) {
+ smbd_server_conn->fde = event_add_fd(smbd_event_context(),
+ smbd_server_conn,
+ smbd_server_fd(),
+ EVENT_FD_READ,
+ smbd_server_connection_handler,
+ smbd_server_conn);
+ if (!smbd_server_conn->fde) {
exit_server("failed to create smbd_server_connection fde");
}
diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
index 1ad2b937b1..c4664e71cf 100644
--- a/source3/smbd/quotas.c
+++ b/source3/smbd/quotas.c
@@ -224,10 +224,10 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
/* find the block device file */
- if (sys_stat(path, &S, false) == -1 )
+ if ( sys_stat(path, &S) == -1 )
return(False) ;
- devno = S.st_ex_dev ;
+ devno = S.st_dev ;
if ((fp = setmntent(MOUNTED,"r")) == NULL)
return(False) ;
@@ -235,10 +235,10 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
found = False ;
while ((mnt = getmntent(fp))) {
- if (sys_stat(mnt->mnt_dir, &S, false) == -1)
+ if ( sys_stat(mnt->mnt_dir,&S) == -1 )
continue ;
- if (S.st_ex_dev == devno) {
+ if (S.st_dev == devno) {
found = True ;
break;
}
@@ -317,21 +317,21 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
int quota_default = 0 ;
bool found = false;
- if (sys_stat(path, &sbuf, false) == -1) {
+ if (sys_stat(path,&sbuf) == -1) {
return false;
}
- devno = sbuf.st_ex_dev ;
+ devno = sbuf.st_dev ;
if ((fd = setmntent(KMTAB)) == NULL) {
return false;
}
while ((mnt = getmntent(fd)) != NULL) {
- if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
+ if (sys_stat(mnt->mnt_dir,&sbuf) == -1) {
continue;
}
- if (sbuf.st_ex_dev == devno) {
+ if (sbuf.st_dev == devno) {
found = frue ;
break;
}
@@ -599,11 +599,11 @@ bool disk_quotas(const char *path,
euser_id = geteuid();
- if (sys_stat(path, &sbuf, false) == -1) {
+ if (sys_stat(path,&sbuf) == -1) {
return false;
}
- devno = sbuf.st_ex_dev ;
+ devno = sbuf.st_dev ;
DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
path, (unsigned int)devno));
#if defined(SUNOS5)
@@ -612,7 +612,7 @@ bool disk_quotas(const char *path,
}
while (getmntent(fd, &mnt) == 0) {
- if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
+ if (sys_stat(mnt.mnt_mountp, &sbuf) == -1) {
continue;
}
@@ -620,7 +620,7 @@ bool disk_quotas(const char *path,
mnt.mnt_mountp, (unsigned int)devno));
/* quotas are only on vxfs, UFS or NFS */
- if ((sbuf.st_ex_dev == devno) && (
+ if ((sbuf.st_dev == devno) && (
strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
@@ -639,13 +639,13 @@ bool disk_quotas(const char *path,
}
while ((mnt = getmntent(fd)) != NULL) {
- if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
+ if (sys_stat(mnt->mnt_dir,&sbuf) == -1) {
continue;
}
DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
mnt->mnt_dir,
- (unsigned int)sbuf.st_ex_dev));
- if (sbuf.st_ex_dev == devno) {
+ (unsigned int)sbuf.st_dev));
+ if (sbuf.st_dev == devno) {
found = true;
name = talloc_strdup(talloc_tos(),
mnt->mnt_fsname);
@@ -832,19 +832,19 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
/* find the block device file */
- if ( sys_stat(path, &S, false) == -1 ) {
+ if ( sys_stat(path, &S) == -1 ) {
return(False) ;
}
- devno = S.st_ex_dev ;
+ devno = S.st_dev ;
fp = setmntent(MOUNTED,"r");
found = False ;
while ((mnt = getmntent(fp))) {
- if ( sys_stat(mnt->mnt_dir, &S, false) == -1 )
+ if ( sys_stat(mnt->mnt_dir,&S) == -1 )
continue ;
- if (S.st_ex_dev == devno) {
+ if (S.st_dev == devno) {
found = True ;
break ;
}
@@ -1154,11 +1154,9 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
* to have a significant performance boost when
* lstat calls on /dev access this function.
*/
- if ((sys_stat(path, &S, false)<0)
- || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 1)<0))
+ if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
#else
- if ((sys_stat(path, &S, false)<0)
- || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
+ if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0))
return (False);
#endif /* ifdef HPUX */
@@ -1185,18 +1183,18 @@ bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *d
SMB_STRUCT_STAT st;
int mntsize, i;
- if (sys_stat(path, &st, false) < 0)
+ if (sys_stat(path,&st) < 0)
return False;
- devno = st.st_ex_dev;
+ devno = st.st_dev;
mntsize = getmntinfo(&mnts,MNT_NOWAIT);
if (mntsize <= 0)
return False;
for (i = 0; i < mntsize; i++) {
- if (sys_stat(mnts[i].f_mntonname, &st, false) < 0)
+ if (sys_stat(mnts[i].f_mntonname,&st) < 0)
return False;
- if (st.st_ex_dev == devno)
+ if (st.st_dev == devno)
break;
}
if (i == mntsize)
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b1a4e31951..23fa3e885b 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -27,6 +27,8 @@
#include "includes.h"
#include "smbd/globals.h"
+extern enum protocol_types Protocol;
+
/****************************************************************************
Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
path or anything including wildcards.
@@ -44,9 +46,9 @@ static NTSTATUS check_path_syntax_internal(char *path,
{
char *d = path;
const char *s = path;
- NTSTATUS ret = NT_STATUS_OK;
bool start_of_name_component = True;
bool stream_started = false;
+ bool check_quota = false;
*p_last_component_contains_wcard = False;
@@ -63,11 +65,14 @@ static NTSTATUS check_path_syntax_internal(char *path,
if (strchr_m(&s[1], ':')) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
+ if (StrCaseCmp(s, ":$DATA") != 0) {
+ check_quota = true;
+ }
break;
}
}
- if ((*s == ':') && !posix_path && !stream_started) {
+ if (!posix_path && !stream_started && *s == ':') {
if (*p_last_component_contains_wcard) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
@@ -122,8 +127,7 @@ static NTSTATUS check_path_syntax_internal(char *path,
/* Are we at the start ? Can't go back further if so. */
if (d <= path) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
+ return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
}
/* Go back one level... */
/* We know this is safe as '/' cannot be part of a mb sequence. */
@@ -196,7 +200,13 @@ static NTSTATUS check_path_syntax_internal(char *path,
*d = '\0';
- return ret;
+ if (check_quota) {
+ if (StrCaseCmp(path, FAKE_FILE_NAME_QUOTA_UNIX) != 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -402,95 +412,6 @@ bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
return False;
}
-static bool netbios_session_retarget(const char *name, int name_type)
-{
- char *trim_name;
- char *trim_name_type;
- const char *retarget_parm;
- char *retarget;
- char *p;
- int retarget_type = 0x20;
- int retarget_port = 139;
- struct sockaddr_storage retarget_addr;
- struct sockaddr_in *in_addr;
- bool ret = false;
- uint8_t outbuf[10];
-
- if (get_socket_port(smbd_server_fd()) != 139) {
- return false;
- }
-
- trim_name = talloc_strdup(talloc_tos(), name);
- if (trim_name == NULL) {
- goto fail;
- }
- trim_char(trim_name, ' ', ' ');
-
- trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
- name_type);
- if (trim_name_type == NULL) {
- goto fail;
- }
-
- retarget_parm = lp_parm_const_string(-1, "netbios retarget",
- trim_name_type, NULL);
- if (retarget_parm == NULL) {
- retarget_parm = lp_parm_const_string(-1, "netbios retarget",
- trim_name, NULL);
- }
- if (retarget_parm == NULL) {
- goto fail;
- }
-
- retarget = talloc_strdup(trim_name, retarget_parm);
- if (retarget == NULL) {
- goto fail;
- }
-
- DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
-
- p = strchr(retarget, ':');
- if (p != NULL) {
- *p++ = '\0';
- retarget_port = atoi(p);
- }
-
- p = strchr_m(retarget, '#');
- if (p != NULL) {
- *p++ = '\0';
- sscanf(p, "%x", &retarget_type);
- }
-
- ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
- if (!ret) {
- DEBUG(10, ("could not resolve %s\n", retarget));
- goto fail;
- }
-
- if (retarget_addr.ss_family != AF_INET) {
- DEBUG(10, ("Retarget target not an IPv4 addr\n"));
- goto fail;
- }
-
- in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
-
- _smb_setlen(outbuf, 6);
- SCVAL(outbuf, 0, 0x84);
- *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
- *(uint16_t *)(outbuf+8) = htons(retarget_port);
-
- if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
- NULL)) {
- exit_server_cleanly("netbios_session_regarget: srv_send_smb "
- "failed.");
- }
-
- ret = true;
- fail:
- TALLOC_FREE(trim_name);
- return ret;
-}
-
/****************************************************************************
Reply to a (netbios-level) special message.
****************************************************************************/
@@ -500,8 +421,7 @@ void reply_special(char *inbuf)
int msg_type = CVAL(inbuf,0);
int msg_flags = CVAL(inbuf,1);
fstring name1,name2;
- char name_type1, name_type2;
- struct smbd_server_connection *sconn = smbd_server_conn;
+ char name_type = 0;
/*
* We only really use 4 bytes of the outbuf, but for the smb_setlen
@@ -519,7 +439,7 @@ void reply_special(char *inbuf)
switch (msg_type) {
case 0x81: /* session request */
- if (sconn->nbt.got_session) {
+ if (already_got_session) {
exit_server_cleanly("multiple session request not permitted");
}
@@ -530,23 +450,19 @@ void reply_special(char *inbuf)
DEBUG(0,("Invalid name length in session request\n"));
return;
}
- name_type1 = name_extract(inbuf,4,name1);
- name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
- DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
- name1, name_type1, name2, name_type2));
-
- if (netbios_session_retarget(name1, name_type1)) {
- exit_server_cleanly("retargeted client");
- }
+ name_extract(inbuf,4,name1);
+ name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
+ DEBUG(2,("netbios connect: name1=%s name2=%s\n",
+ name1,name2));
set_local_machine_name(name1, True);
set_remote_machine_name(name2, True);
DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
get_local_machine_name(), get_remote_machine_name(),
- name_type2));
+ name_type));
- if (name_type2 == 'R') {
+ if (name_type == 'R') {
/* We are being asked for a pathworks session ---
no thanks! */
SCVAL(outbuf, 0,0x83);
@@ -557,13 +473,13 @@ void reply_special(char *inbuf)
of possibly valid usernames if we are operating
in share mode security */
if (lp_security() == SEC_SHARE) {
- add_session_user(sconn, get_remote_machine_name());
+ add_session_user(get_remote_machine_name());
}
reload_services(True);
reopen_logs();
- sconn->nbt.got_session = true;
+ already_got_session = True;
break;
case 0x89: /* session keepalive request
@@ -586,7 +502,7 @@ void reply_special(char *inbuf)
DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
msg_type, msg_flags));
- srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
+ srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
return;
}
@@ -607,7 +523,6 @@ void reply_tcon(struct smb_request *req)
const char *p;
DATA_BLOB password_blob;
TALLOC_CTX *ctx = talloc_tos();
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBtcon);
@@ -639,8 +554,7 @@ void reply_tcon(struct smb_request *req)
password_blob = data_blob(password, pwlen+1);
- conn = make_connection(sconn,service,password_blob,dev,
- req->vuid,&nt_status);
+ conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
req->conn = conn;
data_blob_clear_free(&password_blob);
@@ -652,7 +566,7 @@ void reply_tcon(struct smb_request *req)
}
reply_outbuf(req, 2, 0);
- SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
+ SSVAL(req->outbuf,smb_vwv0,max_recv);
SSVAL(req->outbuf,smb_vwv1,conn->cnum);
SSVAL(req->outbuf,smb_tid,conn->cnum);
@@ -683,7 +597,6 @@ void reply_tcon_and_X(struct smb_request *req)
char *path = NULL;
const char *p, *q;
uint16 tcon_flags;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBtconX);
@@ -704,12 +617,12 @@ void reply_tcon_and_X(struct smb_request *req)
}
if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
- reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
+ reply_doserror(req, ERRDOS, ERRbuftoosmall);
END_PROFILE(SMBtconX);
return;
}
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (global_encrypted_passwords_negotiated) {
password = data_blob_talloc(talloc_tos(), req->buf, passlen);
if (lp_security() == SEC_SHARE) {
/*
@@ -744,7 +657,7 @@ void reply_tcon_and_X(struct smb_request *req)
q = strchr_m(path+2,'\\');
if (!q) {
data_blob_clear_free(&password);
- reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
+ reply_doserror(req, ERRDOS, ERRnosuchshare);
END_PROFILE(SMBtconX);
return;
}
@@ -766,7 +679,7 @@ void reply_tcon_and_X(struct smb_request *req)
DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
- conn = make_connection(sconn, service, password, client_devicetype,
+ conn = make_connection(service, password, client_devicetype,
req->vuid, &nt_status);
req->conn =conn;
@@ -785,7 +698,7 @@ void reply_tcon_and_X(struct smb_request *req)
else
server_devicetype = "A:";
- if (get_Protocol() < PROTOCOL_NT1) {
+ if (Protocol < PROTOCOL_NT1) {
reply_outbuf(req, 2, 0);
if (message_push_string(&req->outbuf, server_devicetype,
STR_TERMINATE|STR_ASCII) == -1) {
@@ -864,7 +777,7 @@ void reply_unknown_new(struct smb_request *req, uint8 type)
{
DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
smb_fn_name(type), type, type));
- reply_force_doserror(req, ERRSRV, ERRunknownsmb);
+ reply_doserror(req, ERRSRV, ERRunknownsmb);
return;
}
@@ -901,7 +814,7 @@ void reply_ioctl(struct smb_request *req)
replysize = 32;
break;
default:
- reply_force_doserror(req, ERRSRV, ERRnosupport);
+ reply_doserror(req, ERRSRV, ERRnosupport);
END_PROFILE(SMBioctl);
return;
}
@@ -920,7 +833,7 @@ void reply_ioctl(struct smb_request *req)
files_struct *fsp = file_fsp(
req, SVAL(req->vwv+0, 0));
if (!fsp) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBioctl);
return;
}
@@ -966,8 +879,8 @@ static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
void reply_checkpath(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *name = NULL;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -983,16 +896,10 @@ void reply_checkpath(struct smb_request *req)
return;
}
- DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- name,
- 0,
- NULL,
- &smb_fname);
-
+ status = resolve_dfspath(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ name,
+ &name);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1003,23 +910,50 @@ void reply_checkpath(struct smb_request *req)
goto path_err;
}
- if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, smb_fname) != 0)) {
- DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname), strerror(errno)));
- status = map_nt_error_from_unix(errno);
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
+
+ status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto path_err;
+ }
+
+ status = check_name(conn, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
goto path_err;
}
- if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (!VALID_STAT(sbuf)) {
+ int ret;
+
+ if (lp_posix_pathnames()) {
+ ret = SMB_VFS_LSTAT(conn,name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,name,&sbuf);
+ }
+ if (ret != 0) {
+ DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
+ status = map_nt_error_from_unix(errno);
+ goto path_err;
+ }
+ }
+
+ if (!S_ISDIR(sbuf.st_mode)) {
reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
ERRDOS, ERRbadpath);
- goto out;
+ END_PROFILE(SMBcheckpath);
+ return;
}
reply_outbuf(req, 0, 0);
- path_err:
+ END_PROFILE(SMBcheckpath);
+ return;
+
+ path_err:
+
+ END_PROFILE(SMBcheckpath);
+
/* We special case this - as when a Windows machine
is parsing a path is steps through the components
one at a time - if a component fails it expects
@@ -1036,15 +970,10 @@ void reply_checkpath(struct smb_request *req)
*/
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
ERRDOS, ERRbadpath);
- goto out;
+ return;
}
reply_nterror(req, status);
-
- out:
- TALLOC_FREE(smb_fname);
- END_PROFILE(SMBcheckpath);
- return;
}
/****************************************************************************
@@ -1054,15 +983,14 @@ void reply_checkpath(struct smb_request *req)
void reply_getatr(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
+ SMB_STRUCT_STAT sbuf;
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
const char *p;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
- bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
START_PROFILE(SMBgetatr);
@@ -1070,7 +998,24 @@ void reply_getatr(struct smb_request *req)
p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBgetatr);
+ return;
+ }
+
+ status = resolve_dfspath(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ END_PROFILE(SMBgetatr);
+ return;
+ }
+ reply_nterror(req, status);
+ END_PROFILE(SMBgetatr);
+ return;
}
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
@@ -1083,47 +1028,38 @@ void reply_getatr(struct smb_request *req)
size = 0;
mtime = 0;
} else {
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
+ status = unix_convert(ctx, conn, fname, False, &fname, NULL,&sbuf);
if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBgetatr);
+ return;
}
- if (!VALID_STAT(smb_fname->st) &&
- (SMB_VFS_STAT(conn, smb_fname) != 0)) {
- DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req, map_nt_error_from_unix(errno));
- goto out;
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
+ reply_nterror(req, status);
+ END_PROFILE(SMBgetatr);
+ return;
}
+ if (!VALID_STAT(sbuf)) {
+ int ret;
- mode = dos_mode(conn, smb_fname);
- size = smb_fname->st.st_ex_size;
-
- if (ask_sharemode) {
- struct timespec write_time_ts;
- struct file_id fileid;
-
- ZERO_STRUCT(write_time_ts);
- fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
- get_file_infos(fileid, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&smb_fname->st, write_time_ts);
+ if (lp_posix_pathnames()) {
+ ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,fname,&sbuf);
+ }
+ if (ret != 0) {
+ DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req, ERRDOS,ERRbadfile);
+ END_PROFILE(SMBgetatr);
+ return;
}
}
- mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
+ mode = dos_mode(conn,fname,&sbuf);
+ size = sbuf.st_size;
+ mtime = sbuf.st_mtime;
if (mode & aDIR) {
size = 0;
}
@@ -1139,17 +1075,13 @@ void reply_getatr(struct smb_request *req)
}
SIVAL(req->outbuf,smb_vwv3,(uint32)size);
- if (get_Protocol() >= PROTOCOL_NT1) {
+ if (Protocol >= PROTOCOL_NT1) {
SSVAL(req->outbuf, smb_flg2,
SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
- DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
- smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
+ DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
- out:
- TALLOC_FREE(smb_fname);
- TALLOC_FREE(fname);
END_PROFILE(SMBgetatr);
return;
}
@@ -1162,10 +1094,10 @@ void reply_setatr(struct smb_request *req)
{
struct smb_file_time ft;
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
int mode;
time_t mtime;
+ SMB_STRUCT_STAT sbuf;
const char *p;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -1176,72 +1108,86 @@ void reply_setatr(struct smb_request *req)
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
p = (const char *)req->buf + 1;
p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBsetatr);
+ return;
}
- status = filename_convert(ctx,
- conn,
+ status = resolve_dfspath(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
- NULL,
- &smb_fname);
+ &fname);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBsetatr);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBsetatr);
+ return;
+ }
+
+ status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetatr);
+ return;
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetatr);
+ return;
}
- if (smb_fname->base_name[0] == '.' &&
- smb_fname->base_name[1] == '\0') {
+ if (fname[0] == '.' && fname[1] == '\0') {
/*
* Not sure here is the right place to catch this
* condition. Might be moved to somewhere else later -- vl
*/
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ END_PROFILE(SMBsetatr);
+ return;
}
mode = SVAL(req->vwv+0, 0);
mtime = srv_make_unix_date3(req->vwv+1);
ft.mtime = convert_time_t_to_timespec(mtime);
- status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
+ status = smb_set_file_time(conn, NULL, fname,
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBsetatr);
+ return;
}
if (mode != FILE_ATTRIBUTE_NORMAL) {
- if (VALID_STAT_OF_DIR(smb_fname->st))
+ if (VALID_STAT_OF_DIR(sbuf))
mode |= aDIR;
else
mode &= ~aDIR;
- if (file_set_dosmode(conn, smb_fname, mode, NULL,
- false) != 0) {
- reply_nterror(req, map_nt_error_from_unix(errno));
- goto out;
+ if (file_set_dosmode(conn,fname,mode,&sbuf,NULL,false) != 0) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBsetatr);
+ return;
}
}
reply_outbuf(req, 0, 0);
- DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
- mode));
- out:
- TALLOC_FREE(smb_fname);
+ DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
+
END_PROFILE(SMBsetatr);
return;
}
@@ -1257,14 +1203,14 @@ void reply_dskattr(struct smb_request *req)
START_PROFILE(SMBdskattr);
if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRHRD, ERRgeneral);
END_PROFILE(SMBdskattr);
return;
}
reply_outbuf(req, 5, 0);
- if (get_Protocol() <= PROTOCOL_LANMAN2) {
+ if (Protocol <= PROTOCOL_LANMAN2) {
double total_space, free_space;
/* we need to scale this to a number that DOS6 can handle. We
use floating point so we can handle large drives on systems
@@ -1298,38 +1244,6 @@ void reply_dskattr(struct smb_request *req)
return;
}
-/*
- * Utility function to split the filename from the directory.
- */
-static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
- char **fname_dir_out,
- char **fname_mask_out)
-{
- const char *p = NULL;
- char *fname_dir = NULL;
- char *fname_mask = NULL;
-
- p = strrchr_m(fname_in, '/');
- if (!p) {
- fname_dir = talloc_strdup(ctx, ".");
- fname_mask = talloc_strdup(ctx, fname_in);
- } else {
- fname_dir = talloc_strndup(ctx, fname_in,
- PTR_DIFF(p, fname_in));
- fname_mask = talloc_strdup(ctx, p+1);
- }
-
- if (!fname_dir || !fname_mask) {
- TALLOC_FREE(fname_dir);
- TALLOC_FREE(fname_mask);
- return NT_STATUS_NO_MEMORY;
- }
-
- *fname_dir_out = fname_dir;
- *fname_mask_out = fname_mask;
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Reply to a search.
Can be called from SMBsearch, SMBffirst or SMBfunique.
@@ -1338,20 +1252,19 @@ static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
void reply_search(struct smb_request *req)
{
connection_struct *conn = req->conn;
- char *path = NULL;
const char *mask = NULL;
char *directory = NULL;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
SMB_OFF_T size;
uint32 mode;
- struct timespec date;
+ time_t date;
uint32 dirtype;
unsigned int numentries = 0;
unsigned int maxentries = 0;
bool finished = False;
const char *p;
int status_len;
+ char *path = NULL;
char status[21];
int dptr_num= -1;
bool check_descend = False;
@@ -1361,19 +1274,19 @@ void reply_search(struct smb_request *req)
bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
TALLOC_CTX *ctx = talloc_tos();
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
- struct dptr_struct *dirptr = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBsearch);
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
if (lp_posix_pathnames()) {
reply_unknown_new(req, req->cmd);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
/* If we were called as SMBffirst then we must expect close. */
@@ -1389,7 +1302,25 @@ void reply_search(struct smb_request *req)
&nt_status, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
+ }
+
+ nt_status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ path,
+ &path,
+ &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ END_PROFILE(SMBsearch);
+ return;
+ }
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBsearch);
+ return;
}
p++;
@@ -1399,23 +1330,22 @@ void reply_search(struct smb_request *req)
/* dirtype &= ~aDIR; */
if (status_len == 0) {
- nt_status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- path,
- UCF_ALWAYS_ALLOW_WCARD_LCOMP,
- &mask_contains_wcard,
- &smb_fname);
+ SMB_STRUCT_STAT sbuf;
+
+ nt_status = unix_convert(ctx, conn, path, True,
+ &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(nt_status)) {
- if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
reply_nterror(req, nt_status);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
- directory = smb_fname->base_name;
+ nt_status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBsearch);
+ return;
+ }
p = strrchr_m(directory,'/');
if ((p != NULL) && (*directory != '/')) {
@@ -1429,7 +1359,8 @@ void reply_search(struct smb_request *req)
if (!directory) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
memset((char *)status,'\0',21);
@@ -1443,15 +1374,15 @@ void reply_search(struct smb_request *req)
mask,
mask_contains_wcard,
dirtype,
- &dirptr);
+ &conn->dirptr);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
- dptr_num = dptr_dnum(dirptr);
+ dptr_num = dptr_dnum(conn->dirptr);
} else {
int status_dirtype;
- const char *dirpath;
memcpy(status,p,21);
status_dirtype = CVAL(status,0) & 0x1F;
@@ -1459,18 +1390,12 @@ void reply_search(struct smb_request *req)
dirtype = status_dirtype;
}
- dirptr = dptr_fetch(sconn, status+12,&dptr_num);
- if (!dirptr) {
+ conn->dirptr = dptr_fetch(status+12,&dptr_num);
+ if (!conn->dirptr) {
goto SearchEmpty;
}
- dirpath = dptr_path(sconn, dptr_num);
- directory = talloc_strdup(ctx, dirpath);
- if (!directory) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
-
- mask = dptr_wcard(sconn, dptr_num);
+ string_set(&conn->dirpath,dptr_path(dptr_num));
+ mask = dptr_wcard(dptr_num);
if (!mask) {
goto SearchEmpty;
}
@@ -1479,13 +1404,13 @@ void reply_search(struct smb_request *req)
* check from the initial saved string.
*/
mask_contains_wcard = ms_has_wild(mask);
- dirtype = dptr_attr(sconn, dptr_num);
+ dirtype = dptr_attr(dptr_num);
}
DEBUG(4,("dptr_num is %d\n",dptr_num));
/* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
- dptr_init_search_op(dirptr);
+ dptr_init_search_op(conn->dirptr);
if ((dirtype&0x1F) == aVOLID) {
char buf[DIR_STRUCT_SIZE];
@@ -1493,9 +1418,10 @@ void reply_search(struct smb_request *req)
if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
0,aVOLID,0,!allow_long_path_components)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
- dptr_fill(sconn, buf+12,dptr_num);
+ dptr_fill(buf+12,dptr_num);
if (dptr_zero(buf+12) && (status_len==0)) {
numentries = 1;
} else {
@@ -1505,7 +1431,8 @@ void reply_search(struct smb_request *req)
data_blob_const(buf, sizeof(buf)))
== -1) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
} else {
unsigned int i;
@@ -1516,14 +1443,14 @@ void reply_search(struct smb_request *req)
/DIR_STRUCT_SIZE));
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
+ conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
check_descend = True;
}
for (i=numentries;(i<maxentries) && !finished;i++) {
finished = !get_dir_entry(ctx,
- dirptr,
+ conn,
mask,
dirtype,
&fname,
@@ -1541,19 +1468,21 @@ void reply_search(struct smb_request *req)
fname,
size,
mode,
- convert_timespec_to_time_t(date),
+ date,
!allow_long_path_components)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
- if (!dptr_fill(sconn, buf+12,dptr_num)) {
+ if (!dptr_fill(buf+12,dptr_num)) {
break;
}
if (message_push_blob(&req->outbuf,
data_blob_const(buf, sizeof(buf)))
== -1) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
numentries++;
}
@@ -1567,20 +1496,21 @@ void reply_search(struct smb_request *req)
(X/Open spec) */
if (numentries == 0) {
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
} else if(expect_close && status_len == 0) {
/* Close the dptr - we know it's gone */
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
if(dptr_num >= 0 && req->cmd == SMBfunique) {
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
}
if ((numentries == 0) && !mask_contains_wcard) {
reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
- goto out;
+ END_PROFILE(SMBsearch);
+ return;
}
SSVAL(req->outbuf,smb_vwv0,numentries);
@@ -1601,16 +1531,18 @@ void reply_search(struct smb_request *req)
SSVAL(req->outbuf, smb_flg2,
(SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
+ if (!directory) {
+ directory = dptr_path(dptr_num);
+ }
+
DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
smb_fn_name(req->cmd),
mask,
- directory,
+ directory ? directory : "./",
dirtype,
numentries,
maxentries ));
- out:
- TALLOC_FREE(directory);
- TALLOC_FREE(smb_fname);
+
END_PROFILE(SMBsearch);
return;
}
@@ -1629,7 +1561,6 @@ void reply_fclose(struct smb_request *req)
NTSTATUS err;
bool path_contains_wcard = False;
TALLOC_CTX *ctx = talloc_tos();
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBfclose);
@@ -1652,16 +1583,16 @@ void reply_fclose(struct smb_request *req)
p += 2;
if (status_len == 0) {
- reply_force_doserror(req, ERRSRV, ERRsrverror);
+ reply_doserror(req, ERRSRV, ERRsrverror);
END_PROFILE(SMBfclose);
return;
}
memcpy(status,p,21);
- if(dptr_fetch(sconn, status+12,&dptr_num)) {
+ if(dptr_fetch(status+12,&dptr_num)) {
/* Close the dptr - we know it's gone */
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
}
reply_outbuf(req, 1, 0);
@@ -1680,12 +1611,12 @@ void reply_fclose(struct smb_request *req)
void reply_open(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr=0;
SMB_OFF_T size = 0;
time_t mtime=0;
int info;
+ SMB_STRUCT_STAT sbuf;
files_struct *fsp;
int oplock_request;
int deny_mode;
@@ -1695,14 +1626,16 @@ void reply_open(struct smb_request *req)
uint32 create_disposition;
uint32 create_options = 0;
NTSTATUS status;
- bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBopen);
+ SET_STAT_INVALID(sbuf);
+
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBopen);
+ return;
}
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
@@ -1713,40 +1646,24 @@ void reply_open(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
- }
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBopen);
+ return;
}
- if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
- OPENX_FILE_EXISTS_OPEN, &access_mask,
- &share_mode, &create_disposition,
- &create_options)) {
- reply_force_doserror(req, ERRDOS, ERRbadaccess);
- goto out;
+ if (!map_open_params_to_ntcreate(
+ fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
+ &share_mode, &create_disposition, &create_options)) {
+ reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
+ END_PROFILE(SMBopen);
+ return;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
@@ -1757,41 +1674,30 @@ void reply_open(struct smb_request *req)
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ END_PROFILE(SMBopen);
+ return;
}
reply_openerror(req, status);
- goto out;
- }
-
- size = smb_fname->st.st_ex_size;
- fattr = dos_mode(conn, smb_fname);
-
- /* Deal with other possible opens having a modified
- write time. JRA. */
- if (ask_sharemode) {
- struct timespec write_time_ts;
-
- ZERO_STRUCT(write_time_ts);
- get_file_infos(fsp->file_id, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&smb_fname->st, write_time_ts);
- }
+ END_PROFILE(SMBopen);
+ return;
}
- mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
+ size = sbuf.st_size;
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
+ mtime = sbuf.st_mtime;
if (fattr & aDIR) {
- DEBUG(3,("attempt to open a directory %s\n",
- fsp_str_dbg(fsp)));
+ DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
close_file(req, fsp, ERROR_CLOSE);
- reply_botherror(req, NT_STATUS_ACCESS_DENIED,
- ERRDOS, ERRnoaccess);
- goto out;
+ reply_doserror(req, ERRDOS,ERRnoaccess);
+ END_PROFILE(SMBopen);
+ return;
}
reply_outbuf(req, 7, 0);
@@ -1814,8 +1720,6 @@ void reply_open(struct smb_request *req)
SCVAL(req->outbuf,smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- out:
- TALLOC_FREE(smb_fname);
END_PROFILE(SMBopen);
return;
}
@@ -1827,7 +1731,6 @@ void reply_open(struct smb_request *req)
void reply_open_and_X(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint16 open_flags;
int deny_mode;
@@ -1844,6 +1747,7 @@ void reply_open_and_X(struct smb_request *req)
int smb_ofun;
uint32 fattr=0;
int mtime=0;
+ SMB_STRUCT_STAT sbuf;
int smb_action = 0;
files_struct *fsp;
NTSTATUS status;
@@ -1859,9 +1763,12 @@ void reply_open_and_X(struct smb_request *req)
if (req->wct < 15) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBopenX);
+ return;
}
+ SET_STAT_INVALID(sbuf);
+
open_flags = SVAL(req->vwv+2, 0);
deny_mode = SVAL(req->vwv+3, 0);
smb_attr = SVAL(req->vwv+5, 0);
@@ -1876,9 +1783,10 @@ void reply_open_and_X(struct smb_request *req)
if (lp_nt_pipe_support()) {
reply_open_pipe_and_X(conn, req);
} else {
- reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
}
- goto out;
+ END_PROFILE(SMBopenX);
+ return;
}
/* XXXX we need to handle passed times, sattr and flags */
@@ -1886,40 +1794,24 @@ void reply_open_and_X(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
- }
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBopenX);
+ return;
}
- if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
- &access_mask, &share_mode,
- &create_disposition,
- &create_options)) {
- reply_force_doserror(req, ERRDOS, ERRbadaccess);
- goto out;
+ if (!map_open_params_to_ntcreate(
+ fname, deny_mode, smb_ofun, &access_mask,
+ &share_mode, &create_disposition, &create_options)) {
+ reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
+ END_PROFILE(SMBopenX);
+ return;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
@@ -1930,15 +1822,17 @@ void reply_open_and_X(struct smb_request *req)
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &smb_action); /* pinfo */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBopenX);
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ return;
}
reply_openerror(req, status);
- goto out;
+ return;
}
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
@@ -1948,24 +1842,26 @@ void reply_open_and_X(struct smb_request *req)
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
- goto out;
+ END_PROFILE(SMBopenX);
+ return;
}
retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
if (retval < 0) {
close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
- goto out;
+ END_PROFILE(SMBopenX);
+ return;
}
- smb_fname->st.st_ex_size =
- SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
+ sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
}
- fattr = dos_mode(conn, smb_fname);
- mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
+ mtime = sbuf.st_mtime;
if (fattr & aDIR) {
close_file(req, fsp, ERROR_CLOSE);
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBopenX);
+ return;
}
/* If the caller set the extended oplock request bit
@@ -2009,7 +1905,7 @@ void reply_open_and_X(struct smb_request *req)
} else {
srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
}
- SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
+ SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
SSVAL(req->outbuf,smb_vwv11,smb_action);
@@ -2017,10 +1913,8 @@ void reply_open_and_X(struct smb_request *req)
SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
}
- chain_reply(req);
- out:
- TALLOC_FREE(smb_fname);
END_PROFILE(SMBopenX);
+ chain_reply(req);
return;
}
@@ -2030,12 +1924,11 @@ void reply_open_and_X(struct smb_request *req)
void reply_ulogoffX(struct smb_request *req)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
user_struct *vuser;
START_PROFILE(SMBulogoffX);
- vuser = get_valid_user_struct(sconn, req->vuid);
+ vuser = get_valid_user_struct(req->vuid);
if(vuser == NULL) {
DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
@@ -2048,7 +1941,7 @@ void reply_ulogoffX(struct smb_request *req)
file_close_user(req->vuid);
}
- invalidate_vuid(sconn, req->vuid);
+ invalidate_vuid(req->vuid);
reply_outbuf(req, 2, 0);
@@ -2066,12 +1959,12 @@ void reply_ulogoffX(struct smb_request *req)
void reply_mknew(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr = 0;
struct smb_file_time ft;
files_struct *fsp;
int oplock_request = 0;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
@@ -2081,10 +1974,12 @@ void reply_mknew(struct smb_request *req)
START_PROFILE(SMBcreate);
ZERO_STRUCT(ft);
+ SET_STAT_INVALID(sbuf);
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBcreate);
+ return;
}
fattr = SVAL(req->vwv+0, 0);
@@ -2097,31 +1992,13 @@ void reply_mknew(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
- }
-
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcreate);
+ return;
}
if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - "
- "please report this\n",
- smb_fname_str_dbg(smb_fname)));
+ "please report this\n", fname));
}
if(req->cmd == SMBmknew) {
@@ -2136,7 +2013,8 @@ void reply_mknew(struct smb_request *req)
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
@@ -2147,22 +2025,25 @@ void reply_mknew(struct smb_request *req)
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ return;
}
reply_openerror(req, status);
- goto out;
+ return;
}
- ft.atime = smb_fname->st.st_ex_atime; /* atime. */
- status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
+ ft.atime = get_atimespec(&sbuf); /* atime. */
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
- goto out;
+ reply_openerror(req, status);
+ return;
}
reply_outbuf(req, 1, 0);
@@ -2178,13 +2059,10 @@ void reply_mknew(struct smb_request *req)
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
- DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
- smb_fname_str_dbg(smb_fname), fsp->fh->fd,
- (unsigned int)fattr));
+ DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
+ DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
+ fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
- out:
- TALLOC_FREE(smb_fname);
END_PROFILE(SMBcreate);
return;
}
@@ -2196,12 +2074,12 @@ void reply_mknew(struct smb_request *req)
void reply_ctemp(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname = NULL;
char *fname = NULL;
uint32 fattr;
files_struct *fsp;
int oplock_request;
int tmpfd;
+ SMB_STRUCT_STAT sbuf;
char *s;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -2210,7 +2088,8 @@ void reply_ctemp(struct smb_request *req)
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
fattr = SVAL(req->vwv+0, 0);
@@ -2220,7 +2099,8 @@ void reply_ctemp(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
if (*fname) {
fname = talloc_asprintf(ctx,
@@ -2232,39 +2112,57 @@ void reply_ctemp(struct smb_request *req)
if (!fname) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
- status = filename_convert(ctx, conn,
+ status = resolve_dfspath(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
- NULL,
- &smb_fname);
+ &fname);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
- tmpfd = mkstemp(smb_fname->base_name);
+ status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBctemp);
+ return;
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBctemp);
+ return;
+ }
+
+ tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
- reply_nterror(req, map_nt_error_from_unix(errno));
- goto out;
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBctemp);
+ return;
}
- SMB_VFS_STAT(conn, smb_fname);
+ SET_STAT_INVALID(sbuf);
+ SMB_VFS_STAT(conn,fname,&sbuf);
/* We should fail if file does not exist. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
FILE_OPEN, /* create_disposition*/
@@ -2275,27 +2173,30 @@ void reply_ctemp(struct smb_request *req)
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
- /* close fd from mkstemp() */
+ /* close fd from smb_mkstemp() */
close(tmpfd);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
reply_openerror(req, status);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
/* the returned filename is relative to the directory */
- s = strrchr_m(fsp->fsp_name->base_name, '/');
+ s = strrchr_m(fsp->fsp_name, '/');
if (!s) {
- s = fsp->fsp_name->base_name;
+ s = fsp->fsp_name;
} else {
s++;
}
@@ -2308,7 +2209,8 @@ void reply_ctemp(struct smb_request *req)
if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
== -1) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBctemp);
+ return;
}
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -2321,11 +2223,10 @@ void reply_ctemp(struct smb_request *req)
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
- DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
- fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
- out:
- TALLOC_FREE(smb_fname);
+ DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
+ DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
+ fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
+
END_PROFILE(SMBctemp);
return;
}
@@ -2335,7 +2236,7 @@ void reply_ctemp(struct smb_request *req)
********************************************************************/
static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
- uint16 dirtype)
+ uint16 dirtype, SMB_STRUCT_STAT *pst)
{
uint32 fmode;
@@ -2343,12 +2244,12 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- fmode = dos_mode(conn, fsp->fsp_name);
+ fmode = dos_mode(conn, fsp->fsp_name, pst);
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
return NT_STATUS_NO_SUCH_FILE;
}
- if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
+ if (S_ISDIR(pst->st_mode)) {
if (fsp->posix_open) {
return NT_STATUS_OK;
}
@@ -2375,34 +2276,33 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
static NTSTATUS do_unlink(connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_fname,
+ const char *fname,
uint32 dirtype)
{
+ SMB_STRUCT_STAT sbuf;
uint32 fattr;
files_struct *fsp;
uint32 dirtype_orig = dirtype;
- NTSTATUS status;
- int ret;
bool posix_paths = lp_posix_pathnames();
+ int ret;
+ NTSTATUS status;
- DEBUG(10,("do_unlink: %s, dirtype = %d\n",
- smb_fname_str_dbg(smb_fname),
- dirtype));
+ DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
if (posix_paths) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ ret = SMB_VFS_LSTAT(conn,fname,&sbuf);
} else {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
+ ret = SMB_VFS_STAT(conn,fname,&sbuf);
}
if (ret != 0) {
return map_nt_error_from_unix(errno);
}
- fattr = dos_mode(conn, smb_fname);
+ fattr = dos_mode(conn,fname,&sbuf);
if (dirtype & FILE_ATTRIBUTE_NORMAL) {
dirtype = aDIR|aARCH|aRONLY;
@@ -2455,6 +2355,24 @@ static NTSTATUS do_unlink(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_INVALID;
#endif /* JRATEST */
+ /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
+
+ On a Windows share, a file with read-only dosmode can be opened with
+ DELETE_ACCESS. But on a Samba share (delete readonly = no), it
+ fails with NT_STATUS_CANNOT_DELETE error.
+
+ This semantic causes a problem that a user can not
+ rename a file with read-only dosmode on a Samba share
+ from a Windows command prompt (i.e. cmd.exe, but can rename
+ from Windows Explorer).
+ */
+
+ if (!lp_delete_readonly(SNUM(conn))) {
+ if (fattr & aRONLY) {
+ return NT_STATUS_CANNOT_DELETE;
+ }
+ }
+
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
@@ -2462,12 +2380,13 @@ static NTSTATUS do_unlink(connection_struct *conn,
(conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
DELETE_ACCESS, /* access_mask */
FILE_SHARE_NONE, /* share_access */
FILE_OPEN, /* create_disposition*/
FILE_NON_DIRECTORY_FILE, /* create_options */
- /* file_attributes */
+ /* file_attributes */
posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
FILE_ATTRIBUTE_NORMAL,
0, /* oplock_request */
@@ -2475,7 +2394,8 @@ static NTSTATUS do_unlink(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
@@ -2483,16 +2403,6 @@ static NTSTATUS do_unlink(connection_struct *conn,
return status;
}
- status = can_set_delete_on_close(fsp, fattr);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- nt_errstr(status)));
- close_file(req, fsp, NORMAL_CLOSE);
- return status;
- }
-
/* The set is across all open files on this dev/inode pair. */
if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
close_file(req, fsp, NORMAL_CLOSE);
@@ -2508,20 +2418,33 @@ static NTSTATUS do_unlink(connection_struct *conn,
****************************************************************************/
NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
- uint32 dirtype, struct smb_filename *smb_fname,
- bool has_wild)
+ uint32 dirtype, const char *name_in, bool has_wild)
{
- char *fname_dir = NULL;
- char *fname_mask = NULL;
+ const char *directory = NULL;
+ char *mask = NULL;
+ char *name = NULL;
+ char *p = NULL;
int count=0;
NTSTATUS status = NT_STATUS_OK;
+ SMB_STRUCT_STAT sbuf, st;
TALLOC_CTX *ctx = talloc_tos();
- /* Split up the directory from the filename/mask. */
- status = split_fname_dir_mask(ctx, smb_fname->base_name,
- &fname_dir, &fname_mask);
+ status = unix_convert(ctx, conn, name_in, has_wild, &name, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
+ }
+
+ p = strrchr_m(name,'/');
+ if (!p) {
+ directory = talloc_strdup(ctx, ".");
+ if (!directory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ mask = name;
+ } else {
+ *p = 0;
+ directory = name;
+ mask = p+1;
}
/*
@@ -2533,77 +2456,63 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(smb_fname->st) &&
- mangle_is_mangled(fname_mask, conn->params)) {
+ if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
char *new_mask = NULL;
- mangle_lookup_name_from_8_3(ctx, fname_mask,
- &new_mask, conn->params);
+ mangle_lookup_name_from_8_3(ctx,
+ mask,
+ &new_mask,
+ conn->params );
if (new_mask) {
- TALLOC_FREE(fname_mask);
- fname_mask = new_mask;
+ mask = new_mask;
}
}
if (!has_wild) {
-
- /*
- * Only one file needs to be unlinked. Append the mask back
- * onto the directory.
- */
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = talloc_asprintf(smb_fname,
- "%s/%s",
- fname_dir,
- fname_mask);
- if (!smb_fname->base_name) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ directory = talloc_asprintf(ctx,
+ "%s/%s",
+ directory,
+ mask);
+ if (!directory) {
+ return NT_STATUS_NO_MEMORY;
}
if (dirtype == 0) {
dirtype = FILE_ATTRIBUTE_NORMAL;
}
- status = check_name(conn, smb_fname->base_name);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
- status = do_unlink(conn, req, smb_fname, dirtype);
+ status = do_unlink(conn, req, directory, dirtype);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
count++;
} else {
struct smb_Dir *dir_hnd = NULL;
long offset = 0;
- const char *dname = NULL;
- char *talloced = NULL;
+ const char *dname;
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
- status = NT_STATUS_OBJECT_NAME_INVALID;
- goto out;
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
- if (strequal(fname_mask,"????????.???")) {
- TALLOC_FREE(fname_mask);
- fname_mask = talloc_strdup(ctx, "*");
- if (!fname_mask) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
+ if (strequal(mask,"????????.???")) {
+ mask[0] = '*';
+ mask[1] = '\0';
}
- status = check_name(conn, fname_dir);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
- dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
+ dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
dirtype);
if (dir_hnd == NULL) {
- status = map_nt_error_from_unix(errno);
- goto out;
+ return map_nt_error_from_unix(errno);
}
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
@@ -2613,65 +2522,48 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
status = NT_STATUS_NO_SUCH_FILE;
- while ((dname = ReadDirName(dir_hnd, &offset,
- &smb_fname->st, &talloced))) {
- TALLOC_CTX *frame = talloc_stackframe();
+ while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
+ char *fname = NULL;
- if (!is_visible_file(conn, fname_dir, dname,
- &smb_fname->st, true)) {
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
+ if (!is_visible_file(conn, directory, dname, &st,
+ true))
+ {
continue;
}
/* Quick check for "." and ".." */
if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
continue;
}
- if(!mask_match(dname, fname_mask,
- conn->case_sensitive)) {
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
+ if(!mask_match(dname, mask, conn->case_sensitive)) {
continue;
}
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name =
- talloc_asprintf(smb_fname, "%s/%s",
- fname_dir, dname);
-
- if (!smb_fname->base_name) {
- TALLOC_FREE(dir_hnd);
- status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
- goto out;
+ fname = talloc_asprintf(ctx, "%s/%s",
+ directory,
+ dname);
+ if (!fname) {
+ return NT_STATUS_NO_MEMORY;
}
- status = check_name(conn, smb_fname->base_name);
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
- goto out;
+ return status;
}
- status = do_unlink(conn, req, smb_fname, dirtype);
+ status = do_unlink(conn, req, fname, dirtype);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
+ TALLOC_FREE(fname);
continue;
}
count++;
DEBUG(3,("unlink_internals: successful unlink [%s]\n",
- smb_fname->base_name));
+ fname));
- TALLOC_FREE(frame);
- TALLOC_FREE(talloced);
+ TALLOC_FREE(fname);
}
TALLOC_FREE(dir_hnd);
}
@@ -2680,9 +2572,6 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
status = map_nt_error_from_unix(errno);
}
- out:
- TALLOC_FREE(fname_dir);
- TALLOC_FREE(fname_mask);
return status;
}
@@ -2694,7 +2583,6 @@ void reply_unlink(struct smb_request *req)
{
connection_struct *conn = req->conn;
char *name = NULL;
- struct smb_filename *smb_fname = NULL;
uint32 dirtype;
NTSTATUS status;
bool path_contains_wcard = False;
@@ -2704,7 +2592,8 @@ void reply_unlink(struct smb_request *req)
if (req->wct < 1) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
dirtype = SVAL(req->vwv+0, 0);
@@ -2714,42 +2603,45 @@ void reply_unlink(struct smb_request *req)
&path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
- status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- name,
- UCF_COND_ALLOW_WCARD_LCOMP,
- &path_contains_wcard,
- &smb_fname);
+ status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ name,
+ &name,
+ &path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
- DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
+ DEBUG(3,("reply_unlink : %s\n",name));
- status = unlink_internals(conn, req, dirtype, smb_fname,
+ status = unlink_internals(conn, req, dirtype, name,
path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBunlink);
+ return;
}
reply_outbuf(req, 0, 0);
- out:
- TALLOC_FREE(smb_fname);
END_PROFILE(SMBunlink);
+
return;
}
@@ -2836,7 +2728,7 @@ static void sendfile_short_send(files_struct *fsp,
if (nread < headersize) {
DEBUG(0,("sendfile_short_send: sendfile failed to send "
"header for file %s (%s). Terminating\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("sendfile_short_send failed");
}
@@ -2850,7 +2742,7 @@ static void sendfile_short_send(files_struct *fsp,
}
DEBUG(0,("sendfile_short_send: filling truncated file %s "
- "with zeros !\n", fsp_str_dbg(fsp)));
+ "with zeros !\n", fsp->fsp_name));
while (nread < smb_maxcnt) {
/*
@@ -2917,8 +2809,7 @@ static void send_file_readbraw(connection_struct *conn,
*/
if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
- (fsp->wcp == NULL) &&
- lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
+ (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
ssize_t sendfile_read = -1;
char header[4];
DATA_BLOB header_blob;
@@ -2945,19 +2836,15 @@ static void send_file_readbraw(connection_struct *conn,
DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
if (fake_sendfile(fsp, startpos, nread) == -1) {
- DEBUG(0,("send_file_readbraw: "
- "fake_sendfile failed for "
- "file %s (%s).\n",
- fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readbraw fake_sendfile failed");
}
return;
}
- DEBUG(0,("send_file_readbraw: sendfile failed for "
- "file %s (%s). Terminating\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readbraw sendfile failed");
} else if (sendfile_read == 0) {
/*
@@ -2969,7 +2856,7 @@ static void send_file_readbraw(connection_struct *conn,
*/
DEBUG(3, ("send_file_readbraw: sendfile sent zero "
"bytes falling back to the normal read: "
- "%s\n", fsp_str_dbg(fsp)));
+ "%s\n", fsp->fsp_name));
goto normal_readbraw;
}
@@ -3021,12 +2908,12 @@ void reply_readbraw(struct smb_request *req)
SMB_OFF_T startpos;
files_struct *fsp;
struct lock_struct lock;
+ SMB_STRUCT_STAT st;
SMB_OFF_T size = 0;
START_PROFILE(SMBreadbraw);
- if (srv_is_signing_active(smbd_server_conn) ||
- is_encrypted_packet(req->inbuf)) {
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
"raw reads/writes are disallowed.");
}
@@ -3112,7 +2999,7 @@ void reply_readbraw(struct smb_request *req)
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
return;
- }
+ }
}
maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
@@ -3131,8 +3018,8 @@ void reply_readbraw(struct smb_request *req)
return;
}
- if (fsp_stat(fsp) == 0) {
- size = fsp->fsp_name->st.st_ex_size;
+ if (SMB_VFS_FSTAT(fsp, &st) == 0) {
+ size = st.st_size;
}
if (startpos >= size) {
@@ -3181,7 +3068,6 @@ void reply_lockread(struct smb_request *req)
files_struct *fsp;
struct byte_range_lock *br_lck = NULL;
char *p = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBlockread);
@@ -3199,7 +3085,7 @@ void reply_lockread(struct smb_request *req)
}
if (!CHECK_READ(fsp,req)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBlockread);
return;
}
@@ -3244,17 +3130,16 @@ void reply_lockread(struct smb_request *req)
* However the requested READ size IS affected by max_recv. Insanity.... JRA.
*/
- if (numtoread > sconn->smb1.negprot.max_recv) {
+ if (numtoread > max_recv) {
DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
Returning short read of maximum allowed for compatibility with Windows 2000.\n",
- (unsigned int)numtoread,
- (unsigned int)sconn->smb1.negprot.max_recv));
- numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
+ (unsigned int)numtoread, (unsigned int)max_recv ));
+ numtoread = MIN(numtoread,max_recv);
}
nread = read_file(fsp,data,startpos,numtoread);
if (nread < 0) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBlockread);
return;
}
@@ -3291,7 +3176,6 @@ void reply_read(struct smb_request *req)
int outsize = 0;
files_struct *fsp;
struct lock_struct lock;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBread);
@@ -3309,7 +3193,7 @@ void reply_read(struct smb_request *req)
}
if (!CHECK_READ(fsp,req)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBread);
return;
}
@@ -3322,12 +3206,11 @@ void reply_read(struct smb_request *req)
/*
* The requested read size cannot be greater than max_recv. JRA.
*/
- if (numtoread > sconn->smb1.negprot.max_recv) {
+ if (numtoread > max_recv) {
DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
Returning short read of maximum allowed for compatibility with Windows 2000.\n",
- (unsigned int)numtoread,
- (unsigned int)sconn->smb1.negprot.max_recv));
- numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
+ (unsigned int)numtoread, (unsigned int)max_recv ));
+ numtoread = MIN(numtoread,max_recv);
}
reply_outbuf(req, 5, numtoread+3);
@@ -3339,7 +3222,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS,ERRlock);
END_PROFILE(SMBread);
return;
}
@@ -3348,7 +3231,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
nread = read_file(fsp,data,startpos,numtoread);
if (nread < 0) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRDOS,ERRnoaccess);
goto strict_unlock;
}
@@ -3407,12 +3290,12 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
files_struct *fsp, SMB_OFF_T startpos,
size_t smb_maxcnt)
{
+ SMB_STRUCT_STAT sbuf;
ssize_t nread = -1;
struct lock_struct lock;
- int saved_errno = 0;
- if(fsp_stat(fsp) == -1) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -3421,13 +3304,12 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
return;
}
- if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
- (startpos > fsp->fsp_name->st.st_ex_size)
- || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
+ if (!S_ISREG(sbuf.st_mode) || (startpos > sbuf.st_size)
+ || (smb_maxcnt > (sbuf.st_size - startpos))) {
/*
* We already know that we would do a short read, so don't
* try the sendfile() path.
@@ -3444,8 +3326,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
if (!req_is_in_chain(req) &&
!is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
- (fsp->wcp == NULL) &&
- lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
+ lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
@@ -3480,11 +3361,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
nread = fake_sendfile(fsp, startpos,
smb_maxcnt);
if (nread == -1) {
- DEBUG(0,("send_file_readX: "
- "fake_sendfile failed for "
- "file %s (%s).\n",
- fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX: fake_sendfile failed");
}
DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
@@ -3493,9 +3371,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
goto strict_unlock;
}
- DEBUG(0,("send_file_readX: sendfile failed for file "
- "%s (%s). Terminating\n", fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX sendfile failed");
} else if (nread == 0) {
/*
@@ -3507,7 +3384,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
*/
DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
"falling back to the normal read: %s\n",
- fsp_str_dbg(fsp)));
+ fsp->fsp_name));
goto normal_read;
}
@@ -3537,16 +3414,14 @@ normal_read:
/* Send out the header. */
if (write_data(smbd_server_fd(), (char *)headerbuf,
sizeof(headerbuf)) != sizeof(headerbuf)) {
- DEBUG(0,("send_file_readX: write_data failed for file "
- "%s (%s). Terminating\n", fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX sendfile failed");
}
nread = fake_sendfile(fsp, startpos, smb_maxcnt);
if (nread == -1) {
- DEBUG(0,("send_file_readX: fake_sendfile failed for "
- "file %s (%s).\n", fsp_str_dbg(fsp),
- strerror(errno)));
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
exit_server_cleanly("send_file_readX: fake_sendfile failed");
}
goto strict_unlock;
@@ -3557,12 +3432,11 @@ nosendfile_read:
reply_outbuf(req, 12, smb_maxcnt);
nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
- saved_errno = errno;
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
if (nread < 0) {
- reply_nterror(req, map_nt_error_from_unix(saved_errno));
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
return;
}
@@ -3619,7 +3493,7 @@ void reply_read_and_X(struct smb_request *req)
}
if (!CHECK_READ(fsp,req)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS,ERRbadaccess);
END_PROFILE(SMBreadX);
return;
}
@@ -3635,8 +3509,7 @@ void reply_read_and_X(struct smb_request *req)
return;
}
/* We currently don't do this on signed or sealed data. */
- if (srv_is_signing_active(smbd_server_conn) ||
- is_encrypted_packet(req->inbuf)) {
+ if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
@@ -3670,7 +3543,7 @@ void reply_read_and_X(struct smb_request *req)
"used and we don't support 64 bit offsets.\n",
(unsigned int)IVAL(req->vwv+10, 0) ));
END_PROFILE(SMBreadX);
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
return;
}
@@ -3732,7 +3605,7 @@ void reply_writebraw(struct smb_request *req)
*/
SCVAL(req->inbuf,smb_com,SMBwritec);
- if (srv_is_signing_active(smbd_server_conn)) {
+ if (srv_is_signing_active()) {
END_PROFILE(SMBwritebraw);
exit_server_cleanly("reply_writebraw: SMB signing is active - "
"raw reads/writes are disallowed.");
@@ -3753,7 +3626,7 @@ void reply_writebraw(struct smb_request *req)
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
return;
@@ -3766,7 +3639,7 @@ void reply_writebraw(struct smb_request *req)
/* We have to deal with slightly different formats depending
on whether we are using the core+ or lanman1.0 protocol */
- if(get_Protocol() <= PROTOCOL_COREPLUS) {
+ if(Protocol <= PROTOCOL_COREPLUS) {
numtowrite = SVAL(smb_buf(req->inbuf),-2);
data = smb_buf(req->inbuf);
} else {
@@ -3787,7 +3660,7 @@ void reply_writebraw(struct smb_request *req)
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
return;
@@ -3803,7 +3676,7 @@ void reply_writebraw(struct smb_request *req)
(int)nwritten, (int)write_through));
if (nwritten < (ssize_t)numtowrite) {
- reply_nterror(req, NT_STATUS_DISK_FULL);
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
error_to_writebrawerr(req);
goto strict_unlock;
}
@@ -3813,7 +3686,7 @@ void reply_writebraw(struct smb_request *req)
/* Allocate a buffer of 64k + length. */
buf = TALLOC_ARRAY(NULL, char, 65540);
if (!buf) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
+ reply_doserror(req, ERRDOS, ERRnomem);
error_to_writebrawerr(req);
goto strict_unlock;
}
@@ -3822,15 +3695,14 @@ void reply_writebraw(struct smb_request *req)
* it to send more bytes */
memcpy(buf, req->inbuf, smb_size);
- srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
+ srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
SCVAL(buf,smb_com,SMBwritebraw);
SSVALS(buf,smb_vwv0,0xFFFF);
show_msg(buf);
if (!srv_send_smb(smbd_server_fd(),
- buf,
- false, 0, /* no signing */
- IS_CONN_ENCRYPTED(conn),
- &req->pcd)) {
+ buf,
+ IS_CONN_ENCRYPTED(conn),
+ &req->pcd)) {
exit_server_cleanly("reply_writebraw: srv_send_smb "
"failed.");
}
@@ -3872,7 +3744,7 @@ void reply_writebraw(struct smb_request *req)
nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
if (nwritten == -1) {
TALLOC_FREE(buf);
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
error_to_writebrawerr(req);
goto strict_unlock;
}
@@ -3893,7 +3765,7 @@ void reply_writebraw(struct smb_request *req)
status = sync_file(conn, fsp, write_through);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
reply_nterror(req, status);
error_to_writebrawerr(req);
goto strict_unlock;
@@ -3951,7 +3823,6 @@ void reply_writeunlock(struct smb_request *req)
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp;
struct lock_struct lock;
- int saved_errno = 0;
START_PROFILE(SMBwriteunlock);
@@ -3969,7 +3840,7 @@ void reply_writeunlock(struct smb_request *req)
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS,ERRbadaccess);
END_PROFILE(SMBwriteunlock);
return;
}
@@ -3984,7 +3855,7 @@ void reply_writeunlock(struct smb_request *req)
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwriteunlock);
return;
}
@@ -3997,24 +3868,18 @@ void reply_writeunlock(struct smb_request *req)
nwritten = 0;
} else {
nwritten = write_file(req,fsp,data,startpos,numtowrite);
- saved_errno = errno;
}
status = sync_file(conn, fsp, False /* write through */);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
reply_nterror(req, status);
goto strict_unlock;
}
- if(nwritten < 0) {
- reply_nterror(req, map_nt_error_from_unix(saved_errno));
- goto strict_unlock;
- }
-
- if((nwritten < numtowrite) && (numtowrite != 0)) {
- reply_nterror(req, NT_STATUS_DISK_FULL);
+ if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) {
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
goto strict_unlock;
}
@@ -4065,7 +3930,6 @@ void reply_write(struct smb_request *req)
files_struct *fsp;
struct lock_struct lock;
NTSTATUS status;
- int saved_errno = 0;
START_PROFILE(SMBwrite);
@@ -4090,7 +3954,7 @@ void reply_write(struct smb_request *req)
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBwrite);
return;
}
@@ -4104,7 +3968,7 @@ void reply_write(struct smb_request *req)
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwrite);
return;
}
@@ -4137,18 +4001,13 @@ void reply_write(struct smb_request *req)
status = sync_file(conn, fsp, False);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_write: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
reply_nterror(req, status);
goto strict_unlock;
}
- if(nwritten < 0) {
- reply_nterror(req, map_nt_error_from_unix(saved_errno));
- goto strict_unlock;
- }
-
- if((nwritten == 0) && (numtowrite != 0)) {
- reply_nterror(req, NT_STATUS_DISK_FULL);
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
goto strict_unlock;
}
@@ -4184,7 +4043,6 @@ bool is_valid_writeX_buffer(const uint8_t *inbuf)
connection_struct *conn = NULL;
unsigned int doff = 0;
size_t len = smb_len_large(inbuf);
- struct smbd_server_connection *sconn = smbd_server_conn;
if (is_encrypted_packet(inbuf)) {
/* Can't do this on encrypted
@@ -4203,7 +4061,7 @@ bool is_valid_writeX_buffer(const uint8_t *inbuf)
return false;
}
- conn = conn_find(sconn, SVAL(inbuf, smb_tid));
+ conn = conn_find(SVAL(inbuf, smb_tid));
if (conn == NULL) {
DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
return false;
@@ -4300,14 +4158,14 @@ void reply_write_and_X(struct smb_request *req)
return;
}
if (numtowrite != req->unread_bytes) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadmem);
END_PROFILE(SMBwriteX);
return;
}
} else {
if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
smb_doff + numtowrite > smblen) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadmem);
END_PROFILE(SMBwriteX);
return;
}
@@ -4316,7 +4174,7 @@ void reply_write_and_X(struct smb_request *req)
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(conn)) {
if (req->unread_bytes) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ reply_doserror(req, ERRDOS, ERRbadmem);
END_PROFILE(SMBwriteX);
return;
}
@@ -4335,7 +4193,7 @@ void reply_write_and_X(struct smb_request *req)
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBwriteX);
return;
}
@@ -4359,7 +4217,7 @@ void reply_write_and_X(struct smb_request *req)
DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
"used and we don't support 64 bit offsets.\n",
(unsigned int)IVAL(req->vwv+12, 0) ));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBwriteX);
return;
}
@@ -4372,7 +4230,7 @@ void reply_write_and_X(struct smb_request *req)
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwriteX);
return;
}
@@ -4395,13 +4253,8 @@ void reply_write_and_X(struct smb_request *req)
nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
- if(nwritten < 0) {
- reply_nterror(req, map_nt_error_from_unix(errno));
- goto strict_unlock;
- }
-
- if((nwritten == 0) && (numtowrite != 0)) {
- reply_nterror(req, NT_STATUS_DISK_FULL);
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
goto strict_unlock;
}
@@ -4420,7 +4273,7 @@ void reply_write_and_X(struct smb_request *req)
status = sync_file(conn, fsp, write_through);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
reply_nterror(req, status);
goto strict_unlock;
}
@@ -4492,22 +4345,23 @@ void reply_lseek(struct smb_request *req)
if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
if(errno == EINVAL) {
SMB_OFF_T current_pos = startpos;
+ SMB_STRUCT_STAT sbuf;
- if(fsp_stat(fsp) == -1) {
- reply_nterror(req,
- map_nt_error_from_unix(errno));
+ if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ reply_unixerror(req, ERRDOS,
+ ERRnoaccess);
END_PROFILE(SMBlseek);
return;
}
- current_pos += fsp->fsp_name->st.st_ex_size;
+ current_pos += sbuf.st_size;
if(current_pos < 0)
res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
}
}
if(res == -1) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBlseek);
return;
}
@@ -4555,7 +4409,7 @@ void reply_flush(struct smb_request *req)
NTSTATUS status = sync_file(conn, fsp, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
+ fsp->fsp_name, nt_errstr(status) ));
reply_nterror(req, status);
END_PROFILE(SMBflush);
return;
@@ -4612,7 +4466,7 @@ void reply_close(struct smb_request *req)
*/
if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBclose);
return;
}
@@ -4691,7 +4545,7 @@ void reply_writeclose(struct smb_request *req)
return;
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS,ERRbadaccess);
END_PROFILE(SMBwriteclose);
return;
}
@@ -4707,7 +4561,7 @@ void reply_writeclose(struct smb_request *req)
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS,ERRlock);
END_PROFILE(SMBwriteclose);
return;
}
@@ -4723,8 +4577,8 @@ void reply_writeclose(struct smb_request *req)
*/
if (numtowrite) {
- DEBUG(3,("reply_writeclose: zero length write doesn't close "
- "file %s\n", fsp_str_dbg(fsp)));
+ DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
+ fsp->fsp_name ));
close_status = close_file(req, fsp, NORMAL_CLOSE);
}
@@ -4733,7 +4587,7 @@ void reply_writeclose(struct smb_request *req)
conn->num_files_open));
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
- reply_nterror(req, NT_STATUS_DISK_FULL);
+ reply_doserror(req, ERRHRD, ERRdiskfull);
goto strict_unlock;
}
@@ -4883,7 +4737,7 @@ void reply_tdis(struct smb_request *req)
if (!conn) {
DEBUG(4,("Invalid connection in tdis\n"));
- reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
+ reply_doserror(req, ERRSRV, ERRinvnid);
END_PROFILE(SMBtdis);
return;
}
@@ -4950,7 +4804,6 @@ void reply_echo(struct smb_request *req)
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn)||req->encrypted,
cur_pcd))
exit_server_cleanly("reply_echo: srv_send_smb failed.");
@@ -4972,6 +4825,7 @@ void reply_printopen(struct smb_request *req)
{
connection_struct *conn = req->conn;
files_struct *fsp;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBsplopen);
@@ -4983,7 +4837,7 @@ void reply_printopen(struct smb_request *req)
}
if (!CAN_PRINT(conn)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsplopen);
return;
}
@@ -4996,10 +4850,9 @@ void reply_printopen(struct smb_request *req)
}
/* Open for exclusive use, write only. */
- status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
+ status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- file_free(req, fsp);
reply_nterror(req, status);
END_PROFILE(SMBsplopen);
return;
@@ -5041,7 +4894,7 @@ void reply_printclose(struct smb_request *req)
}
if (!CAN_PRINT(conn)) {
- reply_force_doserror(req, ERRSRV, ERRerror);
+ reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
END_PROFILE(SMBsplclose);
return;
}
@@ -5089,7 +4942,7 @@ void reply_printqueue(struct smb_request *req)
one printer - I think we should now only accept it if they
get it right (tridge) */
if (!CAN_PRINT(conn)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsplretq);
return;
}
@@ -5183,13 +5036,13 @@ void reply_printwrite(struct smb_request *req)
}
if (!CAN_PRINT(conn)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsplwr);
return;
}
if (!CHECK_WRITE(fsp)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBsplwr);
return;
}
@@ -5205,7 +5058,7 @@ void reply_printwrite(struct smb_request *req)
data = (const char *)req->buf + 3;
if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_unixerror(req, ERRHRD, ERRdiskfull);
END_PROFILE(SMBsplwr);
return;
}
@@ -5223,9 +5076,9 @@ void reply_printwrite(struct smb_request *req)
void reply_mkdir(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_dname = NULL;
char *directory = NULL;
NTSTATUS status;
+ SMB_STRUCT_STAT sbuf;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBmkdir);
@@ -5234,26 +5087,41 @@ void reply_mkdir(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmkdir);
+ return;
}
- status = filename_convert(ctx, conn,
+ status = resolve_dfspath(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- 0,
- NULL,
- &smb_dname);
+ &directory);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBmkdir);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmkdir);
+ return;
+ }
+
+ status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBmkdir);
+ return;
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBmkdir);
+ return;
}
- status = create_directory(conn, req, smb_dname);
+ status = create_directory(conn, req, directory);
DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -5271,32 +5139,224 @@ void reply_mkdir(struct smb_request *req)
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmkdir);
+ return;
}
reply_outbuf(req, 0, 0);
- DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
- out:
- TALLOC_FREE(smb_dname);
+ DEBUG( 3, ( "mkdir %s\n", directory ) );
+
END_PROFILE(SMBmkdir);
return;
}
/****************************************************************************
+ Static function used by reply_rmdir to delete an entire directory
+ tree recursively. Return True on ok, False on fail.
+****************************************************************************/
+
+static bool recursive_rmdir(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ char *directory)
+{
+ const char *dname = NULL;
+ bool ret = True;
+ long offset = 0;
+ SMB_STRUCT_STAT st;
+ struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, directory,
+ NULL, 0);
+
+ if(dir_hnd == NULL)
+ return False;
+
+ while((dname = ReadDirName(dir_hnd, &offset, &st))) {
+ char *fullname = NULL;
+
+ if (ISDOT(dname) || ISDOTDOT(dname)) {
+ continue;
+ }
+
+ if (!is_visible_file(conn, directory, dname, &st, False)) {
+ continue;
+ }
+
+ /* Construct the full name. */
+ fullname = talloc_asprintf(ctx,
+ "%s/%s",
+ directory,
+ dname);
+ if (!fullname) {
+ errno = ENOMEM;
+ ret = False;
+ break;
+ }
+
+ if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
+ ret = False;
+ break;
+ }
+
+ if(st.st_mode & S_IFDIR) {
+ if(!recursive_rmdir(ctx, conn, fullname)) {
+ ret = False;
+ break;
+ }
+ if(SMB_VFS_RMDIR(conn,fullname) != 0) {
+ ret = False;
+ break;
+ }
+ } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
+ ret = False;
+ break;
+ }
+ TALLOC_FREE(fullname);
+ }
+ TALLOC_FREE(dir_hnd);
+ return ret;
+}
+
+/****************************************************************************
+ The internals of the rmdir code - called elsewhere.
+****************************************************************************/
+
+NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ const char *directory)
+{
+ int ret;
+ SMB_STRUCT_STAT st;
+
+ /* Might be a symlink. */
+ if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (S_ISLNK(st.st_mode)) {
+ /* Is what it points to a directory ? */
+ if(SMB_VFS_STAT(conn, directory, &st) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ if (!(S_ISDIR(st.st_mode))) {
+ return NT_STATUS_NOT_A_DIRECTORY;
+ }
+ ret = SMB_VFS_UNLINK(conn,directory);
+ } else {
+ ret = SMB_VFS_RMDIR(conn,directory);
+ }
+ if (ret == 0) {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+ return NT_STATUS_OK;
+ }
+
+ if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
+ /*
+ * Check to see if the only thing in this directory are
+ * vetoed files/directories. If so then delete them and
+ * retry. If we fail to delete any of them (and we *don't*
+ * do a recursive delete) then fail the rmdir.
+ */
+ const char *dname;
+ long dirpos = 0;
+ struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
+ directory, NULL, 0);
+
+ if(dir_hnd == NULL) {
+ errno = ENOTEMPTY;
+ goto err;
+ }
+
+ while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
+ continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
+ if(!IS_VETO_PATH(conn, dname)) {
+ TALLOC_FREE(dir_hnd);
+ errno = ENOTEMPTY;
+ goto err;
+ }
+ }
+
+ /* We only have veto files/directories.
+ * Are we allowed to delete them ? */
+
+ if(!lp_recursive_veto_delete(SNUM(conn))) {
+ TALLOC_FREE(dir_hnd);
+ errno = ENOTEMPTY;
+ goto err;
+ }
+
+ /* Do a recursive delete. */
+ RewindDir(dir_hnd,&dirpos);
+ while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
+ char *fullname = NULL;
+
+ if (ISDOT(dname) || ISDOTDOT(dname)) {
+ continue;
+ }
+ if (!is_visible_file(conn, directory, dname, &st, False)) {
+ continue;
+ }
+
+ fullname = talloc_asprintf(ctx,
+ "%s/%s",
+ directory,
+ dname);
+
+ if(!fullname) {
+ errno = ENOMEM;
+ break;
+ }
+
+ if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
+ break;
+ }
+ if(st.st_mode & S_IFDIR) {
+ if(!recursive_rmdir(ctx, conn, fullname)) {
+ break;
+ }
+ if(SMB_VFS_RMDIR(conn,fullname) != 0) {
+ break;
+ }
+ } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
+ break;
+ }
+ TALLOC_FREE(fullname);
+ }
+ TALLOC_FREE(dir_hnd);
+ /* Retry the rmdir */
+ ret = SMB_VFS_RMDIR(conn,directory);
+ }
+
+ err:
+
+ if (ret != 0) {
+ DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
+ "%s\n", directory,strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
+
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ directory);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Reply to a rmdir.
****************************************************************************/
void reply_rmdir(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_dname = NULL;
char *directory = NULL;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
- files_struct *fsp = NULL;
- int info = 0;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBrmdir);
@@ -5304,82 +5364,53 @@ void reply_rmdir(struct smb_request *req)
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBrmdir);
+ return;
}
- status = filename_convert(ctx, conn,
+ status = resolve_dfspath(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- 0,
- NULL,
- &smb_dname);
+ &directory);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBrmdir);
+ return;
}
reply_nterror(req, status);
- goto out;
- }
-
- if (is_ntfs_stream_smb_fname(smb_dname)) {
- reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
- goto out;
+ END_PROFILE(SMBrmdir);
+ return;
}
- status = SMB_VFS_CREATE_FILE(
- conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- smb_dname, /* fname */
- DELETE_ACCESS, /* access_mask */
- (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
- FILE_SHARE_DELETE),
- FILE_OPEN, /* create_disposition*/
- FILE_DIRECTORY_FILE, /* create_options */
- FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
- 0, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &fsp, /* result */
- &info); /* pinfo */
-
+ status = unix_convert(ctx, conn, directory, False, &directory,
+ NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
- /* We have re-scheduled this call. */
- goto out;
- }
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBrmdir);
+ return;
}
- status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
- close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, status);
- goto out;
- }
-
- if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
- close_file(req, fsp, ERROR_CLOSE);
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ END_PROFILE(SMBrmdir);
+ return;
}
- status = close_file(req, fsp, NORMAL_CLOSE);
+ dptr_closepath(directory, req->smbpid);
+ status = rmdir_internals(ctx, conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- } else {
- reply_outbuf(req, 0, 0);
+ END_PROFILE(SMBrmdir);
+ return;
}
- dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
+ reply_outbuf(req, 0, 0);
+
+ DEBUG( 3, ( "rmdir %s\n", directory ) );
- DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
- out:
- TALLOC_FREE(smb_dname);
END_PROFILE(SMBrmdir);
return;
}
@@ -5518,11 +5549,10 @@ static bool resolve_wildcards(TALLOC_CTX *ctx,
static void rename_open_files(connection_struct *conn,
struct share_mode_lock *lck,
- const struct smb_filename *smb_fname_dst)
+ const char *newname)
{
files_struct *fsp;
bool did_rename = False;
- NTSTATUS status;
for(fsp = file_find_di_first(lck->id); fsp;
fsp = file_find_di_next(fsp)) {
@@ -5533,27 +5563,21 @@ static void rename_open_files(connection_struct *conn,
if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
continue;
}
- DEBUG(10, ("rename_open_files: renaming file fnum %d "
- "(file_id %s) from %s -> %s\n", fsp->fnum,
- file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
- smb_fname_str_dbg(smb_fname_dst)));
-
- status = fsp_set_smb_fname(fsp, smb_fname_dst);
- if (NT_STATUS_IS_OK(status)) {
- did_rename = True;
- }
+ DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
+ fsp->fnum, file_id_string_tos(&fsp->file_id),
+ fsp->fsp_name, newname ));
+ string_set(&fsp->fsp_name, newname);
+ did_rename = True;
}
if (!did_rename) {
- DEBUG(10, ("rename_open_files: no open files on file_id %s "
- "for %s\n", file_id_string_tos(&lck->id),
- smb_fname_str_dbg(smb_fname_dst)));
+ DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
+ file_id_string_tos(&lck->id), newname ));
}
/* Send messages to all smbd's (not ourself) that the name has changed. */
rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
- smb_fname_dst);
-
+ newname);
}
/****************************************************************************
@@ -5567,11 +5591,10 @@ static void rename_open_files(connection_struct *conn,
report from <AndyLiebman@aol.com>.
****************************************************************************/
-static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
+static bool rename_path_prefix_equal(const char *src, const char *dest)
{
- const char *psrc = smb_fname_src->base_name;
- const char *pdst = smb_fname_dst->base_name;
+ const char *psrc = src;
+ const char *pdst = dest;
size_t slen;
if (psrc[0] == '.' && psrc[1] == '/') {
@@ -5591,35 +5614,31 @@ static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
*/
static void notify_rename(connection_struct *conn, bool is_dir,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
+ const char *oldpath, const char *newpath)
{
- char *parent_dir_src = NULL;
- char *parent_dir_dst = NULL;
+ char *olddir, *newdir;
+ const char *oldname, *newname;
uint32 mask;
mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
: FILE_NOTIFY_CHANGE_FILE_NAME;
- if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
- &parent_dir_src, NULL) ||
- !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
- &parent_dir_dst, NULL)) {
- goto out;
+ if (!parent_dirname(talloc_tos(), oldpath, &olddir, &oldname)
+ || !parent_dirname(talloc_tos(), newpath, &newdir, &newname)) {
+ TALLOC_FREE(olddir);
+ return;
}
- if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
- notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
- smb_fname_src->base_name);
- notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
- smb_fname_dst->base_name);
+ if (strcmp(olddir, newdir) == 0) {
+ notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
}
else {
- notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
- smb_fname_src->base_name);
- notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
- smb_fname_dst->base_name);
+ notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
}
+ TALLOC_FREE(olddir);
+ TALLOC_FREE(newdir);
/* this is a strange one. w2k3 gives an additional event for
CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
@@ -5628,11 +5647,8 @@ static void notify_rename(connection_struct *conn, bool is_dir,
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_ATTRIBUTES
|FILE_NOTIFY_CHANGE_CREATION,
- smb_fname_dst->base_name);
+ newpath);
}
- out:
- TALLOC_FREE(parent_dir_src);
- TALLOC_FREE(parent_dir_dst);
}
/****************************************************************************
@@ -5641,39 +5657,32 @@ static void notify_rename(connection_struct *conn, bool is_dir,
NTSTATUS rename_internals_fsp(connection_struct *conn,
files_struct *fsp,
- const struct smb_filename *smb_fname_dst_in,
+ char *newname,
+ const char *newname_last_component,
uint32 attrs,
bool replace_if_exists)
{
TALLOC_CTX *ctx = talloc_tos();
- struct smb_filename *smb_fname_dst = NULL;
+ SMB_STRUCT_STAT sbuf, sbuf1;
NTSTATUS status = NT_STATUS_OK;
struct share_mode_lock *lck = NULL;
bool dst_exists, old_is_stream, new_is_stream;
- status = check_name(conn, smb_fname_dst_in->base_name);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ ZERO_STRUCT(sbuf);
- /* Make a copy of the dst smb_fname structs */
-
- status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
+ status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
- /* Ensure the dst smb_fname contains a '/' */
- if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
- char * tmp;
- tmp = talloc_asprintf(smb_fname_dst, "./%s",
- smb_fname_dst->base_name);
- if (!tmp) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ /* Ensure newname contains a '/' */
+ if(strrchr_m(newname,'/') == 0) {
+ newname = talloc_asprintf(ctx,
+ "./%s",
+ newname);
+ if (!newname) {
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = tmp;
}
/*
@@ -5683,78 +5692,36 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
* the rename (user is trying to change the case of the
* filename).
*/
- if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
- strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
- strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
- char *last_slash;
- char *fname_dst_lcomp_base_mod = NULL;
- struct smb_filename *smb_fname_orig_lcomp = NULL;
- /*
- * Get the last component of the destination name. Note that
- * we guarantee that destination name contains a '/' character
- * above.
- */
- last_slash = strrchr_m(smb_fname_dst->base_name, '/');
- fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
- if (!fname_dst_lcomp_base_mod) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
+ if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
+ strequal(newname, fsp->fsp_name)) {
+ char *p;
+ char *newname_modified_last_component = NULL;
/*
- * Create an smb_filename struct using the original last
- * component of the destination.
+ * Get the last component of the modified name.
+ * Note that we guarantee that newname contains a '/'
+ * character above.
*/
- status = create_synthetic_smb_fname_split(ctx,
- smb_fname_dst->original_lcomp, NULL,
- &smb_fname_orig_lcomp);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(fname_dst_lcomp_base_mod);
- goto out;
+ p = strrchr_m(newname,'/');
+ newname_modified_last_component = talloc_strdup(ctx,
+ p+1);
+ if (!newname_modified_last_component) {
+ return NT_STATUS_NO_MEMORY;
}
- /* If the base names only differ by case, use original. */
- if(!strcsequal(fname_dst_lcomp_base_mod,
- smb_fname_orig_lcomp->base_name)) {
- char *tmp;
+ if(strcsequal(newname_modified_last_component,
+ newname_last_component) == False) {
/*
- * Replace the modified last component with the
- * original.
+ * Replace the modified last component with
+ * the original.
*/
- *last_slash = '\0'; /* Truncate at the '/' */
- tmp = talloc_asprintf(smb_fname_dst,
+ *p = '\0'; /* Truncate at the '/' */
+ newname = talloc_asprintf(ctx,
"%s/%s",
- smb_fname_dst->base_name,
- smb_fname_orig_lcomp->base_name);
- if (tmp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(fname_dst_lcomp_base_mod);
- TALLOC_FREE(smb_fname_orig_lcomp);
- goto out;
- }
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = tmp;
- }
-
- /* If the stream_names only differ by case, use original. */
- if(!strcsequal(smb_fname_dst->stream_name,
- smb_fname_orig_lcomp->stream_name)) {
- char *tmp = NULL;
- /* Use the original stream. */
- tmp = talloc_strdup(smb_fname_dst,
- smb_fname_orig_lcomp->stream_name);
- if (tmp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- TALLOC_FREE(fname_dst_lcomp_base_mod);
- TALLOC_FREE(smb_fname_orig_lcomp);
- goto out;
- }
- TALLOC_FREE(smb_fname_dst->stream_name);
- smb_fname_dst->stream_name = tmp;
+ newname,
+ newname_last_component);
}
- TALLOC_FREE(fname_dst_lcomp_base_mod);
- TALLOC_FREE(smb_fname_orig_lcomp);
}
/*
@@ -5762,71 +5729,74 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
* don't do the rename, just return success.
*/
- if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
- strcsequal(fsp->fsp_name->stream_name,
- smb_fname_dst->stream_name)) {
- DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
- "- returning success\n",
- smb_fname_str_dbg(smb_fname_dst)));
- status = NT_STATUS_OK;
- goto out;
+ if (strcsequal(fsp->fsp_name, newname)) {
+ DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
+ newname));
+ return NT_STATUS_OK;
}
- old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
- new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
+ old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
+ new_is_stream = is_ntfs_stream_name(newname);
/* Return the correct error code if both names aren't streams. */
if (!old_is_stream && new_is_stream) {
- status = NT_STATUS_OBJECT_NAME_INVALID;
- goto out;
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
if (old_is_stream && !new_is_stream) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
+ return NT_STATUS_INVALID_PARAMETER;
}
- dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
+ /*
+ * Have vfs_object_exist also fill sbuf1
+ */
+ dst_exists = vfs_object_exist(conn, newname, &sbuf1);
if(!replace_if_exists && dst_exists) {
- DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
- "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
- smb_fname_str_dbg(smb_fname_dst)));
- status = NT_STATUS_OBJECT_NAME_COLLISION;
- goto out;
+ DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
+ fsp->fsp_name,newname));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
}
if (dst_exists) {
- struct file_id fileid = vfs_file_id_from_sbuf(conn,
- &smb_fname_dst->st);
+ struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
files_struct *dst_fsp = file_find_di_first(fileid);
/* The file can be open when renaming a stream */
if (dst_fsp && !new_is_stream) {
DEBUG(3, ("rename_internals_fsp: Target file open\n"));
- status = NT_STATUS_ACCESS_DENIED;
- goto out;
+ return NT_STATUS_ACCESS_DENIED;
}
}
/* Ensure we have a valid stat struct for the source. */
- status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ } else {
+ int ret = -1;
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+ }
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
}
- status = can_rename(conn, fsp, attrs);
+ status = can_rename(conn, fsp, attrs, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
- nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
- smb_fname_str_dbg(smb_fname_dst)));
+ DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
+ nt_errstr(status), fsp->fsp_name,newname));
if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
status = NT_STATUS_ACCESS_DENIED;
- goto out;
+ return status;
}
- if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
- status = NT_STATUS_ACCESS_DENIED;
+ if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
+ return NT_STATUS_ACCESS_DENIED;
}
lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
@@ -5839,17 +5809,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
SMB_ASSERT(lck != NULL);
- if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
+ if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
uint32 create_options = fsp->fh->private_options;
- DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
- "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
- smb_fname_str_dbg(smb_fname_dst)));
+ DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
+ fsp->fsp_name,newname));
- notify_rename(conn, fsp->is_directory, fsp->fsp_name,
- smb_fname_dst);
+ notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
- rename_open_files(conn, lck, smb_fname_dst);
+ rename_open_files(conn, lck, newname);
/*
* A rename acts as a new file create w.r.t. allowing an initial delete
@@ -5861,7 +5829,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
*/
if (create_options & FILE_DELETE_ON_CLOSE) {
- status = can_set_delete_on_close(fsp, 0);
+ status = can_set_delete_on_close(fsp, True, 0);
if (NT_STATUS_IS_OK(status)) {
/* Note that here we set the *inital* delete on close flag,
@@ -5870,8 +5838,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
}
}
TALLOC_FREE(lck);
- status = NT_STATUS_OK;
- goto out;
+ return NT_STATUS_OK;
}
TALLOC_FREE(lck);
@@ -5882,12 +5849,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
status = map_nt_error_from_unix(errno);
}
- DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
- nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
- smb_fname_str_dbg(smb_fname_dst)));
-
- out:
- TALLOC_FREE(smb_fname_dst);
+ DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
+ nt_errstr(status), fsp->fsp_name,newname));
return status;
}
@@ -5900,25 +5863,45 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
NTSTATUS rename_internals(TALLOC_CTX *ctx,
connection_struct *conn,
struct smb_request *req,
- struct smb_filename *smb_fname_src,
- struct smb_filename *smb_fname_dst,
+ const char *name_in,
+ const char *newname_in,
uint32 attrs,
bool replace_if_exists,
bool src_has_wild,
bool dest_has_wild,
uint32_t access_mask)
{
- char *fname_src_dir = NULL;
- char *fname_src_mask = NULL;
+ char *directory = NULL;
+ char *mask = NULL;
+ char *last_component_src = NULL;
+ char *last_component_dest = NULL;
+ char *name = NULL;
+ char *newname = NULL;
+ char *p;
int count=0;
NTSTATUS status = NT_STATUS_OK;
+ SMB_STRUCT_STAT sbuf1, sbuf2;
struct smb_Dir *dir_hnd = NULL;
- const char *dname = NULL;
- char *talloced = NULL;
+ const char *dname;
long offset = 0;
int create_options = 0;
bool posix_pathnames = lp_posix_pathnames();
+ ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(sbuf2);
+
+ status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
+ &last_component_src, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
+ &last_component_dest, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/*
* Split the old name into directory and last component
* strings. Note that unix_convert may have stripped off a
@@ -5928,12 +5911,21 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* as this is checked in resolve_wildcards().
*/
- /* Split up the directory from the filename/mask. */
- status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
- &fname_src_dir, &fname_src_mask);
- if (!NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ p = strrchr_m(name,'/');
+ if (!p) {
+ directory = talloc_strdup(ctx, ".");
+ if (!directory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ mask = name;
+ } else {
+ *p = 0;
+ directory = talloc_strdup(ctx, name);
+ if (!directory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ mask = p+1;
+ *p = '/'; /* Replace needed for exceptional test below. */
}
/*
@@ -5945,14 +5937,14 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(smb_fname_src->st) &&
- mangle_is_mangled(fname_src_mask, conn->params)) {
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
char *new_mask = NULL;
- mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
- conn->params);
+ mangle_lookup_name_from_8_3(ctx,
+ mask,
+ &new_mask,
+ conn->params );
if (new_mask) {
- TALLOC_FREE(fname_src_mask);
- fname_src_mask = new_mask;
+ mask = new_mask;
}
}
@@ -5960,30 +5952,24 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
files_struct *fsp;
/*
- * Only one file needs to be renamed. Append the mask back
- * onto the directory.
+ * No wildcards - just process the one file.
*/
- TALLOC_FREE(smb_fname_src->base_name);
- smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
- "%s/%s",
- fname_src_dir,
- fname_src_mask);
- if (!smb_fname_src->base_name) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
- /* Ensure dst fname contains a '/' also */
- if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
- char *tmp;
- tmp = talloc_asprintf(smb_fname_dst, "./%s",
- smb_fname_dst->base_name);
- if (!tmp) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ /* Add a terminating '/' to the directory name. */
+ directory = talloc_asprintf_append(directory,
+ "/%s",
+ mask);
+ if (!directory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Ensure newname contains a '/' also */
+ if(strrchr_m(newname,'/') == 0) {
+ newname = talloc_asprintf(ctx,
+ "./%s",
+ newname);
+ if (!newname) {
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = tmp;
}
DEBUG(3, ("rename_internals: case_sensitive = %d, "
@@ -5991,37 +5977,31 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
"directory = %s, newname = %s, "
"last_component_dest = %s\n",
conn->case_sensitive, conn->case_preserve,
- conn->short_case_preserve,
- smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst),
- smb_fname_dst->original_lcomp));
+ conn->short_case_preserve, directory,
+ newname, last_component_dest));
/* The dest name still may have wildcards. */
if (dest_has_wild) {
- char *fname_dst_mod = NULL;
- if (!resolve_wildcards(smb_fname_dst,
- smb_fname_src->base_name,
- smb_fname_dst->base_name,
- &fname_dst_mod)) {
+ char *mod_newname = NULL;
+ if (!resolve_wildcards(ctx,
+ directory,newname,&mod_newname)) {
DEBUG(6, ("rename_internals: resolve_wildcards "
- "%s %s failed\n",
- smb_fname_src->base_name,
- smb_fname_dst->base_name));
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ "%s %s failed\n",
+ directory,
+ newname));
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = fname_dst_mod;
+ newname = mod_newname;
}
- ZERO_STRUCT(smb_fname_src->st);
+ ZERO_STRUCT(sbuf1);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, smb_fname_src);
+ SMB_VFS_LSTAT(conn, directory, &sbuf1);
} else {
- SMB_VFS_STAT(conn, smb_fname_src);
+ SMB_VFS_STAT(conn, directory, &sbuf1);
}
- if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
+ if (S_ISDIR(sbuf1.st_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6029,7 +6009,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname_src, /* fname */
+ directory, /* fname */
+ 0, /* create_file_flags */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE),
@@ -6041,49 +6022,43 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not open rename source %s: %s\n",
- smb_fname_str_dbg(smb_fname_src),
- nt_errstr(status)));
- goto out;
+ directory, nt_errstr(status)));
+ return status;
}
- status = rename_internals_fsp(conn, fsp, smb_fname_dst,
+ status = rename_internals_fsp(conn, fsp, newname,
+ last_component_dest,
attrs, replace_if_exists);
close_file(req, fsp, NORMAL_CLOSE);
DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ nt_errstr(status), directory,newname));
- goto out;
+ return status;
}
/*
* Wildcards - process each file that matches.
*/
- if (strequal(fname_src_mask, "????????.???")) {
- TALLOC_FREE(fname_src_mask);
- fname_src_mask = talloc_strdup(ctx, "*");
- if (!fname_src_mask) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
+ if (strequal(mask,"????????.???")) {
+ mask[0] = '*';
+ mask[1] = '\0';
}
- status = check_name(conn, fname_src_dir);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
- dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
- attrs);
+ dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
if (dir_hnd == NULL) {
- status = map_nt_error_from_unix(errno);
- goto out;
+ return map_nt_error_from_unix(errno);
}
status = NT_STATUS_NO_SUCH_FILE;
@@ -6092,9 +6067,9 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
* - gentest fix. JRA
*/
- while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
- &talloced))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
files_struct *fsp = NULL;
+ char *fname = NULL;
char *destname = NULL;
bool sysdir_entry = False;
@@ -6103,19 +6078,15 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
if (attrs & aDIR) {
sysdir_entry = True;
} else {
- TALLOC_FREE(talloced);
continue;
}
}
- if (!is_visible_file(conn, fname_src_dir, dname,
- &smb_fname_src->st, false)) {
- TALLOC_FREE(talloced);
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
continue;
}
- if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
- TALLOC_FREE(talloced);
+ if(!mask_match(dname, mask, conn->case_sensitive)) {
continue;
}
@@ -6124,42 +6095,35 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
break;
}
- TALLOC_FREE(smb_fname_src->base_name);
- smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
- "%s/%s",
- fname_src_dir,
- dname);
- if (!smb_fname_src->base_name) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ fname = talloc_asprintf(ctx,
+ "%s/%s",
+ directory,
+ dname);
+ if (!fname) {
+ return NT_STATUS_NO_MEMORY;
}
- if (!resolve_wildcards(ctx, smb_fname_src->base_name,
- smb_fname_dst->base_name,
- &destname)) {
+ if (!resolve_wildcards(ctx,
+ fname,newname,&destname)) {
DEBUG(6, ("resolve_wildcards %s %s failed\n",
- smb_fname_src->base_name, destname));
- TALLOC_FREE(talloced);
+ fname, destname));
+ TALLOC_FREE(fname);
continue;
}
if (!destname) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ return NT_STATUS_NO_MEMORY;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = destname;
-
- ZERO_STRUCT(smb_fname_src->st);
+ ZERO_STRUCT(sbuf1);
if (posix_pathnames) {
- SMB_VFS_LSTAT(conn, smb_fname_src);
+ SMB_VFS_LSTAT(conn, fname, &sbuf1);
} else {
- SMB_VFS_STAT(conn, smb_fname_src);
+ SMB_VFS_STAT(conn, fname, &sbuf1);
}
create_options = 0;
- if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
+ if (S_ISDIR(sbuf1.st_mode)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -6167,7 +6131,8 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname_src, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
access_mask, /* access_mask */
(FILE_SHARE_READ | /* share_access */
FILE_SHARE_WRITE),
@@ -6179,25 +6144,17 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
"returned %s rename %s -> %s\n",
- nt_errstr(status),
- smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ nt_errstr(status), directory, newname));
break;
}
- smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
- dname);
- if (!smb_fname_dst->original_lcomp) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
- status = rename_internals_fsp(conn, fsp, smb_fname_dst,
+ status = rename_internals_fsp(conn, fsp, destname, dname,
attrs, replace_if_exists);
close_file(req, fsp, NORMAL_CLOSE);
@@ -6205,17 +6162,17 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rename_internals_fsp returned %s for "
"rename %s -> %s\n", nt_errstr(status),
- smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ directory, newname));
break;
}
count++;
DEBUG(3,("rename_internals: doing rename on %s -> "
- "%s\n", smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_src)));
- TALLOC_FREE(talloced);
+ "%s\n",fname,destname));
+
+ TALLOC_FREE(fname);
+ TALLOC_FREE(destname);
}
TALLOC_FREE(dir_hnd);
@@ -6223,10 +6180,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
status = map_nt_error_from_unix(errno);
}
- out:
- TALLOC_FREE(talloced);
- TALLOC_FREE(fname_src_dir);
- TALLOC_FREE(fname_src_mask);
return status;
}
@@ -6245,14 +6198,13 @@ void reply_mv(struct smb_request *req)
bool src_has_wcard = False;
bool dest_has_wcard = False;
TALLOC_CTX *ctx = talloc_tos();
- struct smb_filename *smb_fname_src = NULL;
- struct smb_filename *smb_fname_dst = NULL;
START_PROFILE(SMBmv);
if (req->wct < 1) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
attrs = SVAL(req->vwv+0, 0);
@@ -6262,71 +6214,69 @@ void reply_mv(struct smb_request *req)
&status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
p++;
p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
&status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- name,
- UCF_COND_ALLOW_WCARD_LCOMP,
- &src_has_wcard,
- &smb_fname_src);
-
+ status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ name,
+ &name,
+ &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- newname,
- UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
- &dest_has_wcard,
- &smb_fname_dst);
-
+ status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ newname,
+ &newname,
+ &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
- DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
+ DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
- attrs, False, src_has_wcard, dest_has_wcard,
- DELETE_ACCESS);
+ status = rename_internals(ctx, conn, req, name, newname, attrs, False,
+ src_has_wcard, dest_has_wcard, DELETE_ACCESS);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBmv);
+ return;
}
reply_outbuf(req, 0, 0);
- out:
- TALLOC_FREE(smb_fname_src);
- TALLOC_FREE(smb_fname_dst);
+
END_PROFILE(SMBmv);
return;
}
@@ -6341,73 +6291,60 @@ void reply_mv(struct smb_request *req)
NTSTATUS copy_file(TALLOC_CTX *ctx,
connection_struct *conn,
- struct smb_filename *smb_fname_src,
- struct smb_filename *smb_fname_dst,
+ const char *src,
+ const char *dest1,
int ofun,
int count,
bool target_is_directory)
{
- struct smb_filename *smb_fname_dst_tmp = NULL;
+ SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
+ char *dest = NULL;
uint32 dosattrs;
uint32 new_create_disposition;
NTSTATUS status;
-
- status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ dest = talloc_strdup(ctx, dest1);
+ if (!dest) {
+ return NT_STATUS_NO_MEMORY;
}
-
- /*
- * If the target is a directory, extract the last component from the
- * src filename and append it to the dst filename
- */
if (target_is_directory) {
- const char *p;
-
- /* dest/target can't be a stream if it's a directory. */
- SMB_ASSERT(smb_fname_dst->stream_name == NULL);
-
- p = strrchr_m(smb_fname_src->base_name,'/');
+ const char *p = strrchr_m(src,'/');
if (p) {
p++;
} else {
- p = smb_fname_src->base_name;
+ p = src;
}
- smb_fname_dst_tmp->base_name =
- talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
- p);
- if (!smb_fname_dst_tmp->base_name) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ dest = talloc_asprintf_append(dest,
+ "/%s",
+ p);
+ if (!dest) {
+ return NT_STATUS_NO_MEMORY;
}
}
- status = vfs_file_exist(conn, smb_fname_src);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ if (!vfs_file_exist(conn,src,&src_sbuf)) {
+ TALLOC_FREE(dest);
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (!target_is_directory && count) {
new_create_disposition = FILE_OPEN;
} else {
- if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
- NULL, NULL,
- &new_create_disposition,
- NULL)) {
- status = NT_STATUS_INVALID_PARAMETER;
- goto out;
+ if (!map_open_params_to_ntcreate(dest1,0,ofun,
+ NULL, NULL, &new_create_disposition, NULL)) {
+ TALLOC_FREE(dest);
+ return NT_STATUS_INVALID_PARAMETER;
}
}
- /* Open the src file for reading. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- smb_fname_src, /* fname */
+ src, /* fname */
+ 0, /* create_file_flags */
FILE_GENERIC_READ, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
FILE_OPEN, /* create_disposition*/
@@ -6418,24 +6355,25 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp1, /* result */
- NULL); /* psbuf */
+ NULL, /* pinfo */
+ &src_sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ TALLOC_FREE(dest);
+ return status;
}
- dosattrs = dos_mode(conn, smb_fname_src);
-
- if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
- ZERO_STRUCTP(&smb_fname_dst_tmp->st);
+ dosattrs = dos_mode(conn, src, &src_sbuf);
+ if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
+ ZERO_STRUCTP(&sbuf2);
}
- /* Open the dst file for writing. */
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
0, /* root_dir_fid */
- smb_fname_dst, /* fname */
+ dest, /* fname */
+ 0, /* create_file_flags */
FILE_GENERIC_WRITE, /* access_mask */
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
new_create_disposition, /* create_disposition*/
@@ -6446,11 +6384,14 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
NULL, /* sd */
NULL, /* ea_list */
&fsp2, /* result */
- NULL); /* psbuf */
+ NULL, /* pinfo */
+ &sbuf2); /* psbuf */
+
+ TALLOC_FREE(dest);
if (!NT_STATUS_IS_OK(status)) {
close_file(NULL, fsp1, ERROR_CLOSE);
- goto out;
+ return status;
}
if ((ofun&3) == 1) {
@@ -6460,19 +6401,18 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
* Stop the copy from occurring.
*/
ret = -1;
- smb_fname_src->st.st_ex_size = 0;
+ src_sbuf.st_size = 0;
}
}
- /* Do the actual copy. */
- if (smb_fname_src->st.st_ex_size) {
- ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
+ if (src_sbuf.st_size) {
+ ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
}
close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
+ set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
/*
* As we are opening fsp1 read-only we only expect
@@ -6483,19 +6423,14 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
status = close_file(NULL, fsp2, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
- goto out;
+ return status;
}
- if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
- status = NT_STATUS_DISK_FULL;
- goto out;
+ if (ret != (SMB_OFF_T)src_sbuf.st_size) {
+ return NT_STATUS_DISK_FULL;
}
- status = NT_STATUS_OK;
-
- out:
- TALLOC_FREE(smb_fname_dst_tmp);
- return status;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -6505,21 +6440,22 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
void reply_copy(struct smb_request *req)
{
connection_struct *conn = req->conn;
- struct smb_filename *smb_fname_src = NULL;
- struct smb_filename *smb_fname_dst = NULL;
- char *fname_src = NULL;
- char *fname_dst = NULL;
- char *fname_src_mask = NULL;
- char *fname_src_dir = NULL;
+ char *name = NULL;
+ char *newname = NULL;
+ char *directory = NULL;
+ const char *mask = NULL;
+ const char mask_star[] = "*";
const char *p;
int count=0;
int error = ERRnoaccess;
+ int err = 0;
int tid2;
int ofun;
int flags;
bool target_is_directory=False;
bool source_has_wild = False;
bool dest_has_wild = False;
+ SMB_STRUCT_STAT sbuf1, sbuf2;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
@@ -6527,7 +6463,8 @@ void reply_copy(struct smb_request *req)
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
tid2 = SVAL(req->vwv+0, 0);
@@ -6535,85 +6472,116 @@ void reply_copy(struct smb_request *req)
flags = SVAL(req->vwv+2, 0);
p = (const char *)req->buf;
- p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
+ p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
&status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
+ p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
&status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
+ DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
if (tid2 != conn->cnum) {
/* can't currently handle inter share copies XXXX */
DEBUG(3,("Rejecting inter-share copy\n"));
- reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
- goto out;
+ reply_doserror(req, ERRSRV, ERRinvdevice);
+ END_PROFILE(SMBcopy);
+ return;
}
- status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname_src,
- UCF_COND_ALLOW_WCARD_LCOMP,
- &source_has_wild,
- &smb_fname_src);
+ status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ name,
+ &name,
+ &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- status = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname_dst,
- UCF_COND_ALLOW_WCARD_LCOMP,
- &dest_has_wild,
- &smb_fname_dst);
+ status = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ newname,
+ &newname,
+ &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
+ status = unix_convert(ctx, conn, name, source_has_wild,
+ &name, NULL, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBcopy);
+ return;
+ }
+
+ status = unix_convert(ctx, conn, newname, dest_has_wild,
+ &newname, NULL, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBcopy);
+ return;
+ }
+
+ target_is_directory = VALID_STAT_OF_DIR(sbuf2);
if ((flags&1) && target_is_directory) {
- reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
- goto out;
+ reply_doserror(req, ERRDOS, ERRbadfile);
+ END_PROFILE(SMBcopy);
+ return;
}
if ((flags&2) && !target_is_directory) {
- reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
- goto out;
+ reply_doserror(req, ERRDOS, ERRbadpath);
+ END_PROFILE(SMBcopy);
+ return;
}
- if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
+ if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
/* wants a tree copy! XXXX */
DEBUG(3,("Rejecting tree copy\n"));
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ reply_doserror(req, ERRSRV, ERRerror);
+ END_PROFILE(SMBcopy);
+ return;
}
- /* Split up the directory from the filename/mask. */
- status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
- &fname_src_dir, &fname_src_mask);
- if (!NT_STATUS_IS_OK(status)) {
+ p = strrchr_m(name,'/');
+ if (p != NULL) {
+ directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
+ mask = p+1;
+ } else {
+ directory = talloc_strdup(ctx, "./");
+ mask = name;
+ }
+
+ if (!directory) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
/*
@@ -6624,210 +6592,167 @@ void reply_copy(struct smb_request *req)
* for a possible mangle. This patch from
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!VALID_STAT(smb_fname_src->st) &&
- mangle_is_mangled(fname_src_mask, conn->params)) {
- char *new_mask = NULL;
- mangle_lookup_name_from_8_3(ctx, fname_src_mask,
- &new_mask, conn->params);
- /* Use demangled name if one was successfully found. */
+ if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
+ char *new_mask = NULL;
+ mangle_lookup_name_from_8_3(ctx,
+ mask,
+ &new_mask,
+ conn->params );
if (new_mask) {
- TALLOC_FREE(fname_src_mask);
- fname_src_mask = new_mask;
+ mask = new_mask;
}
}
if (!source_has_wild) {
-
- /*
- * Only one file needs to be copied. Append the mask back onto
- * the directory.
- */
- TALLOC_FREE(smb_fname_src->base_name);
- smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
- "%s/%s",
- fname_src_dir,
- fname_src_mask);
- if (!smb_fname_src->base_name) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
-
+ directory = talloc_asprintf_append(directory,
+ "/%s",
+ mask);
if (dest_has_wild) {
- char *fname_dst_mod = NULL;
- if (!resolve_wildcards(smb_fname_dst,
- smb_fname_src->base_name,
- smb_fname_dst->base_name,
- &fname_dst_mod)) {
+ char *mod_newname = NULL;
+ if (!resolve_wildcards(ctx,
+ directory,newname,&mod_newname)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = fname_dst_mod;
+ newname = mod_newname;
}
- status = check_name(conn, smb_fname_src->base_name);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- status = check_name(conn, smb_fname_dst->base_name);
+ status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
- ofun, count, target_is_directory);
+ status = copy_file(ctx,conn,directory,newname,ofun,
+ count,target_is_directory);
if(!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
} else {
count++;
}
} else {
struct smb_Dir *dir_hnd = NULL;
const char *dname = NULL;
- char *talloced = NULL;
long offset = 0;
- /*
- * There is a wildcard that requires us to actually read the
- * src dir and copy each file matching the mask to the dst.
- * Right now streams won't be copied, but this could
- * presumably be added with a nested loop for reach dir entry.
- */
- SMB_ASSERT(!smb_fname_src->stream_name);
- SMB_ASSERT(!smb_fname_dst->stream_name);
-
- smb_fname_src->stream_name = NULL;
- smb_fname_dst->stream_name = NULL;
-
- if (strequal(fname_src_mask,"????????.???")) {
- TALLOC_FREE(fname_src_mask);
- fname_src_mask = talloc_strdup(ctx, "*");
- if (!fname_src_mask) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
- }
+ if (strequal(mask,"????????.???")) {
+ mask = mask_star;
}
- status = check_name(conn, fname_src_dir);
+ status = check_name(conn, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
+ dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
if (dir_hnd == NULL) {
status = map_nt_error_from_unix(errno);
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
error = ERRbadfile;
- /* Iterate over the src dir copying each entry to the dst. */
- while ((dname = ReadDirName(dir_hnd, &offset,
- &smb_fname_src->st, &talloced))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &sbuf1))) {
char *destname = NULL;
+ char *fname = NULL;
if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(talloced);
continue;
}
- if (!is_visible_file(conn, fname_src_dir, dname,
- &smb_fname_src->st, false)) {
- TALLOC_FREE(talloced);
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
continue;
}
- if(!mask_match(dname, fname_src_mask,
- conn->case_sensitive)) {
- TALLOC_FREE(talloced);
+ if(!mask_match(dname, mask, conn->case_sensitive)) {
continue;
}
error = ERRnoaccess;
-
- /* Get the src smb_fname struct setup. */
- TALLOC_FREE(smb_fname_src->base_name);
- smb_fname_src->base_name =
- talloc_asprintf(smb_fname_src, "%s/%s",
- fname_src_dir, dname);
-
- if (!smb_fname_src->base_name) {
+ fname = talloc_asprintf(ctx,
+ "%s/%s",
+ directory,
+ dname);
+ if (!fname) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(talloced);
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- if (!resolve_wildcards(ctx, smb_fname_src->base_name,
- smb_fname_dst->base_name,
- &destname)) {
- TALLOC_FREE(talloced);
+ if (!resolve_wildcards(ctx,
+ fname,newname,&destname)) {
continue;
}
if (!destname) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(talloced);
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- TALLOC_FREE(smb_fname_dst->base_name);
- smb_fname_dst->base_name = destname;
-
- status = check_name(conn, smb_fname_src->base_name);
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(talloced);
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- status = check_name(conn, smb_fname_dst->base_name);
+ status = check_name(conn, destname);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(talloced);
reply_nterror(req, status);
- goto out;
+ END_PROFILE(SMBcopy);
+ return;
}
- DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
- smb_fname_src->base_name,
- smb_fname_dst->base_name));
+ DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
- status = copy_file(ctx, conn, smb_fname_src,
- smb_fname_dst, ofun, count,
- target_is_directory);
+ status = copy_file(ctx,conn,fname,destname,ofun,
+ count,target_is_directory);
if (NT_STATUS_IS_OK(status)) {
count++;
}
-
- TALLOC_FREE(talloced);
+ TALLOC_FREE(fname);
+ TALLOC_FREE(destname);
}
TALLOC_FREE(dir_hnd);
}
if (count == 0) {
- reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
- goto out;
+ if(err) {
+ /* Error on close... */
+ errno = err;
+ reply_unixerror(req, ERRHRD, ERRgeneral);
+ END_PROFILE(SMBcopy);
+ return;
+ }
+
+ reply_doserror(req, ERRDOS, error);
+ END_PROFILE(SMBcopy);
+ return;
}
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,count);
- out:
- TALLOC_FREE(smb_fname_src);
- TALLOC_FREE(smb_fname_dst);
- TALLOC_FREE(fname_src);
- TALLOC_FREE(fname_dst);
- TALLOC_FREE(fname_src_mask);
- TALLOC_FREE(fname_src_dir);
END_PROFILE(SMBcopy);
return;
@@ -6972,238 +6897,6 @@ uint64_t get_lock_offset(const uint8_t *data, int data_offset,
return offset;
}
-NTSTATUS smbd_do_locking(struct smb_request *req,
- files_struct *fsp,
- uint8_t type,
- int32_t timeout,
- uint16_t num_ulocks,
- struct smbd_lock_element *ulocks,
- uint16_t num_locks,
- struct smbd_lock_element *locks,
- bool *async)
-{
- connection_struct *conn = req->conn;
- int i;
- NTSTATUS status = NT_STATUS_OK;
-
- *async = false;
-
- /* Data now points at the beginning of the list
- of smb_unlkrng structs */
- for(i = 0; i < (int)num_ulocks; i++) {
- struct smbd_lock_element *e = &ulocks[i];
-
- DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
- "pid %u, file %s\n",
- (double)e->offset,
- (double)e->count,
- (unsigned int)e->smbpid,
- fsp_str_dbg(fsp)));
-
- if (e->brltype != UNLOCK_LOCK) {
- /* this can only happen with SMB2 */
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- status = do_unlock(smbd_messaging_context(),
- fsp,
- e->smbpid,
- e->count,
- e->offset,
- WINDOWS_LOCK);
-
- DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
- nt_errstr(status)));
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
- /* Setup the timeout in seconds. */
-
- if (!lp_blocking_locks(SNUM(conn))) {
- timeout = 0;
- }
-
- /* Data now points at the beginning of the list
- of smb_lkrng structs */
-
- for(i = 0; i < (int)num_locks; i++) {
- struct smbd_lock_element *e = &locks[i];
-
- DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
- "%u, file %s timeout = %d\n",
- (double)e->offset,
- (double)e->count,
- (unsigned int)e->smbpid,
- fsp_str_dbg(fsp),
- (int)timeout));
-
- if (type & LOCKING_ANDX_CANCEL_LOCK) {
- struct blocking_lock_record *blr = NULL;
-
- if (num_locks > 1) {
- /*
- * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
- * if the lock vector contains one entry. When given mutliple cancel
- * requests in a single PDU we expect the server to return an
- * error. Windows servers seem to accept the request but only
- * cancel the first lock.
- * JRA - Do what Windows does (tm) :-).
- */
-
-#if 0
- /* MS-CIFS (2.2.4.32.1) behavior. */
- return NT_STATUS_DOS(ERRDOS,
- ERRcancelviolation);
-#else
- /* Windows behavior. */
- if (i != 0) {
- DEBUG(10,("smbd_do_locking: ignoring subsequent "
- "cancel request\n"));
- continue;
- }
-#endif
- }
-
- if (lp_blocking_locks(SNUM(conn))) {
-
- /* Schedule a message to ourselves to
- remove the blocking lock record and
- return the right error. */
-
- blr = blocking_lock_cancel(fsp,
- e->smbpid,
- e->offset,
- e->count,
- WINDOWS_LOCK,
- type,
- NT_STATUS_FILE_LOCK_CONFLICT);
- if (blr == NULL) {
- return NT_STATUS_DOS(
- ERRDOS,
- ERRcancelviolation);
- }
- }
- /* Remove a matching pending lock. */
- status = do_lock_cancel(fsp,
- e->smbpid,
- e->count,
- e->offset,
- WINDOWS_LOCK,
- blr);
- } else {
- bool blocking_lock = timeout ? true : false;
- bool defer_lock = false;
- struct byte_range_lock *br_lck;
- uint32_t block_smbpid;
-
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
- e->smbpid,
- e->count,
- e->offset,
- e->brltype,
- WINDOWS_LOCK,
- blocking_lock,
- &status,
- &block_smbpid,
- NULL);
-
- if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
- /* Windows internal resolution for blocking locks seems
- to be about 200ms... Don't wait for less than that. JRA. */
- if (timeout != -1 && timeout < lp_lock_spin_time()) {
- timeout = lp_lock_spin_time();
- }
- defer_lock = true;
- }
-
- /* If a lock sent with timeout of zero would fail, and
- * this lock has been requested multiple times,
- * according to brl_lock_failed() we convert this
- * request to a blocking lock with a timeout of between
- * 150 - 300 milliseconds.
- *
- * If lp_lock_spin_time() has been set to 0, we skip
- * this blocking retry and fail immediately.
- *
- * Replacement for do_lock_spin(). JRA. */
-
- if (br_lck && lp_blocking_locks(SNUM(conn)) &&
- lp_lock_spin_time() && !blocking_lock &&
- NT_STATUS_EQUAL((status),
- NT_STATUS_FILE_LOCK_CONFLICT))
- {
- defer_lock = true;
- timeout = lp_lock_spin_time();
- }
-
- if (br_lck && defer_lock) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(br_lck,
- req,
- fsp,
- timeout,
- i,
- e->smbpid,
- e->brltype,
- WINDOWS_LOCK,
- e->offset,
- e->count,
- block_smbpid)) {
- TALLOC_FREE(br_lck);
- *async = true;
- return NT_STATUS_OK;
- }
- }
-
- TALLOC_FREE(br_lck);
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- break;
- }
- }
-
- /* If any of the above locks failed, then we must unlock
- all of the previous locks (X/Open spec). */
-
- if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
-
- if (type & LOCKING_ANDX_CANCEL_LOCK) {
- i = -1; /* we want to skip the for loop */
- }
-
- /*
- * Ensure we don't do a remove on the lock that just failed,
- * as under POSIX rules, if we have a lock already there, we
- * will delete it (and we shouldn't) .....
- */
- for(i--; i >= 0; i--) {
- struct smbd_lock_element *e = &locks[i];
-
- do_unlock(smbd_messaging_context(),
- fsp,
- e->smbpid,
- e->count,
- e->offset,
- WINDOWS_LOCK);
- }
- return status;
- }
-
- DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
-
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Reply to a lockingX request.
****************************************************************************/
@@ -7216,15 +6909,14 @@ void reply_lockingX(struct smb_request *req)
unsigned char oplocklevel;
uint16 num_ulocks;
uint16 num_locks;
+ uint64_t count = 0, offset = 0;
+ uint32 lock_pid;
int32 lock_timeout;
int i;
const uint8_t *data;
bool large_file_format;
bool err;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
- struct smbd_lock_element *ulocks;
- struct smbd_lock_element *locks;
- bool async = false;
START_PROFILE(SMBlockingX);
@@ -7253,7 +6945,7 @@ void reply_lockingX(struct smb_request *req)
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don't really want to be
compatible! (tridge) */
- reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
+ reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
END_PROFILE(SMBlockingX);
return;
}
@@ -7286,8 +6978,7 @@ void reply_lockingX(struct smb_request *req)
DEBUG(5,("reply_lockingX: Error : oplock break from "
"client for fnum = %d (oplock=%d) and no "
"oplock granted on this file (%s).\n",
- fsp->fnum, fsp->oplock_type,
- fsp_str_dbg(fsp)));
+ fsp->fnum, fsp->oplock_type, fsp->fsp_name));
/* if this is a pure oplock break request then don't
* send a reply */
@@ -7296,7 +6987,7 @@ void reply_lockingX(struct smb_request *req)
return;
} else {
END_PROFILE(SMBlockingX);
- reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
+ reply_doserror(req, ERRDOS, ERRlock);
return;
}
}
@@ -7310,7 +7001,7 @@ void reply_lockingX(struct smb_request *req)
if (!result) {
DEBUG(0, ("reply_lockingX: error in removing "
- "oplock on file %s\n", fsp_str_dbg(fsp)));
+ "oplock on file %s\n", fsp->fsp_name));
/* Hmmm. Is this panic justified? */
smb_panic("internal tdb error");
}
@@ -7338,38 +7029,49 @@ void reply_lockingX(struct smb_request *req)
return;
}
- ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
- if (ulocks == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBlockingX);
- return;
- }
-
- locks = talloc_array(req, struct smbd_lock_element, num_locks);
- if (locks == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBlockingX);
- return;
- }
-
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for(i = 0; i < (int)num_ulocks; i++) {
- ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
- ulocks[i].count = get_lock_count(data, i, large_file_format);
- ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
- ulocks[i].brltype = UNLOCK_LOCK;
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format, &err);
/*
* There is no error code marked "stupid client bug".... :-).
*/
if(err) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
END_PROFILE(SMBlockingX);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
+
+ DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
+ "pid %u, file %s\n", (double)offset, (double)count,
+ (unsigned int)lock_pid, fsp->fsp_name ));
+
+ status = do_unlock(smbd_messaging_context(),
+ fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
+
+ DEBUG(10, ("reply_lockingX: unlock returned %s\n",
+ nt_errstr(status)));
+
+ if (NT_STATUS_V(status)) {
+ END_PROFILE(SMBlockingX);
+ reply_nterror(req, status);
return;
}
}
+ /* Setup the timeout in seconds. */
+
+ if (!lp_blocking_locks(SNUM(conn))) {
+ lock_timeout = 0;
+ }
+
/* Now do any requested locks */
data += ((large_file_format ? 20 : 10)*num_ulocks);
@@ -7377,48 +7079,168 @@ void reply_lockingX(struct smb_request *req)
of smb_lkrng structs */
for(i = 0; i < (int)num_locks; i++) {
- locks[i].smbpid = get_lock_pid(data, i, large_file_format);
- locks[i].count = get_lock_count(data, i, large_file_format);
- locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
-
- if (locktype & LOCKING_ANDX_SHARED_LOCK) {
- if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- locks[i].brltype = PENDING_READ_LOCK;
- } else {
- locks[i].brltype = READ_LOCK;
- }
- } else {
- if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
- locks[i].brltype = PENDING_WRITE_LOCK;
- } else {
- locks[i].brltype = WRITE_LOCK;
- }
- }
+ enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
+ READ_LOCK:WRITE_LOCK);
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format, &err);
/*
* There is no error code marked "stupid client bug".... :-).
*/
if(err) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
END_PROFILE(SMBlockingX);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
+
+ DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
+ "%u, file %s timeout = %d\n", (double)offset,
+ (double)count, (unsigned int)lock_pid,
+ fsp->fsp_name, (int)lock_timeout ));
+
+ if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ struct blocking_lock_record *blr = NULL;
+
+ if (lp_blocking_locks(SNUM(conn))) {
+
+ /* Schedule a message to ourselves to
+ remove the blocking lock record and
+ return the right error. */
+
+ blr = blocking_lock_cancel(fsp,
+ lock_pid,
+ offset,
+ count,
+ WINDOWS_LOCK,
+ locktype,
+ NT_STATUS_FILE_LOCK_CONFLICT);
+ if (blr == NULL) {
+ END_PROFILE(SMBlockingX);
+ reply_nterror(
+ req,
+ NT_STATUS_DOS(
+ ERRDOS,
+ ERRcancelviolation));
+ return;
+ }
+ }
+ /* Remove a matching pending lock. */
+ status = do_lock_cancel(fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK,
+ blr);
+ } else {
+ bool blocking_lock = lock_timeout ? True : False;
+ bool defer_lock = False;
+ struct byte_range_lock *br_lck;
+ uint32 block_smbpid;
+
+ br_lck = do_lock(smbd_messaging_context(),
+ fsp,
+ lock_pid,
+ count,
+ offset,
+ lock_type,
+ WINDOWS_LOCK,
+ blocking_lock,
+ &status,
+ &block_smbpid,
+ NULL);
+
+ if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
+ /* Windows internal resolution for blocking locks seems
+ to be about 200ms... Don't wait for less than that. JRA. */
+ if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
+ lock_timeout = lp_lock_spin_time();
+ }
+ defer_lock = True;
+ }
+
+ /* This heuristic seems to match W2K3 very well. If a
+ lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
+ it pretends we asked for a timeout of between 150 - 300 milliseconds as
+ far as I can tell. Replacement for do_lock_spin(). JRA. */
+
+ if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
+ NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
+ defer_lock = True;
+ lock_timeout = lp_lock_spin_time();
+ }
+
+ if (br_lck && defer_lock) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(br_lck,
+ req,
+ fsp,
+ lock_timeout,
+ i,
+ lock_pid,
+ lock_type,
+ WINDOWS_LOCK,
+ offset,
+ count,
+ block_smbpid)) {
+ TALLOC_FREE(br_lck);
+ END_PROFILE(SMBlockingX);
+ return;
+ }
+ }
+
+ TALLOC_FREE(br_lck);
+ }
+
+ if (NT_STATUS_V(status)) {
+ break;
+ }
}
- status = smbd_do_locking(req, fsp,
- locktype, lock_timeout,
- num_ulocks, ulocks,
- num_locks, locks,
- &async);
- if (!NT_STATUS_IS_OK(status)) {
+ /* If any of the above locks failed, then we must unlock
+ all of the previous locks (X/Open spec). */
+ if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
+
+ if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ i = -1; /* we want to skip the for loop */
+ }
+
+ /*
+ * Ensure we don't do a remove on the lock that just failed,
+ * as under POSIX rules, if we have a lock already there, we
+ * will delete it (and we shouldn't) .....
+ */
+ for(i--; i >= 0; i--) {
+ lock_pid = get_lock_pid( data, i, large_file_format);
+ count = get_lock_count( data, i, large_file_format);
+ offset = get_lock_offset( data, i, large_file_format,
+ &err);
+
+ /*
+ * There is no error code marked "stupid client
+ * bug".... :-).
+ */
+ if(err) {
+ END_PROFILE(SMBlockingX);
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
+
+ do_unlock(smbd_messaging_context(),
+ fsp,
+ lock_pid,
+ count,
+ offset,
+ WINDOWS_LOCK);
+ }
END_PROFILE(SMBlockingX);
reply_nterror(req, status);
return;
}
- if (async) {
- END_PROFILE(SMBlockingX);
- return;
- }
reply_outbuf(req, 2, 0);
@@ -7441,7 +7263,7 @@ void reply_lockingX(struct smb_request *req)
void reply_readbmpx(struct smb_request *req)
{
START_PROFILE(SMBreadBmpx);
- reply_force_doserror(req, ERRSRV, ERRuseSTD);
+ reply_doserror(req, ERRSRV, ERRuseSTD);
END_PROFILE(SMBreadBmpx);
return;
}
@@ -7455,7 +7277,7 @@ void reply_readbmpx(struct smb_request *req)
void reply_readbs(struct smb_request *req)
{
START_PROFILE(SMBreadBs);
- reply_force_doserror(req, ERRSRV, ERRuseSTD);
+ reply_doserror(req, ERRSRV, ERRuseSTD);
END_PROFILE(SMBreadBs);
return;
}
@@ -7469,6 +7291,7 @@ void reply_setattrE(struct smb_request *req)
connection_struct *conn = req->conn;
struct smb_file_time ft;
files_struct *fsp;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBsetattrE);
@@ -7476,16 +7299,19 @@ void reply_setattrE(struct smb_request *req)
if (req->wct < 7) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ END_PROFILE(SMBsetattrE);
+ return;
}
fsp = file_fsp(req, SVAL(req->vwv+0, 0));
if(!fsp || (fsp->conn != conn)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
- goto out;
+ reply_doserror(req, ERRDOS, ERRbadfid);
+ END_PROFILE(SMBsetattrE);
+ return;
}
+
/*
* Convert the DOS times into unix times.
*/
@@ -7505,16 +7331,35 @@ void reply_setattrE(struct smb_request *req)
*/
/* Ensure we have a valid stat struct for the source. */
- status = vfs_stat_fsp(fsp);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetattrE);
+ return;
+ }
+ } else {
+ int ret = -1;
+
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf);
+ }
+ if (ret == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetattrE);
+ return;
+ }
}
- status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name,
+ &sbuf, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- goto out;
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBsetattrE);
+ return;
}
DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
@@ -7524,7 +7369,7 @@ void reply_setattrE(struct smb_request *req)
(unsigned int)ft.mtime.tv_sec,
(unsigned int)ft.create_time.tv_sec
));
- out:
+
END_PROFILE(SMBsetattrE);
return;
}
@@ -7541,7 +7386,7 @@ void reply_setattrE(struct smb_request *req)
void reply_writebmpx(struct smb_request *req)
{
START_PROFILE(SMBwriteBmpx);
- reply_force_doserror(req, ERRSRV, ERRuseSTD);
+ reply_doserror(req, ERRSRV, ERRuseSTD);
END_PROFILE(SMBwriteBmpx);
return;
}
@@ -7555,7 +7400,7 @@ void reply_writebmpx(struct smb_request *req)
void reply_writebs(struct smb_request *req)
{
START_PROFILE(SMBwriteBs);
- reply_force_doserror(req, ERRSRV, ERRuseSTD);
+ reply_doserror(req, ERRSRV, ERRuseSTD);
END_PROFILE(SMBwriteBs);
return;
}
@@ -7567,6 +7412,7 @@ void reply_writebs(struct smb_request *req)
void reply_getattrE(struct smb_request *req)
{
connection_struct *conn = req->conn;
+ SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
struct timespec create_ts;
@@ -7582,19 +7428,19 @@ void reply_getattrE(struct smb_request *req)
fsp = file_fsp(req, SVAL(req->vwv+0, 0));
if(!fsp || (fsp->conn != conn)) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBgetattrE);
return;
}
/* Do an fstat on this file */
- if(fsp_stat(fsp)) {
- reply_nterror(req, map_nt_error_from_unix(errno));
+ if(fsp_stat(fsp, &sbuf)) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBgetattrE);
return;
}
- mode = dos_mode(conn, fsp->fsp_name);
+ mode = dos_mode(conn,fsp->fsp_name,&sbuf);
/*
* Convert the times into dos times. Set create
@@ -7604,20 +7450,19 @@ void reply_getattrE(struct smb_request *req)
reply_outbuf(req, 11, 0);
- create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
+ create_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
- srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
- convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
+ srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
/* Should we check pending modtime here ? JRA */
- srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
- convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
+ srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
if (mode & aDIR) {
SIVAL(req->outbuf, smb_vwv6, 0);
SIVAL(req->outbuf, smb_vwv8, 0);
} else {
- uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
- SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
+ uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
+ SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
SIVAL(req->outbuf, smb_vwv8, allocation_size);
}
SSVAL(req->outbuf,smb_vwv10, mode);
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index 2d738cbd12..0d5415b5f4 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -19,7 +19,6 @@
#include "includes.h"
#include "smbd/globals.h"
-#include "../libcli/auth/spnego.h"
/******************************************************************************
Server side encryption.
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 642980a6b9..2c5ce40085 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -181,34 +181,20 @@ static void msg_inject_fault(struct messaging_context *msg,
}
#endif /* DEVELOPER */
-/*
- * Parent smbd process sets its own debug level first and then
- * sends a message to all the smbd children to adjust their debug
- * level to that of the parent.
- */
-
-static void smbd_msg_debug(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
-{
- struct child_pid *child;
-
- debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
-
- for (child = children; child != NULL; child = child->next) {
- messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
- MSG_DEBUG,
- data->data,
- strlen((char *) data->data) + 1);
- }
-}
+struct child_pid {
+ struct child_pid *prev, *next;
+ pid_t pid;
+};
static void add_child_pid(pid_t pid)
{
struct child_pid *child;
+ if (lp_max_smbd_processes() == 0) {
+ /* Don't bother with the child list if we don't care anyway */
+ return;
+ }
+
child = SMB_MALLOC_P(struct child_pid);
if (child == NULL) {
DEBUG(0, ("Could not add child struct -- malloc failed\n"));
@@ -234,6 +220,11 @@ static void remove_child_pid(pid_t pid, bool unclean_shutdown)
MSG_SMB_UNLOCK, NULL, 0, NULL);
}
+ if (lp_max_smbd_processes() == 0) {
+ /* Don't bother with the child list if we don't care anyway */
+ return;
+ }
+
for (child = children; child != NULL; child = child->next) {
if (child->pid == pid) {
struct child_pid *tmp = child;
@@ -646,8 +637,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
MSG_SMB_CONF_UPDATED, smb_conf_updated);
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_DEBUG, smbd_msg_debug);
brl_register_msgs(smbd_messaging_context());
#ifdef CLUSTER_SUPPORT
@@ -710,10 +699,6 @@ void reload_printers(void)
int pnum = lp_servicenumber(PRINTERS_NAME);
const char *pname;
- if (!lp_load_printers()
- && (lp_auto_services() == NULL || !strcmp(lp_auto_services(),"")))
- return;
-
pcap_cache_reload();
/* remove stale printers */
@@ -800,8 +785,7 @@ static void exit_server_common(enum server_exit_reason how,
static void exit_server_common(enum server_exit_reason how,
const char *const reason)
{
- bool had_open_conn = false;
- struct smbd_server_connection *sconn = smbd_server_conn;
+ bool had_open_conn;
if (!exit_firsttime)
exit(0);
@@ -809,15 +793,13 @@ static void exit_server_common(enum server_exit_reason how,
change_to_root_user();
- if (sconn && sconn->smb1.negprot.auth_context) {
- struct auth_context *a = sconn->smb1.negprot.auth_context;
- a->free(&sconn->smb1.negprot.auth_context);
+ if (negprot_global_auth_context) {
+ (negprot_global_auth_context->free)(&negprot_global_auth_context);
}
- if (sconn) {
- had_open_conn = conn_close_all(sconn);
- invalidate_all_vuids(sconn);
- }
+ had_open_conn = conn_close_all();
+
+ invalidate_all_vuids();
/* 3 second timeout. */
print_notify_send_messages(smbd_messaging_context(), 3);
@@ -843,15 +825,6 @@ static void exit_server_common(enum server_exit_reason how,
locking_end();
printing_end();
- /*
- * we need to force the order of freeing the following,
- * because smbd_msg_ctx is not a talloc child of smbd_server_conn.
- */
- sconn = NULL;
- TALLOC_FREE(smbd_server_conn);
- TALLOC_FREE(smbd_msg_ctx);
- TALLOC_FREE(smbd_event_ctx);
-
if (how != SERVER_EXIT_NORMAL) {
int oldlevel = DEBUGLEVEL;
@@ -873,7 +846,6 @@ static void exit_server_common(enum server_exit_reason how,
if (am_parent) {
pidfile_unlink();
}
- gencache_stabilize();
}
/* if we had any open SMB connections when we exited then we
@@ -916,8 +888,12 @@ static bool init_structs(void )
if (!init_names())
return False;
+ conn_init();
+
file_init();
+ init_dptrs();
+
if (!secrets_init())
return False;
@@ -1222,15 +1198,6 @@ extern void build_options(bool screen);
return -1;
}
- /* Open the share_info.tdb here, so we don't have to open
- after the fork on every single connection. This is a small
- performance improvment and reduces the total number of system
- fds used. */
- if (!share_info_db_init()) {
- DEBUG(0,("ERROR: failed to load share info db.\n"));
- exit(1);
- }
-
/* only start the background queue daemon if we are
running as a daemon -- bad things will happen if
smbd is launched via inetd and we fork a copy of
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 572861a084..8490f17dea 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -187,8 +187,8 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
if (do_chdir &&
vfs_ChDir(conn,conn->connectpath) != 0 &&
vfs_ChDir(conn,conn->origpath) != 0) {
- DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
- conn->connectpath, strerror(errno)));
+ DEBUG(0,("chdir (%s) failed\n",
+ conn->connectpath));
return(False);
}
@@ -306,7 +306,6 @@ int add_home_service(const char *service, const char *username, const char *home
int find_service(fstring service)
{
int iService;
- struct smbd_server_connection *sconn = smbd_server_conn;
all_string_sub(service,"\\","/",0);
@@ -321,7 +320,7 @@ int find_service(fstring service)
* Try mapping the servicename, it may
* be a Windows to unix mapped user name.
*/
- if(map_username(sconn, service))
+ if(map_username(service))
phome_dir = get_user_home_dir(
talloc_tos(), service);
}
@@ -562,8 +561,7 @@ static NTSTATUS find_forced_group(bool force_user,
Create an auth_serversupplied_info structure for a connection_struct
****************************************************************************/
-static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
- TALLOC_CTX *mem_ctx, int snum,
+static NTSTATUS create_connection_server_info(TALLOC_CTX *mem_ctx, int snum,
struct auth_serversupplied_info *vuid_serverinfo,
DATA_BLOB password,
struct auth_serversupplied_info **presult)
@@ -617,11 +615,11 @@ static NTSTATUS create_connection_server_info(struct smbd_server_connection *sco
/* add the sharename as a possible user name if we
are in share mode security */
- add_session_user(sconn, lp_servicename(snum));
+ add_session_user(lp_servicename(snum));
/* shall we let them in? */
- if (!authorise_login(sconn, snum,user,password,&guest)) {
+ if (!authorise_login(snum,user,password,&guest)) {
DEBUG( 2, ( "Invalid username/password for [%s]\n",
lp_servicename(snum)) );
return NT_STATUS_WRONG_PASSWORD;
@@ -641,26 +639,26 @@ static NTSTATUS create_connection_server_info(struct smbd_server_connection *sco
connecting user if appropriate.
****************************************************************************/
-connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
- int snum, user_struct *vuser,
- DATA_BLOB password,
- const char *pdev,
- NTSTATUS *pstatus)
+static connection_struct *make_connection_snum(int snum, user_struct *vuser,
+ DATA_BLOB password,
+ const char *pdev,
+ NTSTATUS *pstatus)
{
connection_struct *conn;
- struct smb_filename *smb_fname_cpath = NULL;
+ SMB_STRUCT_STAT st;
fstring dev;
int ret;
char addr[INET6_ADDRSTRLEN];
NTSTATUS status;
fstrcpy(dev, pdev);
+ SET_STAT_INVALID(st);
if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
return NULL;
}
- conn = conn_new(sconn);
+ conn = conn_new();
if (!conn) {
DEBUG(0,("Couldn't find free connection.\n"));
*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
@@ -669,7 +667,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
conn->params->service = snum;
- status = create_connection_server_info(sconn,
+ status = create_connection_server_info(
conn, snum, vuser ? vuser->server_info : NULL, password,
&conn->server_info);
@@ -685,7 +683,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
conn->force_user = true;
}
- add_session_user(sconn, conn->server_info->unix_name);
+ add_session_user(conn->server_info->unix_name);
safe_strcpy(conn->client_address,
client_addr(get_client_fd(),addr,sizeof(addr)),
@@ -696,6 +694,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
conn->printer = (strncmp(dev,"LPT",3) == 0);
conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
+ conn->dirptr = NULL;
/* Case options for the share. */
if (lp_casesensitive(snum) == Auto) {
@@ -715,6 +714,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
conn->hide_list = NULL;
conn->veto_oplock_list = NULL;
conn->aio_write_behind_list = NULL;
+ string_set(&conn->dirpath,"");
conn->read_only = lp_readonly(SNUM(conn));
conn->admin_user = False;
@@ -1006,21 +1006,15 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
lp_aio_write_behind(snum));
}
- status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
- NULL, NULL, &smb_fname_cpath);
- if (!NT_STATUS_IS_OK(status)) {
- *pstatus = status;
- goto err_root_exit;
- }
/* win2000 does not check the permissions on the directory
during the tree connect, instead relying on permission
check during individual operations. To match this behaviour
I have disabled this chdir check (tridge) */
/* the alternative is just to check the directory exists */
- if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
- !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
- if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
+ if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
+ !S_ISDIR(st.st_mode)) {
+ if (ret == 0 && !S_ISDIR(st.st_mode)) {
DEBUG(0,("'%s' is not a directory, when connecting to "
"[%s]\n", conn->connectpath,
lp_servicename(snum)));
@@ -1058,7 +1052,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
* the same characteristics, which is likely but not guaranteed.
*/
- conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
+ conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
/*
* Print out the 'connected as' stuff here as we need
@@ -1069,7 +1063,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
dbgtext( "%s (%s) ", get_remote_machine_name(),
conn->client_address );
- dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
+ dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
dbgtext( "connect to service %s ", lp_servicename(snum) );
dbgtext( "initially as user %s ",
conn->server_info->unix_name );
@@ -1082,7 +1076,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
return(conn);
err_root_exit:
- TALLOC_FREE(smb_fname_cpath);
+
change_to_root_user();
/* Call VFS disconnect hook */
SMB_VFS_DISCONNECT(conn);
@@ -1097,8 +1091,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
* @param service
****************************************************************************/
-connection_struct *make_connection(struct smbd_server_connection *sconn,
- const char *service_in, DATA_BLOB password,
+connection_struct *make_connection(const char *service_in, DATA_BLOB password,
const char *pdev, uint16 vuid,
NTSTATUS *status)
{
@@ -1119,13 +1112,13 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
}
- if (conn_num_open(sconn) > 2047) {
+ if (conn_num_open() > 2047) {
*status = NT_STATUS_INSUFF_SERVER_RESOURCES;
return NULL;
}
if(lp_security() != SEC_SHARE) {
- vuser = get_valid_user_struct(sconn, vuid);
+ vuser = get_valid_user_struct(vuid);
if (!vuser) {
DEBUG(1,("make_connection: refusing to connect with "
"no session setup\n"));
@@ -1156,8 +1149,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
}
DEBUG(5, ("making a connection to [homes] service "
"created at session setup time\n"));
- return make_connection_snum(sconn,
- vuser->homes_snum,
+ return make_connection_snum(vuser->homes_snum,
vuser, no_pw,
dev, status);
} else {
@@ -1167,15 +1159,14 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
fstring unix_username;
fstrcpy(unix_username,
current_user_info.smb_name);
- map_username(sconn, unix_username);
+ map_username(unix_username);
snum = find_service(unix_username);
}
if (snum != -1) {
DEBUG(5, ("making a connection to 'homes' "
"service %s based on "
"security=share\n", service_in));
- return make_connection_snum(sconn,
- snum, NULL,
+ return make_connection_snum(snum, NULL,
password,
dev, status);
}
@@ -1186,8 +1177,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
DATA_BLOB no_pw = data_blob_null;
DEBUG(5, ("making a connection to 'homes' service [%s] "
"created at session setup time\n", service_in));
- return make_connection_snum(sconn,
- vuser->homes_snum,
+ return make_connection_snum(vuser->homes_snum,
vuser, no_pw,
dev, status);
}
@@ -1206,7 +1196,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
return NULL;
}
- DEBUG(3,("%s (%s) couldn't find service %s\n",
+ DEBUG(0,("%s (%s) couldn't find service %s\n",
get_remote_machine_name(),
client_addr(get_client_fd(),addr,sizeof(addr)),
service));
@@ -1225,7 +1215,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
DEBUG(5, ("making a connection to 'normal' service %s\n", service));
- return make_connection_snum(sconn, snum, vuser,
+ return make_connection_snum(snum, vuser,
password,
dev, status);
}
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 1529166d43..044e3988af 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -24,16 +24,8 @@
#include "includes.h"
#include "smbd/globals.h"
-#include "../libcli/auth/spnego.h"
-/* For split krb5 SPNEGO blobs. */
-struct pending_auth_data {
- struct pending_auth_data *prev, *next;
- uint16 vuid; /* Tag for this entry. */
- uint16 smbpid; /* Alternate tag for this entry. */
- size_t needed_len;
- DATA_BLOB partial_data;
-};
+extern enum protocol_types Protocol;
/*
on a logon error possibly map the error to success if "map to guest"
@@ -99,6 +91,25 @@ static int push_signature(uint8 **outbuf)
}
/****************************************************************************
+ Start the signing engine if needed. Don't fail signing here.
+****************************************************************************/
+
+static void sessionsetup_start_signing_engine(
+ const auth_serversupplied_info *server_info,
+ const uint8 *inbuf)
+{
+ if (!server_info->guest && !srv_signing_started()) {
+ /* We need to start the signing engine
+ * here but a W2K client sends the old
+ * "BSRSPYL " signature instead of the
+ * correct one. Subsequent packets will
+ * be correct.
+ */
+ srv_check_sign_mac((char *)inbuf, False);
+ }
+}
+
+/****************************************************************************
Send a security blob via a session setup reply.
****************************************************************************/
@@ -251,7 +262,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
bool map_domainuser_to_guest = False;
bool username_was_mapped;
struct PAC_LOGON_INFO *logon_info = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
ZERO_STRUCT(ticket);
ZERO_STRUCT(ap_rep);
@@ -415,7 +425,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
/* lookup the passwd struct, create a new user if necessary */
- username_was_mapped = map_username(sconn, user);
+ username_was_mapped = map_username( user );
pw = smb_getpwnam( mem_ctx, user, real_username, True );
@@ -485,40 +495,10 @@ static void reply_spnego_kerberos(struct smb_request *req,
}
} else {
- /*
- * We didn't get a PAC, we have to make up the user
- * ourselves. Try to ask the pdb backend to provide
- * SID consistency with ntlmssp session setup
- */
- struct samu *sampass;
-
- sampass = samu_new(talloc_tos());
- if (sampass == NULL) {
- ret = NT_STATUS_NO_MEMORY;
- data_blob_free(&ap_rep);
- data_blob_free(&session_key);
- TALLOC_FREE(mem_ctx);
- reply_nterror(req, nt_status_squash(ret));
- return;
- }
-
- if (pdb_getsampwnam(sampass, real_username)) {
- DEBUG(10, ("found user %s in passdb, calling "
- "make_server_info_sam\n", real_username));
- ret = make_server_info_sam(&server_info, sampass);
- } else {
- /*
- * User not in passdb, make it up artificially
- */
- TALLOC_FREE(sampass);
- DEBUG(10, ("didn't find user %s in passdb, calling "
- "make_server_info_pw\n", real_username));
- ret = make_server_info_pw(&server_info, real_username,
- pw);
- }
+ ret = make_server_info_pw(&server_info, real_username, pw);
if ( !NT_STATUS_IS_OK(ret) ) {
- DEBUG(1,("make_server_info_[sam|pw] failed: %s!\n",
+ DEBUG(1,("make_server_info_pw failed: %s!\n",
nt_errstr(ret)));
data_blob_free(&ap_rep);
data_blob_free(&session_key);
@@ -556,8 +536,8 @@ static void reply_spnego_kerberos(struct smb_request *req,
}
}
- if (!is_partial_auth_vuid(sconn, sess_vuid)) {
- sess_vuid = register_initial_vuid(sconn);
+ if (!is_partial_auth_vuid(sess_vuid)) {
+ sess_vuid = register_initial_vuid();
}
data_blob_free(&server_info->user_session_key);
@@ -569,8 +549,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
* no need to free after this on success. A better interface would copy
* it.... */
- sess_vuid = register_existing_vuid(sconn,
- sess_vuid,
+ sess_vuid = register_existing_vuid(sess_vuid,
server_info,
nullblob,
client);
@@ -592,6 +571,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
SSVAL(req->outbuf, smb_uid, sess_vuid);
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
/* Successful logon. Keep this vuid. */
*p_invalidate_vuid = False;
}
@@ -632,7 +612,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
{
DATA_BLOB response;
struct auth_serversupplied_info *server_info = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
if (NT_STATUS_IS_OK(nt_status)) {
server_info = (*auth_ntlmssp_state)->server_info;
@@ -650,7 +629,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
if (NT_STATUS_IS_OK(nt_status)) {
DATA_BLOB nullblob = data_blob_null;
- if (!is_partial_auth_vuid(sconn, vuid)) {
+ if (!is_partial_auth_vuid(vuid)) {
nt_status = NT_STATUS_LOGON_FAILURE;
goto out;
}
@@ -663,7 +642,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
(*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
/* register_existing_vuid keeps the server info */
- if (register_existing_vuid(sconn, vuid,
+ if (register_existing_vuid(vuid,
server_info, nullblob,
(*auth_ntlmssp_state)->ntlmssp_state->user) !=
vuid) {
@@ -681,6 +660,9 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
if (server_info->guest) {
SSVAL(req->outbuf,smb_vwv2,1);
}
+
+ sessionsetup_start_signing_engine(server_info,
+ (uint8 *)req->inbuf);
}
out:
@@ -705,7 +687,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
auth_ntlmssp_end(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(nt_status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
}
}
}
@@ -791,12 +773,11 @@ static void reply_spnego_negotiate(struct smb_request *req,
DATA_BLOB chal;
char *kerb_mech = NULL;
NTSTATUS status;
- struct smbd_server_connection *sconn = smbd_server_conn;
status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
@@ -813,7 +794,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
data_blob_free(&secblob);
if (destroy_vuid) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
}
SAFE_FREE(kerb_mech);
return;
@@ -836,7 +817,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
@@ -868,14 +849,13 @@ static void reply_spnego_auth(struct smb_request *req,
DATA_BLOB auth_reply = data_blob_null;
DATA_BLOB secblob = data_blob_null;
NTSTATUS status = NT_STATUS_LOGON_FAILURE;
- struct smbd_server_connection *sconn = smbd_server_conn;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
file_save("auth.dat", blob1.data, blob1.length);
#endif
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(
NT_STATUS_LOGON_FAILURE));
@@ -890,7 +870,7 @@ static void reply_spnego_auth(struct smb_request *req,
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
@@ -907,7 +887,7 @@ static void reply_spnego_auth(struct smb_request *req,
data_blob_free(&auth);
if (destroy_vuid) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
}
SAFE_FREE(kerb_mech);
return;
@@ -918,7 +898,7 @@ static void reply_spnego_auth(struct smb_request *req,
if (kerb_mech) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
DEBUG(3,("reply_spnego_auth: network "
"misconfiguration, client sent us a "
"krb5 ticket and kerberos security "
@@ -936,7 +916,7 @@ static void reply_spnego_auth(struct smb_request *req,
status = auth_ntlmssp_start(auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
reply_nterror(req, nt_status_squash(status));
return;
}
@@ -963,13 +943,12 @@ static void reply_spnego_auth(struct smb_request *req,
Delete an entry on the list.
****************************************************************************/
-static void delete_partial_auth(struct smbd_server_connection *sconn,
- struct pending_auth_data *pad)
+static void delete_partial_auth(struct pending_auth_data *pad)
{
if (!pad) {
return;
}
- DLIST_REMOVE(sconn->smb1.pd_list, pad);
+ DLIST_REMOVE(pd_list, pad);
data_blob_free(&pad->partial_data);
SAFE_FREE(pad);
}
@@ -978,17 +957,11 @@ static void delete_partial_auth(struct smbd_server_connection *sconn,
Search for a partial SPNEGO auth fragment matching an smbpid.
****************************************************************************/
-static struct pending_auth_data *get_pending_auth_data(
- struct smbd_server_connection *sconn,
- uint16_t smbpid)
+static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
{
struct pending_auth_data *pad;
-/*
- * NOTE: using the smbpid here is completely wrong...
- * see [MS-SMB]
- * 3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
- */
- for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
+
+ for (pad = pd_list; pad; pad = pad->next) {
if (pad->smbpid == smbpid) {
break;
}
@@ -1002,21 +975,20 @@ static struct pending_auth_data *get_pending_auth_data(
the blob to be more than 64k.
****************************************************************************/
-static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
- uint16 smbpid, uint16 vuid,
- DATA_BLOB *pblob)
+static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
+ DATA_BLOB *pblob)
{
struct pending_auth_data *pad = NULL;
ASN1_DATA *data;
size_t needed_len = 0;
- pad = get_pending_auth_data(sconn, smbpid);
+ pad = get_pending_auth_data(smbpid);
/* Ensure we have some data. */
if (pblob->length == 0) {
/* Caller can cope. */
DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
- delete_partial_auth(sconn, pad);
+ delete_partial_auth(pad);
return NT_STATUS_OK;
}
@@ -1037,7 +1009,7 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
(unsigned int)pad->partial_data.length,
(unsigned int)copy_len ));
- delete_partial_auth(sconn, pad);
+ delete_partial_auth(pad);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -1073,7 +1045,7 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
data_blob_free(pblob);
*pblob = pad->partial_data;
ZERO_STRUCT(pad->partial_data);
- delete_partial_auth(sconn, pad);
+ delete_partial_auth(pad);
return NT_STATUS_OK;
}
@@ -1158,7 +1130,7 @@ static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
}
pad->smbpid = smbpid;
pad->vuid = vuid;
- DLIST_ADD(sconn->smb1.pd_list, pad);
+ DLIST_ADD(pd_list, pad);
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
@@ -1184,7 +1156,6 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
user_struct *vuser = NULL;
NTSTATUS status = NT_STATUS_OK;
uint16 smbpid = req->smbpid;
- struct smbd_server_connection *sconn = smbd_server_conn;
DEBUG(3,("Doing spnego session setup\n"));
@@ -1247,11 +1218,10 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
}
/* Did we get a valid vuid ? */
- if (!is_partial_auth_vuid(sconn, vuid)) {
+ if (!is_partial_auth_vuid(vuid)) {
/* No, then try and see if this is an intermediate sessionsetup
* for a large SPNEGO packet. */
- struct pending_auth_data *pad;
- pad = get_pending_auth_data(sconn, smbpid);
+ struct pending_auth_data *pad = get_pending_auth_data(smbpid);
if (pad) {
DEBUG(10,("reply_sesssetup_and_X_spnego: found "
"pending vuid %u\n",
@@ -1261,9 +1231,9 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
}
/* Do we have a valid vuid now ? */
- if (!is_partial_auth_vuid(sconn, vuid)) {
+ if (!is_partial_auth_vuid(vuid)) {
/* No, start a new authentication setup. */
- vuid = register_initial_vuid(sconn);
+ vuid = register_initial_vuid();
if (vuid == UID_FIELD_INVALID) {
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(
@@ -1272,7 +1242,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
}
}
- vuser = get_partial_auth_user_struct(sconn, vuid);
+ vuser = get_partial_auth_user_struct(vuid);
/* This MUST be valid. */
if (!vuser) {
smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
@@ -1283,12 +1253,12 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
* field is 4k. Bug #4400. JRA.
*/
- status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
+ status = check_spnego_blob_complete(smbpid, vuid, &blob1);
if (!NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_EQUAL(status,
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
/* Real error - kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
}
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(status));
@@ -1322,7 +1292,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
if (!NT_STATUS_IS_OK(status)) {
/* Kill the intermediate vuid */
- invalidate_vuid(sconn, vuid);
+ invalidate_vuid(vuid);
data_blob_free(&blob1);
reply_nterror(req, nt_status_squash(status));
return;
@@ -1422,9 +1392,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
uint16 smb_flag2 = req->flags2;
NTSTATUS nt_status;
- struct smbd_server_connection *sconn = smbd_server_conn;
- bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
+ bool doencrypt = global_encrypted_passwords_negotiated;
START_PROFILE(SMBsesssetupX);
@@ -1439,7 +1408,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
if (req->wct == 12 &&
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
- if (!sconn->smb1.negprot.spnego) {
+ if (!global_spnego_negotiated) {
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
"at SPNEGO session setup when it was not "
"negotiated.\n"));
@@ -1460,7 +1429,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
smb_bufsize = SVAL(req->vwv+2, 0);
- if (get_Protocol() < PROTOCOL_NT1) {
+ if (Protocol < PROTOCOL_NT1) {
uint16 passlen1 = SVAL(req->vwv+7, 0);
/* Never do NT status codes with protocols before NT1 as we
@@ -1654,7 +1623,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
domain, user, get_remote_machine_name()));
if (*user) {
- if (sconn->smb1.negprot.spnego) {
+ if (global_spnego_negotiated) {
/* This has to be here, because this is a perfectly
* valid behaviour for guest logons :-( */
@@ -1683,9 +1652,9 @@ void reply_sesssetup_and_X(struct smb_request *req)
data_blob_free(&nt_resp);
data_blob_clear_free(&plaintext_password);
- map_username(sconn, sub_user);
- add_session_user(sconn, sub_user);
- add_session_workgroup(sconn, domain);
+ map_username(sub_user);
+ add_session_user(sub_user);
+ add_session_workgroup(domain);
/* Then force it to null for the benfit of the code below */
user = "";
}
@@ -1695,9 +1664,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
nt_status = check_guest_password(&server_info);
} else if (doencrypt) {
- struct auth_context *negprot_auth_context = NULL;
- negprot_auth_context = sconn->smb1.negprot.auth_context;
- if (!negprot_auth_context) {
+ if (!negprot_global_auth_context) {
DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
"session setup without negprot denied!\n"));
reply_nterror(req, nt_status_squash(
@@ -1709,8 +1676,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
domain,
lm_resp, nt_resp);
if (NT_STATUS_IS_OK(nt_status)) {
- nt_status = negprot_auth_context->check_ntlm_password(
- negprot_auth_context,
+ nt_status = negprot_global_auth_context->check_ntlm_password(
+ negprot_global_auth_context,
user_info,
&server_info);
}
@@ -1787,7 +1754,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
/* it's ok - setup a reply */
reply_outbuf(req, 3, 0);
- if (get_Protocol() >= PROTOCOL_NT1) {
+ if (Protocol >= PROTOCOL_NT1) {
push_signature(&req->outbuf);
/* perhaps grab OS version here?? */
}
@@ -1804,7 +1771,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
TALLOC_FREE(server_info);
} else {
/* Ignore the initial vuid. */
- sess_vuid = register_initial_vuid(sconn);
+ sess_vuid = register_initial_vuid();
if (sess_vuid == UID_FIELD_INVALID) {
data_blob_free(&nt_resp);
data_blob_free(&lm_resp);
@@ -1814,7 +1781,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
return;
}
/* register_existing_vuid keeps the server info */
- sess_vuid = register_existing_vuid(sconn, sess_vuid,
+ sess_vuid = register_existing_vuid(sess_vuid,
server_info,
nt_resp.data ? nt_resp : lm_resp,
sub_user);
@@ -1829,6 +1796,8 @@ void reply_sesssetup_and_X(struct smb_request *req)
/* current_user_info is changed on new vuid */
reload_services( True );
+
+ sessionsetup_start_signing_engine(server_info, req->inbuf);
}
data_blob_free(&nt_resp);
@@ -1838,11 +1807,10 @@ void reply_sesssetup_and_X(struct smb_request *req)
SSVAL(req->inbuf,smb_uid,sess_vuid);
req->vuid = sess_vuid;
- if (!sconn->smb1.sessions.done_sesssetup) {
- sconn->smb1.sessions.max_send =
- MIN(sconn->smb1.sessions.max_send,smb_bufsize);
- }
- sconn->smb1.sessions.done_sesssetup = true;
+ if (!done_sesssetup)
+ max_send = MIN(max_send,smb_bufsize);
+
+ done_sesssetup = True;
END_PROFILE(SMBsesssetupX);
chain_reply(req);
diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c
index a300d6f1de..c72251b5a7 100644
--- a/source3/smbd/share_access.c
+++ b/source3/smbd/share_access.c
@@ -18,7 +18,6 @@
*/
#include "includes.h"
-#include "smbd/globals.h"
/*
* No prefix means direct username
@@ -73,7 +72,6 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
const char *prefix;
DOM_SID sid;
enum lsa_SidType type;
- struct smbd_server_connection *sconn = smbd_server_conn;
if (username != NULL) {
name = talloc_sub_basic(mem_ctx, username, domain, name);
@@ -130,10 +128,8 @@ static bool token_contains_name(TALLOC_CTX *mem_ctx,
continue;
}
if (*prefix == '&') {
- if (username) {
- if (user_in_netgroup(sconn, username, name)) {
- return True;
- }
+ if (user_in_netgroup(username, name)) {
+ return True;
}
continue;
}
diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c
deleted file mode 100644
index 9b5e3452f9..0000000000
--- a/source3/smbd/signing.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB Signing Code
- Copyright (C) Jeremy Allison 2003.
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-
-
-/***********************************************************
- Called to validate an incoming packet from the client.
-************************************************************/
-
-bool srv_check_sign_mac(struct smbd_server_connection *conn,
- const char *inbuf, uint32_t *seqnum)
-{
- /* Check if it's a non-session message. */
- if(CVAL(inbuf,0)) {
- return true;
- }
-
- *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
- return smb_signing_check_pdu(conn->smb1.signing_state,
- (const uint8_t *)inbuf,
- *seqnum);
-}
-
-/***********************************************************
- Called to sign an outgoing packet to the client.
-************************************************************/
-
-void srv_calculate_sign_mac(struct smbd_server_connection *conn,
- char *outbuf, uint32_t seqnum)
-{
- /* Check if it's a non-session message. */
- if(CVAL(outbuf,0)) {
- return;
- }
-
- smb_signing_sign_pdu(conn->smb1.signing_state, (uint8_t *)outbuf, seqnum);
-}
-
-
-/***********************************************************
- Called to indicate a oneway request
-************************************************************/
-void srv_cancel_sign_response(struct smbd_server_connection *conn)
-{
- smb_signing_cancel_reply(conn->smb1.signing_state, true);
-}
-
-/***********************************************************
- Called by server negprot when signing has been negotiated.
-************************************************************/
-
-bool srv_init_signing(struct smbd_server_connection *conn)
-{
- bool allowed = true;
- bool mandatory = false;
-
- switch (lp_server_signing()) {
- case Required:
- mandatory = true;
- break;
- case Auto:
- break;
- case True:
- break;
- case False:
- allowed = false;
- break;
- }
-
- conn->smb1.signing_state = smb_signing_init(smbd_event_context(),
- allowed, mandatory);
- if (!conn->smb1.signing_state) {
- return false;
- }
-
- return true;
-}
-
-void srv_set_signing_negotiated(struct smbd_server_connection *conn)
-{
- smb_signing_set_negotiated(conn->smb1.signing_state);
-}
-
-/***********************************************************
- Returns whether signing is active. We can't use sendfile or raw
- reads/writes if it is.
-************************************************************/
-
-bool srv_is_signing_active(struct smbd_server_connection *conn)
-{
- return smb_signing_is_active(conn->smb1.signing_state);
-}
-
-
-/***********************************************************
- Returns whether signing is negotiated. We can't use it unless it was
- in the negprot.
-************************************************************/
-
-bool srv_is_signing_negotiated(struct smbd_server_connection *conn)
-{
- return smb_signing_is_negotiated(conn->smb1.signing_state);
-}
-
-/***********************************************************
- Turn on signing from this packet onwards.
-************************************************************/
-
-void srv_set_signing(struct smbd_server_connection *conn,
- const DATA_BLOB user_session_key,
- const DATA_BLOB response)
-{
- bool negotiated;
- bool mandatory;
-
- if (!user_session_key.length)
- return;
-
- negotiated = smb_signing_is_negotiated(conn->smb1.signing_state);
- mandatory = smb_signing_is_mandatory(conn->smb1.signing_state);
-
- if (!negotiated && !mandatory) {
- DEBUG(5,("srv_set_signing: signing negotiated = %u, "
- "mandatory_signing = %u. Not allowing smb signing.\n",
- negotiated, mandatory));
- return;
- }
-
- if (!smb_signing_activate(conn->smb1.signing_state,
- user_session_key, response)) {
- return;
- }
-
- DEBUG(3,("srv_set_signing: turning on SMB signing: "
- "signing negotiated = %u, mandatory_signing = %u.\n",
- negotiated, mandatory));
-}
-
diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c
deleted file mode 100644
index 879d59f89e..0000000000
--- a/source3/smbd/smb2_break.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_oplock_break_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_oplock_level,
- uint64_t in_file_id_volatile);
-static NTSTATUS smbd_smb2_oplock_break_recv(struct tevent_req *req,
- uint8_t *out_oplock_level);
-
-static void smbd_smb2_request_oplock_break_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x18;
- size_t body_size;
- uint8_t in_oplock_level;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_oplock_level = CVAL(inbody, 0x02);
- /* 0x03 1 bytes reserved */
- /* 0x04 4 bytes reserved */
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_oplock_break_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_oplock_level,
- in_file_id_volatile);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_oplock_break_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_oplock_break_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- const uint8_t *inbody;
- int i = req->current_idx;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint8_t out_oplock_level = 0;
- DATA_BLOB outbody;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_oplock_break_recv(subreq, &out_oplock_level);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x18);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x18); /* struct size */
- SCVAL(outbody.data, 0x02,
- out_oplock_level); /* oplock level */
- SCVAL(outbody.data, 0x03, 0); /* reserved */
- SIVAL(outbody.data, 0x04, 0); /* reserved */
- SBVAL(outbody.data, 0x08,
- in_file_id_persistent); /* file id (persistent) */
- SBVAL(outbody.data, 0x10,
- in_file_id_volatile); /* file id (volatile) */
-
- error = smbd_smb2_request_done(req, outbody, NULL);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_oplock_break_state {
- struct smbd_smb2_request *smb2req;
- uint8_t out_oplock_level;
-};
-
-static struct tevent_req *smbd_smb2_oplock_break_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_oplock_level,
- uint64_t in_file_id_volatile)
-{
- struct tevent_req *req;
- struct smbd_smb2_oplock_break_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_oplock_break_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->out_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
-
- DEBUG(10,("smbd_smb2_oplock_break_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_oplock_break_recv(struct tevent_req *req,
- uint8_t *out_oplock_level)
-{
- NTSTATUS status;
- struct smbd_smb2_oplock_break_state *state =
- tevent_req_data(req,
- struct smbd_smb2_oplock_break_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_oplock_level = state->out_oplock_level;
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
deleted file mode 100644
index b28fb72979..0000000000
--- a/source3/smbd/smb2_close.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
- uint16_t in_flags,
- uint64_t in_file_id_volatile);
-
-NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- size_t expected_body_size = 0x18;
- size_t body_size;
- uint16_t in_flags;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- NTSTATUS status;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_flags = SVAL(inbody, 0x02);
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- status = smbd_smb2_close(req,
- in_flags,
- in_file_id_volatile);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x3C); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* flags */
- SIVAL(outbody.data, 0x04, 0); /* reserved */
- SBVAL(outbody.data, 0x08, 0); /* creation time */
- SBVAL(outbody.data, 0x10, 0); /* last access time */
- SBVAL(outbody.data, 0x18, 0); /* last write time */
- SBVAL(outbody.data, 0x20, 0); /* change time */
- SBVAL(outbody.data, 0x28, 0); /* allocation size */
- SBVAL(outbody.data, 0x30, 0); /* end of size */
- SIVAL(outbody.data, 0x38, 0); /* file attributes */
-
- return smbd_smb2_request_done(req, outbody, NULL);
-}
-
-static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
- uint16_t in_flags,
- uint64_t in_file_id_volatile)
-{
- NTSTATUS status;
- struct smb_request *smbreq;
- connection_struct *conn = req->tcon->compat_conn;
- files_struct *fsp;
-
- DEBUG(10,("smbd_smb2_close: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(req);
- if (smbreq == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- return NT_STATUS_FILE_CLOSED;
- }
- if (conn != fsp->conn) {
- return NT_STATUS_FILE_CLOSED;
- }
- if (req->session->vuid != fsp->vuid) {
- return NT_STATUS_FILE_CLOSED;
- }
-
- status = close_file(smbreq, fsp, NORMAL_CLOSE);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
- return status;
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
deleted file mode 100644
index 3cf8b185b0..0000000000
--- a/source3/smbd/smb2_create.c
+++ /dev/null
@@ -1,754 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_oplock_level,
- uint32_t in_impersonation_level,
- uint32_t in_desired_access,
- uint32_t in_file_attributes,
- uint32_t in_share_access,
- uint32_t in_create_disposition,
- uint32_t in_create_options,
- const char *in_name,
- struct smb2_create_blobs in_context_blobs);
-static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- uint8_t *out_oplock_level,
- uint32_t *out_create_action,
- NTTIME *out_creation_time,
- NTTIME *out_last_access_time,
- NTTIME *out_last_write_time,
- NTTIME *out_change_time,
- uint64_t *out_allocation_size,
- uint64_t *out_end_of_file,
- uint32_t *out_file_attributes,
- uint64_t *out_file_id_volatile,
- struct smb2_create_blobs *out_context_blobs);
-
-static void smbd_smb2_request_create_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x39;
- size_t body_size;
- uint8_t in_oplock_level;
- uint32_t in_impersonation_level;
- uint32_t in_desired_access;
- uint32_t in_file_attributes;
- uint32_t in_share_access;
- uint32_t in_create_disposition;
- uint32_t in_create_options;
- uint16_t in_name_offset;
- uint16_t in_name_length;
- DATA_BLOB in_name_buffer;
- char *in_name_string;
- size_t in_name_string_size;
- uint32_t name_offset = 0;
- uint32_t name_available_length = 0;
- uint32_t in_context_offset;
- uint32_t in_context_length;
- DATA_BLOB in_context_buffer;
- struct smb2_create_blobs in_context_blobs;
- uint32_t context_offset = 0;
- uint32_t context_available_length = 0;
- uint32_t dyn_offset;
- NTSTATUS status;
- bool ok;
- struct tevent_req *subreq;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_oplock_level = CVAL(inbody, 0x03);
- in_impersonation_level = IVAL(inbody, 0x04);
- in_desired_access = IVAL(inbody, 0x18);
- in_file_attributes = IVAL(inbody, 0x1C);
- in_share_access = IVAL(inbody, 0x20);
- in_create_disposition = IVAL(inbody, 0x24);
- in_create_options = IVAL(inbody, 0x28);
- in_name_offset = SVAL(inbody, 0x2C);
- in_name_length = SVAL(inbody, 0x2E);
- in_context_offset = IVAL(inbody, 0x30);
- in_context_length = IVAL(inbody, 0x34);
-
- /*
- * First check if the dynamic name and context buffers
- * are correctly specified.
- *
- * Note: That we don't check if the name and context buffers
- * overlap
- */
-
- dyn_offset = SMB2_HDR_BODY + (body_size & 0xFFFFFFFE);
-
- if (in_name_offset == 0 && in_name_length == 0) {
- /* This is ok */
- name_offset = 0;
- } else if (in_name_offset < dyn_offset) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- } else {
- name_offset = in_name_offset - dyn_offset;
- }
-
- if (name_offset > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- name_available_length = req->in.vector[i+2].iov_len - name_offset;
-
- if (in_name_length > name_available_length) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_name_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base +
- name_offset;
- in_name_buffer.length = in_name_length;
-
- if (in_context_offset == 0 && in_context_length == 0) {
- /* This is ok */
- context_offset = 0;
- } else if (in_context_offset < dyn_offset) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- } else {
- context_offset = in_context_offset - dyn_offset;
- }
-
- if (context_offset > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- context_available_length = req->in.vector[i+2].iov_len - context_offset;
-
- if (in_context_length > context_available_length) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_context_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base +
- context_offset;
- in_context_buffer.length = in_context_length;
-
- /*
- * Now interpret the name and context buffers
- */
-
- ok = convert_string_talloc(req, CH_UTF16, CH_UNIX,
- in_name_buffer.data,
- in_name_buffer.length,
- &in_name_string,
- &in_name_string_size, false);
- if (!ok) {
- return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER);
- }
-
- ZERO_STRUCT(in_context_blobs);
- status = smb2_create_blob_parse(req, in_context_buffer, &in_context_blobs);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
-
- subreq = smbd_smb2_create_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_oplock_level,
- in_impersonation_level,
- in_desired_access,
- in_file_attributes,
- in_share_access,
- in_create_disposition,
- in_create_options,
- in_name_string,
- in_context_blobs);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_create_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_create_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint8_t out_oplock_level = 0;
- uint32_t out_create_action = 0;
- NTTIME out_creation_time = 0;
- NTTIME out_last_access_time = 0;
- NTTIME out_last_write_time = 0;
- NTTIME out_change_time = 0;
- uint64_t out_allocation_size = 0;
- uint64_t out_end_of_file = 0;
- uint32_t out_file_attributes = 0;
- uint64_t out_file_id_volatile = 0;
- struct smb2_create_blobs out_context_blobs;
- DATA_BLOB out_context_buffer;
- uint16_t out_context_buffer_offset = 0;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_create_recv(subreq,
- req,
- &out_oplock_level,
- &out_create_action,
- &out_creation_time,
- &out_last_access_time,
- &out_last_write_time,
- &out_change_time,
- &out_allocation_size,
- &out_end_of_file,
- &out_file_attributes,
- &out_file_id_volatile,
- &out_context_blobs);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- status = smb2_create_blob_push(req, &out_context_buffer, out_context_blobs);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- if (out_context_buffer.length > 0) {
- out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
- }
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x58);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x58 + 1); /* struct size */
- SCVAL(outbody.data, 0x02,
- out_oplock_level); /* oplock level */
- SCVAL(outbody.data, 0x03, 0); /* reserved */
- SIVAL(outbody.data, 0x04,
- out_create_action); /* create action */
- SBVAL(outbody.data, 0x08,
- out_creation_time); /* creation time */
- SBVAL(outbody.data, 0x10,
- out_last_access_time); /* last access time */
- SBVAL(outbody.data, 0x18,
- out_last_write_time); /* last write time */
- SBVAL(outbody.data, 0x20,
- out_change_time); /* change time */
- SBVAL(outbody.data, 0x28,
- out_allocation_size); /* allocation size */
- SBVAL(outbody.data, 0x30,
- out_end_of_file); /* end of file */
- SIVAL(outbody.data, 0x38,
- out_file_attributes); /* file attributes */
- SIVAL(outbody.data, 0x3C, 0); /* reserved */
- SBVAL(outbody.data, 0x40, 0); /* file id (persistent) */
- SBVAL(outbody.data, 0x48,
- out_file_id_volatile); /* file id (volatile) */
- SIVAL(outbody.data, 0x50,
- out_context_buffer_offset); /* create contexts offset */
- SIVAL(outbody.data, 0x54,
- out_context_buffer.length); /* create contexts length */
-
- outdyn = out_context_buffer;
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_create_state {
- struct smbd_smb2_request *smb2req;
- uint8_t out_oplock_level;
- uint32_t out_create_action;
- NTTIME out_creation_time;
- NTTIME out_last_access_time;
- NTTIME out_last_write_time;
- NTTIME out_change_time;
- uint64_t out_allocation_size;
- uint64_t out_end_of_file;
- uint32_t out_file_attributes;
- uint64_t out_file_id_volatile;
- struct smb2_create_blobs out_context_blobs;
-};
-
-static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_oplock_level,
- uint32_t in_impersonation_level,
- uint32_t in_desired_access,
- uint32_t in_file_attributes,
- uint32_t in_share_access,
- uint32_t in_create_disposition,
- uint32_t in_create_options,
- const char *in_name,
- struct smb2_create_blobs in_context_blobs)
-{
- struct tevent_req *req;
- struct smbd_smb2_create_state *state;
- NTSTATUS status;
- struct smb_request *smbreq;
- files_struct *result;
- int info;
- struct timespec write_time_ts;
- struct smb2_create_blobs out_context_blobs;
-
- ZERO_STRUCT(out_context_blobs);
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_create_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
-
- DEBUG(10,("smbd_smb2_create: name[%s]\n",
- in_name));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(smbreq->conn)) {
- const char *pipe_name = in_name;
-
- if (!lp_nt_pipe_support()) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
-
- /* Strip \\ off the name. */
- if (pipe_name[0] == '\\') {
- pipe_name++;
- }
-
- status = open_np_file(smbreq, pipe_name, &result);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- info = FILE_WAS_OPENED;
- } else if (CAN_PRINT(smbreq->conn)) {
- status = file_new(smbreq, smbreq->conn, &result);
- if(!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- status = print_fsp_open(smbreq,
- smbreq->conn,
- in_name,
- smbreq->vuid,
- result);
- if (!NT_STATUS_IS_OK(status)) {
- file_free(smbreq, result);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- info = FILE_WAS_CREATED;
- } else {
- char *fname;
- struct smb_filename *smb_fname = NULL;
- struct smb2_create_blob *exta = NULL;
- struct ea_list *ea_list = NULL;
- struct smb2_create_blob *mxac = NULL;
- NTTIME max_access_time = 0;
- struct smb2_create_blob *secd = NULL;
- struct security_descriptor *sec_desc = NULL;
- struct smb2_create_blob *dhnq = NULL;
- struct smb2_create_blob *dhnc = NULL;
- struct smb2_create_blob *alsi = NULL;
- uint64_t allocation_size = 0;
- struct smb2_create_blob *twrp = NULL;
- struct smb2_create_blob *qfid = NULL;
-
- exta = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_EXTA);
- mxac = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_MXAC);
- secd = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_SECD);
- dhnq = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_DHNQ);
- dhnc = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_DHNC);
- alsi = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_ALSI);
- twrp = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_TWRP);
- qfid = smb2_create_blob_find(&in_context_blobs,
- SMB2_CREATE_TAG_QFID);
-
- fname = talloc_strdup(state, in_name);
- if (tevent_req_nomem(fname, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (exta) {
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- ea_list = read_nttrans_ea_list(mem_ctx,
- (const char *)exta->data.data, exta->data.length);
- if (!ea_list) {
- DEBUG(10,("smbd_smb2_create_send: read_ea_name_list failed.\n"));
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- }
-
- if (mxac) {
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- if (mxac->data.length == 0) {
- max_access_time = 0;
- } else if (mxac->data.length == 8) {
- max_access_time = BVAL(mxac->data.data, 0);
- } else {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- }
-
- if (secd) {
- enum ndr_err_code ndr_err;
-
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- sec_desc = talloc_zero(state, struct security_descriptor);
- if (tevent_req_nomem(sec_desc, req)) {
- return tevent_req_post(req, ev);
- }
-
- ndr_err = ndr_pull_struct_blob(&secd->data,
- sec_desc, NULL, sec_desc,
- (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- DEBUG(2,("ndr_pull_security_descriptor failed: %s\n",
- ndr_errstr(ndr_err)));
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- }
-
- if (dhnq) {
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- if (dhnq->data.length != 16) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- /*
- * we don't support durable handles yet
- * and have to ignore this
- */
- }
-
- if (dhnc) {
- if (dhnc->data.length != 16) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- /* we don't support durable handles yet */
- tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return tevent_req_post(req, ev);
- }
-
- if (alsi) {
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- if (alsi->data.length != 8) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- allocation_size = BVAL(alsi->data.data, 0);
- }
-
- if (twrp) {
- NTTIME nttime;
- time_t t;
- struct tm *tm;
-
- if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- if (twrp->data.length != 8) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- nttime = BVAL(twrp->data.data, 0);
- t = nt_time_to_unix(nttime);
- tm = gmtime(&t);
-
- TALLOC_FREE(fname);
- fname = talloc_asprintf(state,
- "@GMT-%04u.%02u.%02u-%02u.%02u.%02u\\%s",
- tm->tm_year + 1900,
- tm->tm_mon + 1,
- tm->tm_mday,
- tm->tm_hour,
- tm->tm_min,
- tm->tm_sec,
- in_name);
- if (tevent_req_nomem(fname, req)) {
- return tevent_req_post(req, ev);
- }
- }
-
- if (qfid) {
- if (qfid->data.length != 0) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- }
-
- /* these are ignored for SMB2 */
- in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
- in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
-
- /* convert '\\' into '/' */
- status = check_path_syntax(fname);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- status = filename_convert(req,
- smbreq->conn,
- smbreq->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- status = SMB_VFS_CREATE_FILE(smbreq->conn,
- smbreq,
- 0, /* root_dir_fid */
- smb_fname,
- in_desired_access,
- in_share_access,
- in_create_disposition,
- in_create_options,
- in_file_attributes,
- 0, /* oplock_request */
- allocation_size,
- sec_desc,
- ea_list,
- &result,
- &info);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- if (mxac) {
- NTTIME last_write_time;
-
- unix_timespec_to_nt_time(&last_write_time,
- result->fsp_name->st.st_ex_mtime);
- if (last_write_time != max_access_time) {
- uint8_t p[8];
- uint32_t max_access_granted;
- DATA_BLOB blob = data_blob_const(p, sizeof(p));
-
- status = smbd_check_open_rights(smbreq->conn,
- result->fsp_name,
- SEC_FLAG_MAXIMUM_ALLOWED,
- &max_access_granted);
-
- SIVAL(p, 0, NT_STATUS_V(status));
- SIVAL(p, 4, max_access_granted);
-
- status = smb2_create_blob_add(state,
- &out_context_blobs,
- SMB2_CREATE_TAG_MXAC,
- blob);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
- }
-
- if (qfid) {
- uint8_t p[32];
- DATA_BLOB blob = data_blob_const(p, sizeof(p));
-
- ZERO_STRUCT(p);
-
- /* TODO: maybe use result->file_id */
- SIVAL(p, 0, result->fsp_name->st.st_ex_ino);/* FileIndexLow */
- SIVAL(p, 4, result->fsp_name->st.st_ex_dev);/* FileIndexHigh */
-
- status = smb2_create_blob_add(state, &out_context_blobs,
- SMB2_CREATE_TAG_QFID,
- blob);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
- }
-
- smb2req->compat_chain_fsp = smbreq->chain_fsp;
-
- state->out_oplock_level = 0;
- if ((in_create_disposition == FILE_SUPERSEDE)
- && (info == FILE_WAS_OVERWRITTEN)) {
- state->out_create_action = FILE_WAS_SUPERSEDED;
- } else {
- state->out_create_action = info;
- }
- state->out_file_attributes = dos_mode(result->conn,
- result->fsp_name);
- /* Deal with other possible opens having a modified
- write time. JRA. */
- ZERO_STRUCT(write_time_ts);
- get_file_infos(result->file_id, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
- update_stat_ex_mtime(&result->fsp_name->st, write_time_ts);
- }
-
- unix_timespec_to_nt_time(&state->out_creation_time,
- get_create_timespec(smbreq->conn, result,
- result->fsp_name));
- unix_timespec_to_nt_time(&state->out_last_access_time,
- result->fsp_name->st.st_ex_atime);
- unix_timespec_to_nt_time(&state->out_last_write_time,
- result->fsp_name->st.st_ex_mtime);
- unix_timespec_to_nt_time(&state->out_change_time,
- get_change_timespec(smbreq->conn, result,
- result->fsp_name));
- state->out_allocation_size =
- result->fsp_name->st.st_ex_blksize *
- result->fsp_name->st.st_ex_blocks;
- state->out_end_of_file = result->fsp_name->st.st_ex_size;
- if (state->out_file_attributes == 0) {
- state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
- }
- state->out_file_id_volatile = result->fnum;
- state->out_context_blobs = out_context_blobs;
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_create_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- uint8_t *out_oplock_level,
- uint32_t *out_create_action,
- NTTIME *out_creation_time,
- NTTIME *out_last_access_time,
- NTTIME *out_last_write_time,
- NTTIME *out_change_time,
- uint64_t *out_allocation_size,
- uint64_t *out_end_of_file,
- uint32_t *out_file_attributes,
- uint64_t *out_file_id_volatile,
- struct smb2_create_blobs *out_context_blobs)
-{
- NTSTATUS status;
- struct smbd_smb2_create_state *state = tevent_req_data(req,
- struct smbd_smb2_create_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_oplock_level = state->out_oplock_level;
- *out_create_action = state->out_create_action;
- *out_creation_time = state->out_creation_time;
- *out_last_access_time = state->out_last_access_time;
- *out_last_write_time = state->out_last_write_time;
- *out_change_time = state->out_change_time;
- *out_allocation_size = state->out_allocation_size;
- *out_end_of_file = state->out_end_of_file;
- *out_file_attributes = state->out_file_attributes;
- *out_file_id_volatile = state->out_file_id_volatile;
- *out_context_blobs = state->out_context_blobs;
-
- talloc_steal(mem_ctx, state->out_context_blobs.blobs);
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
deleted file mode 100644
index 546aed8db3..0000000000
--- a/source3/smbd/smb2_find.c
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_file_info_class,
- uint8_t in_flags,
- uint32_t in_file_index,
- uint64_t in_file_id_volatile,
- uint32_t in_output_buffer_length,
- const char *in_file_name);
-static NTSTATUS smbd_smb2_find_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer);
-
-static void smbd_smb2_request_find_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_find(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x21;
- size_t body_size;
- uint8_t in_file_info_class;
- uint8_t in_flags;
- uint32_t in_file_index;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint16_t in_file_name_offset;
- uint16_t in_file_name_length;
- DATA_BLOB in_file_name_buffer;
- char *in_file_name_string;
- size_t in_file_name_string_size;
- uint32_t in_output_buffer_length;
- struct tevent_req *subreq;
- bool ok;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_file_info_class = CVAL(inbody, 0x02);
- in_flags = CVAL(inbody, 0x03);
- in_file_index = IVAL(inbody, 0x04);
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
- in_file_name_offset = SVAL(inbody, 0x18);
- in_file_name_length = SVAL(inbody, 0x1A);
- in_output_buffer_length = IVAL(inbody, 0x1C);
-
- if (in_file_name_offset == 0 && in_file_name_length == 0) {
- /* This is ok */
- } else if (in_file_name_offset !=
- (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_file_name_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_file_name_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_file_name_buffer.length = in_file_name_length;
-
- ok = convert_string_talloc(req, CH_UTF16, CH_UNIX,
- in_file_name_buffer.data,
- in_file_name_buffer.length,
- &in_file_name_string,
- &in_file_name_string_size, false);
- if (!ok) {
- return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER);
- }
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_find_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_file_info_class,
- in_flags,
- in_file_index,
- in_file_id_volatile,
- in_output_buffer_length,
- in_file_name_string);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_find_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_find_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint16_t out_output_buffer_offset;
- DATA_BLOB out_output_buffer = data_blob_null;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_find_recv(subreq,
- req,
- &out_output_buffer);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x08);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
- SSVAL(outbody.data, 0x02,
- out_output_buffer_offset); /* output buffer offset */
- SIVAL(outbody.data, 0x04,
- out_output_buffer.length); /* output buffer length */
-
- outdyn = out_output_buffer;
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_find_state {
- struct smbd_smb2_request *smb2req;
- DATA_BLOB out_output_buffer;
-};
-
-static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_file_info_class,
- uint8_t in_flags,
- uint32_t in_file_index,
- uint64_t in_file_id_volatile,
- uint32_t in_output_buffer_length,
- const char *in_file_name)
-{
- struct tevent_req *req;
- struct smbd_smb2_find_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
- NTSTATUS status;
- NTSTATUS empty_status;
- uint32_t info_level;
- uint32_t max_count;
- char *pdata;
- char *base_data;
- char *end_data;
- int last_entry_off = 0;
- uint64_t off = 0;
- uint32_t num = 0;
- uint32_t dirtype = aHIDDEN | aSYSTEM | aDIR;
- const char *directory;
- bool dont_descend = false;
- bool ask_sharemode = true;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_find_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->out_output_buffer = data_blob_null;
-
- DEBUG(10,("smbd_smb2_find_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (!fsp->is_directory) {
- tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return tevent_req_post(req, ev);
- }
-
- directory = fsp->fsp_name->base_name;
-
- if (strcmp(in_file_name, "") == 0) {
- tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
- return tevent_req_post(req, ev);
- }
- if (strcmp(in_file_name, "\\") == 0) {
- tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
- return tevent_req_post(req, ev);
- }
- if (strcmp(in_file_name, "/") == 0) {
- tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
- return tevent_req_post(req, ev);
- }
-
- if (in_output_buffer_length > 0x10000) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- switch (in_file_info_class) {
- case SMB2_FIND_DIRECTORY_INFO:
- info_level = SMB_FIND_FILE_DIRECTORY_INFO;
- break;
-
- case SMB2_FIND_FULL_DIRECTORY_INFO:
- info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO;
- break;
-
- case SMB2_FIND_BOTH_DIRECTORY_INFO:
- info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
- break;
-
- case SMB2_FIND_NAME_INFO:
- info_level = SMB_FIND_FILE_NAMES_INFO;
- break;
-
- case SMB2_FIND_ID_BOTH_DIRECTORY_INFO:
- info_level = SMB_FIND_ID_BOTH_DIRECTORY_INFO;
- break;
-
- case SMB2_FIND_ID_FULL_DIRECTORY_INFO:
- info_level = SMB_FIND_ID_FULL_DIRECTORY_INFO;
- break;
-
- default:
- tevent_req_nterror(req, NT_STATUS_INVALID_INFO_CLASS);
- return tevent_req_post(req, ev);
- }
-
- if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
- if (fsp->dptr) {
- dptr_CloseDir(fsp->dptr);
- fsp->dptr = NULL;
- }
- }
-
- if (fsp->dptr == NULL) {
- bool wcard_has_wild;
-
- if (!(fsp->access_mask & SEC_DIR_LIST)) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
-
- wcard_has_wild = ms_has_wild(in_file_name);
-
- status = dptr_create(conn,
- directory,
- false, /* old_handle */
- false, /* expect_close */
- 0, /* spid */
- in_file_name, /* wcard */
- wcard_has_wild,
- dirtype,
- &fsp->dptr);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- empty_status = NT_STATUS_NO_SUCH_FILE;
- } else {
- empty_status = STATUS_NO_MORE_FILES;
- }
-
- if (in_flags & SMB2_CONTINUE_FLAG_RESTART) {
- dptr_SeekDir(fsp->dptr, 0);
- }
-
- if (in_flags & SMB2_CONTINUE_FLAG_SINGLE) {
- max_count = 1;
- } else {
- max_count = UINT16_MAX;
- }
-
-#define DIR_ENTRY_SAFETY_MARGIN 4096
-
- state->out_output_buffer = data_blob_talloc(state, NULL,
- in_output_buffer_length + DIR_ENTRY_SAFETY_MARGIN);
- if (tevent_req_nomem(state->out_output_buffer.data, req)) {
- return tevent_req_post(req, ev);
- }
-
- state->out_output_buffer.length = 0;
- pdata = (char *)state->out_output_buffer.data;
- base_data = pdata;
- end_data = pdata + in_output_buffer_length;
- last_entry_off = 0;
- off = 0;
- num = 0;
-
- DEBUG(8,("smbd_smb2_find_send: dirpath=<%s> dontdescend=<%s>\n",
- directory, lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive)) {
- dont_descend = true;
- }
-
- ask_sharemode = lp_parm_bool(SNUM(conn),
- "smbd", "search ask sharemode",
- true);
-
- while (true) {
- bool ok;
- bool got_exact_match = false;
- bool out_of_space = false;
- int space_remaining = in_output_buffer_length - off;
-
- ok = smbd_dirptr_lanman2_entry(state,
- conn,
- fsp->dptr,
- smbreq->flags2,
- in_file_name,
- dirtype,
- info_level,
- false, /* requires_resume_key */
- dont_descend,
- ask_sharemode,
- 8, /* align to 8 bytes */
- false, /* no padding */
- &pdata,
- base_data,
- end_data,
- space_remaining,
- &out_of_space,
- &got_exact_match,
- &last_entry_off,
- NULL);
-
- off = PTR_DIFF(pdata, base_data);
-
- if (!ok) {
- if (num > 0) {
- SIVAL(state->out_output_buffer.data, last_entry_off, 0);
- tevent_req_done(req);
- return tevent_req_post(req, ev);
- } else if (out_of_space) {
- tevent_req_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
- return tevent_req_post(req, ev);
- } else {
- tevent_req_nterror(req, empty_status);
- return tevent_req_post(req, ev);
- }
- }
-
- num++;
- state->out_output_buffer.length = off;
-
- if (num < max_count) {
- continue;
- }
-
- SIVAL(state->out_output_buffer.data, last_entry_off, 0);
- tevent_req_done(req);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_find_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer)
-{
- NTSTATUS status;
- struct smbd_smb2_find_state *state = tevent_req_data(req,
- struct smbd_smb2_find_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_output_buffer = state->out_output_buffer;
- talloc_steal(mem_ctx, out_output_buffer->data);
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
deleted file mode 100644
index 561e690582..0000000000
--- a/source3/smbd/smb2_flush.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint64_t in_file_id_volatile);
-static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req);
-
-static void smbd_smb2_request_flush_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x18;
- size_t body_size;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_flush_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_file_id_volatile);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_flush_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_flush_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- DATA_BLOB outbody;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_flush_recv(subreq);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x04); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
-
- error = smbd_smb2_request_done(req, outbody, NULL);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_flush_state {
- struct smbd_smb2_request *smb2req;
-};
-
-static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint64_t in_file_id_volatile)
-{
- struct tevent_req *req;
- struct smbd_smb2_flush_state *state;
- NTSTATUS status;
- struct smb_request *smbreq;
- files_struct *fsp;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_flush_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
-
- DEBUG(10,("smbd_smb2_flush: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(smbreq->conn)) {
- tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smbreq->conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (!CHECK_WRITE(fsp)) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
-
- status = sync_file(smbreq->conn, fsp, true);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5,("smbd_smb2_flush: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_flush_recv(struct tevent_req *req)
-{
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
deleted file mode 100644
index 3b50ab9cd7..0000000000
--- a/source3/smbd/smb2_getinfo.c
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_info_type,
- uint8_t in_file_info_class,
- uint32_t in_output_buffer_length,
- DATA_BLOB in_input_buffer,
- uint32_t in_additional_information,
- uint32_t in_flags,
- uint64_t in_file_id_volatile);
-static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer);
-
-static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x29;
- size_t body_size;
- uint8_t in_info_type;
- uint8_t in_file_info_class;
- uint32_t in_output_buffer_length;
- uint16_t in_input_buffer_offset;
- uint32_t in_input_buffer_length;
- DATA_BLOB in_input_buffer;
- uint32_t in_additional_information;
- uint32_t in_flags;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_info_type = CVAL(inbody, 0x02);
- in_file_info_class = CVAL(inbody, 0x03);
- in_output_buffer_length = IVAL(inbody, 0x04);
- in_input_buffer_offset = SVAL(inbody, 0x08);
- /* 0x0A 2 bytes reserved */
- in_input_buffer_length = IVAL(inbody, 0x0C);
- in_additional_information = IVAL(inbody, 0x10);
- in_flags = IVAL(inbody, 0x14);
- in_file_id_persistent = BVAL(inbody, 0x18);
- in_file_id_volatile = BVAL(inbody, 0x20);
-
- if (in_input_buffer_offset == 0 && in_input_buffer_length == 0) {
- /* This is ok */
- } else if (in_input_buffer_offset !=
- (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_input_buffer_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_input_buffer.length = in_input_buffer_length;
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_getinfo_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_info_type,
- in_file_info_class,
- in_output_buffer_length,
- in_input_buffer,
- in_additional_information,
- in_flags,
- in_file_id_volatile);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_getinfo_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint16_t out_output_buffer_offset;
- DATA_BLOB out_output_buffer = data_blob_null;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_getinfo_recv(subreq,
- req,
- &out_output_buffer);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x08);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
- SSVAL(outbody.data, 0x02,
- out_output_buffer_offset); /* output buffer offset */
- SIVAL(outbody.data, 0x04,
- out_output_buffer.length); /* output buffer length */
-
- outdyn = out_output_buffer;
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_getinfo_state {
- struct smbd_smb2_request *smb2req;
- NTSTATUS status;
- DATA_BLOB out_output_buffer;
-};
-
-static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_info_type,
- uint8_t in_file_info_class,
- uint32_t in_output_buffer_length,
- DATA_BLOB in_input_buffer,
- uint32_t in_additional_information,
- uint32_t in_flags,
- uint64_t in_file_id_volatile)
-{
- struct tevent_req *req;
- struct smbd_smb2_getinfo_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_getinfo_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->status = NT_STATUS_INTERNAL_ERROR;
- state->out_output_buffer = data_blob_null;
-
- DEBUG(10,("smbd_smb2_getinfo_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(conn)) {
- tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return tevent_req_post(req, ev);
- }
-
- switch (in_info_type) {
- case 0x01:/* SMB2_GETINFO_FILE */
- {
- uint16_t file_info_level;
- char *data = NULL;
- unsigned int data_size = 0;
- bool delete_pending = false;
- struct timespec write_time_ts;
- struct file_id fileid;
- struct ea_list *ea_list = NULL;
- int lock_data_count = 0;
- char *lock_data = NULL;
- bool ms_dfs_link = false;
- NTSTATUS status;
-
- ZERO_STRUCT(write_time_ts);
-
- switch (in_file_info_class) {
- case 0x0F:/* RAW_FILEINFO_SMB2_ALL_EAS */
- file_info_level = 0xFF00 | in_file_info_class;
- break;
-
- case 0x12:/* RAW_FILEINFO_SMB2_ALL_INFORMATION */
- file_info_level = 0xFF00 | in_file_info_class;
- break;
-
- default:
- /* the levels directly map to the passthru levels */
- file_info_level = in_file_info_class + 1000;
- break;
- }
-
- if (fsp->fake_file_handle) {
- /*
- * This is actually for the QUOTA_FAKE_FILE --metze
- */
-
- /* We know this name is ok, it's already passed the checks. */
-
- } else if (fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
- /*
- * This is actually a QFILEINFO on a directory
- * handle (returned from an NT SMB). NT5.0 seems
- * to do this call. JRA.
- */
-
- if (INFO_LEVEL_IS_UNIX(file_info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, fsp->fsp_name)) {
- DEBUG(3,("smbd_smb2_getinfo_send: "
- "SMB_VFS_LSTAT of %s failed "
- "(%s)\n", fsp_str_dbg(fsp),
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- } else if (SMB_VFS_STAT(conn, fsp->fsp_name)) {
- DEBUG(3,("smbd_smb2_getinfo_send: "
- "SMB_VFS_STAT of %s failed (%s)\n",
- fsp_str_dbg(fsp),
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- fileid = vfs_file_id_from_sbuf(conn,
- &fsp->fsp_name->st);
- get_file_infos(fileid, &delete_pending, &write_time_ts);
- } else {
- /*
- * Original code - this is an open file.
- */
-
- if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
- DEBUG(3, ("smbd_smb2_getinfo_send: "
- "fstat of fnum %d failed (%s)\n",
- fsp->fnum, strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- fileid = vfs_file_id_from_sbuf(conn,
- &fsp->fsp_name->st);
- get_file_infos(fileid, &delete_pending, &write_time_ts);
- }
-
- status = smbd_do_qfilepathinfo(conn, state,
- file_info_level,
- fsp,
- fsp->fsp_name,
- delete_pending,
- write_time_ts,
- ms_dfs_link,
- ea_list,
- lock_data_count,
- lock_data,
- STR_UNICODE,
- in_output_buffer_length,
- &data,
- &data_size);
- if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(data);
- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
- status = NT_STATUS_INVALID_INFO_CLASS;
- }
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- if (data_size > 0) {
- state->out_output_buffer = data_blob_talloc(state,
- data,
- data_size);
- SAFE_FREE(data);
- if (tevent_req_nomem(state->out_output_buffer.data, req)) {
- return tevent_req_post(req, ev);
- }
- }
- SAFE_FREE(data);
- break;
- }
-
- case 0x02:/* SMB2_GETINFO_FS */
- {
- uint16_t file_info_level;
- char *data = NULL;
- int data_size = 0;
- NTSTATUS status;
-
- /* the levels directly map to the passthru levels */
- file_info_level = in_file_info_class + 1000;
-
- status = smbd_do_qfsinfo(conn, state,
- file_info_level,
- STR_UNICODE,
- in_output_buffer_length,
- &data,
- &data_size);
- if (!NT_STATUS_IS_OK(status)) {
- SAFE_FREE(data);
- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
- status = NT_STATUS_INVALID_INFO_CLASS;
- }
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- if (data_size > 0) {
- state->out_output_buffer = data_blob_talloc(state,
- data,
- data_size);
- SAFE_FREE(data);
- if (tevent_req_nomem(state->out_output_buffer.data, req)) {
- return tevent_req_post(req, ev);
- }
- }
- SAFE_FREE(data);
- break;
- }
-
- default:
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer)
-{
- NTSTATUS status;
- struct smbd_smb2_getinfo_state *state = tevent_req_data(req,
- struct smbd_smb2_getinfo_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_output_buffer = state->out_output_buffer;
- talloc_steal(mem_ctx, out_output_buffer->data);
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_glue.c b/source3/smbd/smb2_glue.c
deleted file mode 100644
index d5a6217aa3..0000000000
--- a/source3/smbd/smb2_glue.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req)
-{
- struct smb_request *smbreq;
- const uint8_t *inhdr;
- int i = req->current_idx;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
-
- smbreq = talloc_zero(req, struct smb_request);
- if (smbreq == NULL) {
- return NULL;
- }
-
- smbreq->vuid = req->session->compat_vuser->vuid;
- smbreq->tid = req->tcon->compat_conn->cnum;
- smbreq->conn = req->tcon->compat_conn;
- smbreq->smbpid = (uint16_t)IVAL(inhdr, SMB2_HDR_PID);
- smbreq->flags2 = FLAGS2_UNICODE_STRINGS |
- FLAGS2_32_BIT_ERROR_CODES |
- FLAGS2_LONG_PATH_COMPONENTS |
- FLAGS2_IS_LONG_NAME;
- if (IVAL(inhdr, SMB2_HDR_FLAGS) & SMB2_HDR_FLAG_DFS) {
- smbreq->flags2 |= FLAGS2_DFS_PATHNAMES;
- }
- smbreq->chain_fsp = req->compat_chain_fsp;
-
- return smbreq;
-}
diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
deleted file mode 100644
index 0041e5f7d0..0000000000
--- a/source3/smbd/smb2_ioctl.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_ctl_code,
- uint64_t in_file_id_volatile,
- DATA_BLOB in_input,
- uint32_t in_max_output,
- uint32_t in_flags);
-static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output);
-
-static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x39;
- size_t body_size;
- uint32_t in_ctl_code;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint32_t in_input_offset;
- uint32_t in_input_length;
- DATA_BLOB in_input_buffer;
- uint32_t in_max_output_length;
- uint32_t in_flags;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_ctl_code = IVAL(inbody, 0x04);
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
- in_input_offset = IVAL(inbody, 0x18);
- in_input_length = IVAL(inbody, 0x1C);
- in_max_output_length = IVAL(inbody, 0x2C);
- in_flags = IVAL(inbody, 0x30);
-
- if (in_input_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_input_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_input_buffer.length = in_input_length;
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent == UINT64_MAX &&
- in_file_id_volatile == UINT64_MAX) {
- /* without a handle */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_ioctl_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_ctl_code,
- in_file_id_volatile,
- in_input_buffer,
- in_max_output_length,
- in_flags);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_ioctl_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_ioctl_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- const uint8_t *inbody;
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint32_t in_ctl_code;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint32_t out_input_offset;
- uint32_t out_output_offset;
- DATA_BLOB out_output_buffer = data_blob_null;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_ioctl_recv(subreq, req, &out_output_buffer);
- TALLOC_FREE(subreq);
- if (NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
- /* also ok */
- } else if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- out_input_offset = SMB2_HDR_BODY + 0x30;
- out_output_offset = SMB2_HDR_BODY + 0x30;
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- in_ctl_code = IVAL(inbody, 0x04);
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x30);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x30 + 1); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
- SIVAL(outbody.data, 0x04,
- in_ctl_code); /* ctl code */
- SBVAL(outbody.data, 0x08,
- in_file_id_persistent); /* file id (persistent) */
- SBVAL(outbody.data, 0x10,
- in_file_id_volatile); /* file id (volatile) */
- SIVAL(outbody.data, 0x18,
- out_input_offset); /* input offset */
- SIVAL(outbody.data, 0x1C, 0); /* input count */
- SIVAL(outbody.data, 0x20,
- out_output_offset); /* output offset */
- SIVAL(outbody.data, 0x24,
- out_output_buffer.length); /* output count */
- SIVAL(outbody.data, 0x28, 0); /* flags */
- SIVAL(outbody.data, 0x2C, 0); /* reserved */
-
- /*
- * Note: Windows Vista and 2008 send back also the
- * input from the request. But it was fixed in
- * Windows 7.
- */
- outdyn = out_output_buffer;
-
- error = smbd_smb2_request_done_ex(req, status, outbody, &outdyn,
- __location__);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_ioctl_state {
- struct smbd_smb2_request *smb2req;
- struct smb_request *smbreq;
- files_struct *fsp;
- DATA_BLOB in_input;
- uint32_t in_max_output;
- DATA_BLOB out_output;
-};
-
-static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq);
-static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq);
-
-static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_ctl_code,
- uint64_t in_file_id_volatile,
- DATA_BLOB in_input,
- uint32_t in_max_output,
- uint32_t in_flags)
-{
- struct tevent_req *req;
- struct smbd_smb2_ioctl_state *state;
- struct smb_request *smbreq;
- files_struct *fsp = NULL;
- struct tevent_req *subreq;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_ioctl_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->smbreq = NULL;
- state->fsp = NULL;
- state->in_input = in_input;
- state->in_max_output = in_max_output;
- state->out_output = data_blob_null;
-
- DEBUG(10,("smbd_smb2_ioctl: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
- state->smbreq = smbreq;
-
- if (in_file_id_volatile != UINT64_MAX) {
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smbreq->conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- state->fsp = fsp;
- }
-
- switch (in_ctl_code) {
- case 0x00060194: /* FSCTL_DFS_GET_REFERRALS */
- {
- uint16_t in_max_referral_level;
- DATA_BLOB in_file_name_buffer;
- char *in_file_name_string;
- size_t in_file_name_string_size;
- bool ok;
- bool overflow = false;
- NTSTATUS status;
- int dfs_size;
- char *dfs_data = NULL;
-
- if (!IS_IPC(smbreq->conn)) {
- tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
- return tevent_req_post(req, ev);
- }
-
- if (!lp_host_msdfs()) {
- tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
- return tevent_req_post(req, ev);
- }
-
- if (in_input.length < (2 + 2)) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- in_max_referral_level = SVAL(in_input.data, 0);
- in_file_name_buffer.data = in_input.data + 2;
- in_file_name_buffer.length = in_input.length - 2;
-
- ok = convert_string_talloc(state, CH_UTF16, CH_UNIX,
- in_file_name_buffer.data,
- in_file_name_buffer.length,
- &in_file_name_string,
- &in_file_name_string_size, false);
- if (!ok) {
- tevent_req_nterror(req, NT_STATUS_ILLEGAL_CHARACTER);
- return tevent_req_post(req, ev);
- }
-
- dfs_size = setup_dfs_referral(smbreq->conn,
- in_file_name_string,
- in_max_referral_level,
- &dfs_data, &status);
- if (dfs_size < 0) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- if (dfs_size > in_max_output) {
- /*
- * TODO: we need a testsuite for this
- */
- overflow = true;
- dfs_size = in_max_output;
- }
-
- state->out_output = data_blob_talloc(state,
- (uint8_t *)dfs_data,
- dfs_size);
- SAFE_FREE(dfs_data);
- if (dfs_size > 0 &&
- tevent_req_nomem(state->out_output.data, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (overflow) {
- tevent_req_nterror(req, STATUS_BUFFER_OVERFLOW);
- } else {
- tevent_req_done(req);
- }
- return tevent_req_post(req, ev);
- }
- case 0x0011C017: /* FSCTL_PIPE_TRANSCEIVE */
-
- if (!IS_IPC(smbreq->conn)) {
- tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return tevent_req_post(req, ev);
- }
-
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (!fsp_is_np(fsp)) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- subreq = np_write_send(state, ev,
- fsp->fake_file_handle,
- in_input.data,
- in_input.length);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_ioctl_pipe_write_done,
- req);
- return req;
-
- default:
- if (IS_IPC(smbreq->conn)) {
- tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
- return tevent_req_post(req, ev);
- }
- tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return tevent_req_post(req, ev);
-}
-
-static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
- struct smbd_smb2_ioctl_state);
- NTSTATUS status;
- ssize_t nwritten = -1;
-
- status = np_write_recv(subreq, &nwritten);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- if (nwritten != state->in_input.length) {
- tevent_req_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE);
- return;
- }
-
- state->out_output = data_blob_talloc(state, NULL, state->in_max_output);
- if (state->in_max_output > 0 &&
- tevent_req_nomem(state->out_output.data, req)) {
- return;
- }
-
- subreq = np_read_send(state->smbreq->conn,
- state->smb2req->sconn->smb2.event_ctx,
- state->fsp->fake_file_handle,
- state->out_output.data,
- state->out_output.length);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq, smbd_smb2_ioctl_pipe_read_done, req);
-}
-
-static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
- struct smbd_smb2_ioctl_state);
- NTSTATUS status;
- ssize_t nread;
- bool is_data_outstanding;
-
- status = np_read_recv(subreq, &nread, &is_data_outstanding);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- state->out_output.length = nread;
-
- tevent_req_done(req);
-}
-
-static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output)
-{
- NTSTATUS status;
- struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
- struct smbd_smb2_ioctl_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- if (!NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
- tevent_req_received(req);
- return status;
- }
- }
-
- *out_output = state->out_output;
- talloc_steal(mem_ctx, out_output->data);
-
- tevent_req_received(req);
- return status;
-}
diff --git a/source3/smbd/smb2_keepalive.c b/source3/smbd/smb2_keepalive.c
deleted file mode 100644
index 6645a00dad..0000000000
--- a/source3/smbd/smb2_keepalive.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-NTSTATUS smbd_smb2_request_process_keepalive(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- int i = req->current_idx;
- DATA_BLOB outbody;
- size_t expected_body_size = 0x04;
- size_t body_size;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- /* TODO: update some time stamps */
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x04); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
-
- return smbd_smb2_request_done(req, outbody, NULL);
-}
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
deleted file mode 100644
index 908e1cf8a4..0000000000
--- a/source3/smbd/smb2_lock.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-struct smbd_smb2_lock_element {
- uint64_t offset;
- uint64_t length;
- uint32_t flags;
-};
-
-static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- uint16_t in_lock_count,
- struct smbd_smb2_lock_element *in_locks);
-static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req);
-
-static void smbd_smb2_request_lock_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- const int i = req->current_idx;
- size_t expected_body_size = 0x30;
- size_t body_size;
- uint32_t in_smbpid;
- uint16_t in_lock_count;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- struct smbd_smb2_lock_element *in_locks;
- struct tevent_req *subreq;
- const uint8_t *lock_buffer;
- uint16_t l;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
-
- in_lock_count = CVAL(inbody, 0x02);
- /* 0x04 - 4 bytes reserved */
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
-
- if (in_lock_count < 1) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (((in_lock_count - 1) * 0x18) > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- in_locks = talloc_array(req, struct smbd_smb2_lock_element,
- in_lock_count);
- if (in_locks == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- l = 0;
- lock_buffer = inbody + 0x18;
-
- in_locks[l].offset = BVAL(lock_buffer, 0x00);
- in_locks[l].length = BVAL(lock_buffer, 0x08);
- in_locks[l].flags = IVAL(lock_buffer, 0x10);
- /* 0x14 - 4 reserved bytes */
-
- lock_buffer = (const uint8_t *)req->in.vector[i+2].iov_base;
-
- for (l=1; l < in_lock_count; l++) {
- in_locks[l].offset = BVAL(lock_buffer, 0x00);
- in_locks[l].length = BVAL(lock_buffer, 0x08);
- in_locks[l].flags = IVAL(lock_buffer, 0x10);
- /* 0x14 - 4 reserved bytes */
-
- lock_buffer += 0x18;
- }
-
- subreq = smbd_smb2_lock_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_smbpid,
- in_file_id_volatile,
- in_lock_count,
- in_locks);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_lock_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_lock_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- DATA_BLOB outbody;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_lock_recv(subreq);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x04); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
-
- error = smbd_smb2_request_done(req, outbody, NULL);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_lock_state {
- struct smbd_smb2_request *smb2req;
-};
-
-static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- uint16_t in_lock_count,
- struct smbd_smb2_lock_element *in_locks)
-{
- struct tevent_req *req;
- struct smbd_smb2_lock_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
- int32_t timeout = -1;
- bool isunlock = false;
- uint16_t i;
- struct smbd_lock_element *locks;
- NTSTATUS status;
- bool async = false;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_lock_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
-
- DEBUG(10,("smbd_smb2_lock_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- locks = talloc_array(state, struct smbd_lock_element, in_lock_count);
- if (locks == NULL) {
- tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
- return tevent_req_post(req, ev);
- }
-
- switch (in_locks[0].flags) {
- case SMB2_LOCK_FLAG_SHARED:
- case SMB2_LOCK_FLAG_EXCLUSIVE:
- if (in_lock_count > 1) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- timeout = -1;
- break;
-
- case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
- case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
- timeout = 0;
- break;
-
- case SMB2_LOCK_FLAG_UNLOCK:
- /* only the first lock gives the UNLOCK bit - see
- MS-SMB2 3.3.5.14 */
- isunlock = true;
- timeout = 0;
- break;
-
- default:
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- for (i=0; i<in_lock_count; i++) {
- uint64_t max_count;
- bool invalid = false;
-
- switch (in_locks[i].flags) {
- case SMB2_LOCK_FLAG_SHARED:
- case SMB2_LOCK_FLAG_EXCLUSIVE:
- if (i > 0) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- if (isunlock) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- break;
-
- case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
- case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
- if (isunlock) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- break;
-
- case SMB2_LOCK_FLAG_UNLOCK:
- if (!isunlock) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
- break;
-
- default:
- if (isunlock) {
- /*
- * is the first element was a UNLOCK
- * we need to deferr the error response
- * to the backend, because we need to process
- * all unlock elements before
- */
- invalid = true;
- break;
- }
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- locks[i].smbpid = in_smbpid;
- locks[i].offset = in_locks[i].offset;
- locks[i].count = in_locks[i].length;
-
- if (in_locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE) {
- locks[i].brltype = WRITE_LOCK;
- } else if (in_locks[i].flags & SMB2_LOCK_FLAG_SHARED) {
- locks[i].brltype = READ_LOCK;
- } else if (invalid) {
- /*
- * this is an invalid UNLOCK element
- * and the backend needs to test for
- * brltype != UNLOCK_LOCK and return
- * NT_STATUS_INVALID_PARAMER
- */
- locks[i].brltype = READ_LOCK;
- } else {
- locks[i].brltype = UNLOCK_LOCK;
- }
-
- max_count = UINT64_MAX - locks[i].offset;
- if (locks[i].count > max_count) {
- tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_RANGE);
- return tevent_req_post(req, ev);
- }
- }
-
- if (isunlock) {
- status = smbd_do_locking(smbreq, fsp,
- 0,
- timeout,
- in_lock_count,
- locks,
- 0,
- NULL,
- &async);
- } else {
- status = smbd_do_locking(smbreq, fsp,
- 0,
- timeout,
- 0,
- NULL,
- in_lock_count,
- locks,
- &async);
- }
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) {
- status = NT_STATUS_LOCK_NOT_GRANTED;
- }
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- if (async) {
- tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req)
-{
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c
deleted file mode 100644
index 5b97c65d79..0000000000
--- a/source3/smbd/smb2_negprot.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-/*
- * this is the entry point if SMB2 is selected via
- * the SMB negprot
- */
-void reply_smb2002(struct smb_request *req, uint16_t choice)
-{
- uint8_t *smb2_inbuf;
- uint8_t *smb2_hdr;
- uint8_t *smb2_body;
- uint8_t *smb2_dyn;
- size_t len = 4 + SMB2_HDR_BODY + 0x24 + 2;
-
- smb2_inbuf = talloc_zero_array(talloc_tos(), uint8_t, len);
- if (smb2_inbuf == NULL) {
- DEBUG(0, ("Could not push spnego blob\n"));
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- smb2_hdr = smb2_inbuf + 4;
- smb2_body = smb2_hdr + SMB2_HDR_BODY;
- smb2_dyn = smb2_body + 0x24;
-
- SIVAL(smb2_hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
- SIVAL(smb2_hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
-
- SSVAL(smb2_body, 0x00, 0x0024); /* struct size */
- SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */
-
- SSVAL(smb2_dyn, 0x00, 0x0202); /* dialect 2.002 */
-
- req->outbuf = NULL;
-
- smbd_smb2_first_negprot(smbd_server_conn, smb2_inbuf, len);
- return;
-}
-
-NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- const uint8_t *indyn = NULL;
- int i = req->current_idx;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- DATA_BLOB negprot_spnego_blob;
- uint16_t security_offset;
- DATA_BLOB security_buffer;
- size_t expected_body_size = 0x24;
- size_t body_size;
- size_t expected_dyn_size = 0;
- size_t c;
- uint16_t security_mode;
- uint16_t dialect_count;
- uint16_t dialect = 0;
- uint32_t capabilities;
-
-/* TODO: drop the connection with INVALI_PARAMETER */
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- dialect_count = SVAL(inbody, 0x02);
- if (dialect_count == 0) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- expected_dyn_size = dialect_count * 2;
- if (req->in.vector[i+2].iov_len < expected_dyn_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
- indyn = (const uint8_t *)req->in.vector[i+2].iov_base;
-
- for (c=0; c < dialect_count; c++) {
- dialect = SVAL(indyn, c*2);
- if (dialect == SMB2_DIALECT_REVISION_202) {
- break;
- }
- }
-
- if (dialect != SMB2_DIALECT_REVISION_202) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- set_Protocol(PROTOCOL_SMB2);
-
- if (get_remote_arch() != RA_SAMBA) {
- set_remote_arch(RA_VISTA);
- }
-
- /* negprot_spnego() returns a the server guid in the first 16 bytes */
- negprot_spnego_blob = negprot_spnego();
- if (negprot_spnego_blob.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- talloc_steal(req, negprot_spnego_blob.data);
-
- if (negprot_spnego_blob.length < 16) {
- return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
- }
-
- security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
- if (lp_server_signing() == Required) {
- security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
- }
-
- capabilities = 0;
- if (lp_host_msdfs()) {
- capabilities |= SMB2_CAP_DFS;
- }
-
- security_offset = SMB2_HDR_BODY + 0x40;
-
-#if 1
- /* Try SPNEGO auth... */
- security_buffer = data_blob_const(negprot_spnego_blob.data + 16,
- negprot_spnego_blob.length - 16);
-#else
- /* for now we want raw NTLMSSP */
- security_buffer = data_blob_const(NULL, 0);
-#endif
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x40);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x40 + 1); /* struct size */
- SSVAL(outbody.data, 0x02,
- security_mode); /* security mode */
- SSVAL(outbody.data, 0x04, dialect); /* dialect revision */
- SSVAL(outbody.data, 0x06, 0); /* reserved */
- memcpy(outbody.data + 0x08,
- negprot_spnego_blob.data, 16); /* server guid */
- SIVAL(outbody.data, 0x18,
- capabilities); /* capabilities */
- SIVAL(outbody.data, 0x1C, 0x00010000); /* max transact size */
- SIVAL(outbody.data, 0x20, 0x00010000); /* max read size */
- SIVAL(outbody.data, 0x24, 0x00010000); /* max write size */
- SBVAL(outbody.data, 0x28, 0); /* system time */
- SBVAL(outbody.data, 0x30, 0); /* server start time */
- SSVAL(outbody.data, 0x38,
- security_offset); /* security buffer offset */
- SSVAL(outbody.data, 0x3A,
- security_buffer.length); /* security buffer length */
- SIVAL(outbody.data, 0x3C, 0); /* reserved */
-
- outdyn = security_buffer;
-
- return smbd_smb2_request_done(req, outbody, &outdyn);
-}
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
deleted file mode 100644
index fb465abff9..0000000000
--- a/source3/smbd/smb2_notify.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint16_t in_flags,
- uint32_t in_output_buffer_length,
- uint64_t in_file_id_volatile,
- uint64_t in_completion_filter);
-static NTSTATUS smbd_smb2_notify_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer);
-
-static void smbd_smb2_request_notify_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x20;
- size_t body_size;
- uint16_t in_flags;
- uint32_t in_output_buffer_length;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint64_t in_completion_filter;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_flags = SVAL(inbody, 0x02);
- in_output_buffer_length = IVAL(inbody, 0x04);
- in_file_id_persistent = BVAL(inbody, 0x08);
- in_file_id_volatile = BVAL(inbody, 0x10);
- in_completion_filter = IVAL(inbody, 0x18);
-
- /*
- * 0x00010000 is what Windows 7 uses,
- * Windows 2008 uses 0x00080000
- */
- if (in_output_buffer_length > 0x00010000) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_notify_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_flags,
- in_output_buffer_length,
- in_file_id_volatile,
- in_completion_filter);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_notify_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_notify_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint16_t out_output_buffer_offset;
- DATA_BLOB out_output_buffer = data_blob_null;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_notify_recv(subreq,
- req,
- &out_output_buffer);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x08);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
- SSVAL(outbody.data, 0x02,
- out_output_buffer_offset); /* output buffer offset */
- SIVAL(outbody.data, 0x04,
- out_output_buffer.length); /* output buffer length */
-
- outdyn = out_output_buffer;
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_notify_state {
- struct smbd_smb2_request *smb2req;
- struct smb_request *smbreq;
- struct tevent_immediate *im;
- NTSTATUS status;
- DATA_BLOB out_output_buffer;
-};
-
-static void smbd_smb2_notify_reply(struct smb_request *smbreq,
- NTSTATUS error_code,
- uint8_t *buf, size_t len);
-static void smbd_smb2_notify_reply_trigger(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data);
-static bool smbd_smb2_notify_cancel(struct tevent_req *req);
-
-static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint16_t in_flags,
- uint32_t in_output_buffer_length,
- uint64_t in_file_id_volatile,
- uint64_t in_completion_filter)
-{
- struct tevent_req *req;
- struct smbd_smb2_notify_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
- bool recursive = (in_flags & 0x0001) ? true : false;
- NTSTATUS status;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_notify_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->status = NT_STATUS_INTERNAL_ERROR;
- state->out_output_buffer = data_blob_null;
- state->im = NULL;
-
- DEBUG(10,("smbd_smb2_notify_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- state->smbreq = smbreq;
- smbreq->async_priv = (void *)req;
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- {
- char *filter_string;
-
- filter_string = notify_filter_string(NULL, in_completion_filter);
- if (tevent_req_nomem(filter_string, req)) {
- return tevent_req_post(req, ev);
- }
-
- DEBUG(3,("smbd_smb2_notify_send: notify change "
- "called on %s, filter = %s, recursive = %d\n",
- fsp_str_dbg(fsp), filter_string, recursive));
-
- TALLOC_FREE(filter_string);
- }
-
- if ((!fsp->is_directory) || (conn != fsp->conn)) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- if (fsp->notify == NULL) {
-
- status = change_notify_create(fsp,
- in_completion_filter,
- recursive);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("change_notify_create returned %s\n",
- nt_errstr(status)));
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
-
- if (fsp->notify->num_changes != 0) {
-
- /*
- * We've got changes pending, respond immediately
- */
-
- /*
- * TODO: write a torture test to check the filtering behaviour
- * here.
- */
-
- change_notify_reply(fsp->conn, smbreq,
- NT_STATUS_OK,
- in_output_buffer_length,
- fsp->notify,
- smbd_smb2_notify_reply);
-
- /*
- * change_notify_reply() above has independently
- * called tevent_req_done().
- */
- return tevent_req_post(req, ev);
- }
-
- state->im = tevent_create_immediate(state);
- if (tevent_req_nomem(state->im, req)) {
- return tevent_req_post(req, ev);
- }
-
- /*
- * No changes pending, queue the request
- */
-
- status = change_notify_add_request(smbreq,
- in_output_buffer_length,
- in_completion_filter,
- recursive, fsp,
- smbd_smb2_notify_reply);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- /* allow this request to be canceled */
- tevent_req_set_cancel_fn(req, smbd_smb2_notify_cancel);
-
- return req;
-}
-
-static void smbd_smb2_notify_reply(struct smb_request *smbreq,
- NTSTATUS error_code,
- uint8_t *buf, size_t len)
-{
- struct tevent_req *req = talloc_get_type_abort(smbreq->async_priv,
- struct tevent_req);
- struct smbd_smb2_notify_state *state = tevent_req_data(req,
- struct smbd_smb2_notify_state);
-
- state->status = error_code;
- if (!NT_STATUS_IS_OK(error_code)) {
- /* nothing */
- } else if (len == 0) {
- state->status = STATUS_NOTIFY_ENUM_DIR;
- } else {
- state->out_output_buffer = data_blob_talloc(state, buf, len);
- if (state->out_output_buffer.data == NULL) {
- state->status = NT_STATUS_NO_MEMORY;
- }
- }
-
- if (state->im == NULL) {
- smbd_smb2_notify_reply_trigger(NULL, NULL, req);
- return;
- }
-
- /*
- * if this is called async, we need to go via an immediate event
- * because the caller replies on the smb_request (a child of req
- * being arround after calling this function
- */
- tevent_schedule_immediate(state->im,
- state->smb2req->sconn->smb2.event_ctx,
- smbd_smb2_notify_reply_trigger,
- req);
-}
-
-static void smbd_smb2_notify_reply_trigger(struct tevent_context *ctx,
- struct tevent_immediate *im,
- void *private_data)
-{
- struct tevent_req *req = talloc_get_type_abort(private_data,
- struct tevent_req);
- struct smbd_smb2_notify_state *state = tevent_req_data(req,
- struct smbd_smb2_notify_state);
-
- if (!NT_STATUS_IS_OK(state->status)) {
- tevent_req_nterror(req, state->status);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static bool smbd_smb2_notify_cancel(struct tevent_req *req)
-{
- struct smbd_smb2_notify_state *state = tevent_req_data(req,
- struct smbd_smb2_notify_state);
-
- smbd_notify_cancel_by_smbreq(state->smb2req->sconn,
- state->smbreq);
-
- return true;
-}
-
-static NTSTATUS smbd_smb2_notify_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer)
-{
- NTSTATUS status;
- struct smbd_smb2_notify_state *state = tevent_req_data(req,
- struct smbd_smb2_notify_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_output_buffer = state->out_output_buffer;
- talloc_steal(mem_ctx, out_output_buffer->data);
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
deleted file mode 100644
index 3f316e0b71..0000000000
--- a/source3/smbd/smb2_read.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- uint32_t in_length,
- uint64_t in_offset,
- uint32_t in_minimum,
- uint32_t in_remaining);
-static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_data,
- uint32_t *out_remaining);
-
-static void smbd_smb2_request_read_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x31;
- size_t body_size;
- uint32_t in_smbpid;
- uint32_t in_length;
- uint64_t in_offset;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint32_t in_minimum_count;
- uint32_t in_remaining_bytes;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
-
- in_length = IVAL(inbody, 0x04);
- in_offset = BVAL(inbody, 0x08);
- in_file_id_persistent = BVAL(inbody, 0x10);
- in_file_id_volatile = BVAL(inbody, 0x18);
- in_minimum_count = IVAL(inbody, 0x20);
- in_remaining_bytes = IVAL(inbody, 0x28);
-
- /* check the max read size */
- if (in_length > 0x00010000) {
- DEBUG(0,("here:%s: 0x%08X: 0x%08X\n",
- __location__, in_length, 0x00010000));
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_read_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_smbpid,
- in_file_id_volatile,
- in_length,
- in_offset,
- in_minimum_count,
- in_remaining_bytes);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_read_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint8_t out_data_offset;
- DATA_BLOB out_data_buffer = data_blob_null;
- uint32_t out_data_remaining = 0;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_read_recv(subreq,
- req,
- &out_data_buffer,
- &out_data_remaining);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- out_data_offset = SMB2_HDR_BODY + 0x10;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x10 + 1); /* struct size */
- SCVAL(outbody.data, 0x02,
- out_data_offset); /* data offset */
- SCVAL(outbody.data, 0x03, 0); /* reserved */
- SIVAL(outbody.data, 0x04,
- out_data_buffer.length); /* data length */
- SIVAL(outbody.data, 0x08,
- out_data_remaining); /* data remaining */
- SIVAL(outbody.data, 0x0C, 0); /* reserved */
-
- outdyn = out_data_buffer;
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_read_state {
- struct smbd_smb2_request *smb2req;
- DATA_BLOB out_data;
- uint32_t out_remaining;
-};
-
-static void smbd_smb2_read_pipe_done(struct tevent_req *subreq);
-
-static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- uint32_t in_length,
- uint64_t in_offset,
- uint32_t in_minimum,
- uint32_t in_remaining)
-{
- struct tevent_req *req;
- struct smbd_smb2_read_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
- ssize_t nread = -1;
- struct lock_struct lock;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_read_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->out_data = data_blob_null;
- state->out_remaining = 0;
-
- DEBUG(10,("smbd_smb2_read: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- state->out_data = data_blob_talloc(state, NULL, in_length);
- if (in_length > 0 && tevent_req_nomem(state->out_data.data, req)) {
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(smbreq->conn)) {
- struct tevent_req *subreq;
-
- if (!fsp_is_np(fsp)) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- subreq = np_read_send(state, smbd_event_context(),
- fsp->fake_file_handle,
- state->out_data.data,
- state->out_data.length);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_read_pipe_done,
- req);
- return req;
- }
-
- if (!CHECK_READ(fsp, smbreq)) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
-
- init_strict_lock_struct(fsp,
- in_smbpid,
- in_offset,
- in_length,
- READ_LOCK,
- &lock);
-
- if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
- return tevent_req_post(req, ev);
- }
-
- nread = read_file(fsp,
- (char *)state->out_data.data,
- in_offset,
- in_length);
-
- SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-
- if (nread < 0) {
- DEBUG(5,("smbd_smb2_read: read_file[%s] nread[%lld]\n",
- fsp_str_dbg(fsp), (long long)nread));
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
- if (nread == 0 && in_length != 0) {
- DEBUG(5,("smbd_smb2_read: read_file[%s] end of file\n",
- fsp_str_dbg(fsp)));
- tevent_req_nterror(req, NT_STATUS_END_OF_FILE);
- return tevent_req_post(req, ev);
- }
-
- state->out_data.length = nread;
- state->out_remaining = 0;
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static void smbd_smb2_read_pipe_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct smbd_smb2_read_state *state = tevent_req_data(req,
- struct smbd_smb2_read_state);
- NTSTATUS status;
- ssize_t nread = -1;
- bool is_data_outstanding;
-
- status = np_read_recv(subreq, &nread, &is_data_outstanding);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- if (nread == 0 && state->out_data.length != 0) {
- tevent_req_nterror(req, NT_STATUS_END_OF_FILE);
- return;
- }
-
- state->out_data.length = nread;
- state->out_remaining = 0;
-
- tevent_req_done(req);
-}
-
-static NTSTATUS smbd_smb2_read_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_data,
- uint32_t *out_remaining)
-{
- NTSTATUS status;
- struct smbd_smb2_read_state *state = tevent_req_data(req,
- struct smbd_smb2_read_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_data = state->out_data;
- talloc_steal(mem_ctx, out_data->data);
- *out_remaining = state->out_remaining;
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
deleted file mode 100644
index 9e5be404ef..0000000000
--- a/source3/smbd/smb2_server.c
+++ /dev/null
@@ -1,1586 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-#include "../lib/tsocket/tsocket.h"
-
-bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size)
-{
- if (size < (4 + SMB2_HDR_BODY)) {
- return false;
- }
-
- if (IVAL(inbuf, 4) != SMB2_MAGIC) {
- return false;
- }
-
- return true;
-}
-
-static NTSTATUS smbd_initialize_smb2(struct smbd_server_connection *sconn)
-{
- NTSTATUS status;
- int ret;
-
- TALLOC_FREE(sconn->smb1.fde);
-
- sconn->smb2.event_ctx = smbd_event_context();
-
- sconn->smb2.recv_queue = tevent_queue_create(sconn, "smb2 recv queue");
- if (sconn->smb2.recv_queue == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- sconn->smb2.send_queue = tevent_queue_create(sconn, "smb2 send queue");
- if (sconn->smb2.send_queue == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- sconn->smb2.sessions.idtree = idr_init(sconn);
- if (sconn->smb2.sessions.idtree == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- sconn->smb2.sessions.limit = 0x0000FFFE;
- sconn->smb2.sessions.list = NULL;
-
- ret = tstream_bsd_existing_socket(sconn, smbd_server_fd(),
- &sconn->smb2.stream);
- if (ret == -1) {
- status = map_nt_error_from_unix(errno);
- return status;
- }
-
- /* Ensure child is set to non-blocking mode */
- set_blocking(smbd_server_fd(),false);
- return NT_STATUS_OK;
-}
-
-#define smb2_len(buf) (PVAL(buf,3)|(PVAL(buf,2)<<8)|(PVAL(buf,1)<<16))
-#define _smb2_setlen(_buf,len) do { \
- uint8_t *buf = (uint8_t *)_buf; \
- buf[0] = 0; \
- buf[1] = ((len)&0xFF0000)>>16; \
- buf[2] = ((len)&0xFF00)>>8; \
- buf[3] = (len)&0xFF; \
-} while (0)
-
-static void smb2_setup_nbt_length(struct iovec *vector, int count)
-{
- size_t len = 0;
- int i;
-
- for (i=1; i < count; i++) {
- len += vector[i].iov_len;
- }
-
- _smb2_setlen(vector[0].iov_base, len);
-}
-
-static int smbd_smb2_request_parent_destructor(struct smbd_smb2_request **req)
-{
- if (*req) {
- (*req)->parent = NULL;
- (*req)->mem_pool = NULL;
- }
-
- return 0;
-}
-
-static int smbd_smb2_request_destructor(struct smbd_smb2_request *req)
-{
- if (req->out.vector) {
- DLIST_REMOVE(req->sconn->smb2.requests, req);
- }
-
- if (req->parent) {
- *req->parent = NULL;
- talloc_free(req->mem_pool);
- }
-
- return 0;
-}
-
-static struct smbd_smb2_request *smbd_smb2_request_allocate(TALLOC_CTX *mem_ctx)
-{
- TALLOC_CTX *mem_pool;
- struct smbd_smb2_request **parent;
- struct smbd_smb2_request *req;
-
- mem_pool = talloc_pool(mem_ctx, 8192);
- if (mem_pool == NULL) {
- return NULL;
- }
-
- parent = talloc(mem_pool, struct smbd_smb2_request *);
- if (parent == NULL) {
- talloc_free(mem_pool);
- return NULL;
- }
-
- req = talloc_zero(parent, struct smbd_smb2_request);
- if (req == NULL) {
- talloc_free(mem_pool);
- return NULL;
- }
- *parent = req;
- req->mem_pool = mem_pool;
- req->parent = parent;
-
- talloc_set_destructor(parent, smbd_smb2_request_parent_destructor);
- talloc_set_destructor(req, smbd_smb2_request_destructor);
-
- return req;
-}
-
-static NTSTATUS smbd_smb2_request_create(struct smbd_server_connection *sconn,
- const uint8_t *inbuf, size_t size,
- struct smbd_smb2_request **_req)
-{
- struct smbd_smb2_request *req;
- uint32_t protocol_version;
- const uint8_t *inhdr = NULL;
- off_t ofs = 0;
- uint16_t cmd;
- uint32_t next_command_ofs;
-
- if (size < (4 + SMB2_HDR_BODY + 2)) {
- DEBUG(0,("Invalid SMB2 packet length count %ld\n", (long)size));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- inhdr = inbuf + 4;
-
- protocol_version = IVAL(inhdr, SMB2_HDR_PROTOCOL_ID);
- if (protocol_version != SMB2_MAGIC) {
- DEBUG(0,("Invalid SMB packet: protocol prefix: 0x%08X\n",
- protocol_version));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- cmd = SVAL(inhdr, SMB2_HDR_OPCODE);
- if (cmd != SMB2_OP_NEGPROT) {
- DEBUG(0,("Invalid SMB packet: first request: 0x%04X\n",
- cmd));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- next_command_ofs = IVAL(inhdr, SMB2_HDR_NEXT_COMMAND);
- if (next_command_ofs != 0) {
- DEBUG(0,("Invalid SMB packet: next_command: 0x%08X\n",
- next_command_ofs));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- req = smbd_smb2_request_allocate(sconn);
- if (req == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- req->sconn = sconn;
-
- talloc_steal(req, inbuf);
-
- req->in.vector = talloc_array(req, struct iovec, 4);
- if (req->in.vector == NULL) {
- TALLOC_FREE(req);
- return NT_STATUS_NO_MEMORY;
- }
- req->in.vector_count = 4;
-
- memcpy(req->in.nbt_hdr, inbuf, 4);
-
- ofs = 0;
- req->in.vector[0].iov_base = (void *)req->in.nbt_hdr;
- req->in.vector[0].iov_len = 4;
- ofs += req->in.vector[0].iov_len;
-
- req->in.vector[1].iov_base = (void *)(inbuf + ofs);
- req->in.vector[1].iov_len = SMB2_HDR_BODY;
- ofs += req->in.vector[1].iov_len;
-
- req->in.vector[2].iov_base = (void *)(inbuf + ofs);
- req->in.vector[2].iov_len = SVAL(inbuf, ofs) & 0xFFFE;
- ofs += req->in.vector[2].iov_len;
-
- if (ofs > size) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- req->in.vector[3].iov_base = (void *)(inbuf + ofs);
- req->in.vector[3].iov_len = size - ofs;
- ofs += req->in.vector[3].iov_len;
-
- req->current_idx = 1;
-
- *_req = req;
- return NT_STATUS_OK;
-}
-
-static NTSTATUS smbd_smb2_request_validate(struct smbd_smb2_request *req)
-{
- int count;
- int idx;
- bool compound_related = false;
-
- count = req->in.vector_count;
-
- if (count < 4) {
- /* It's not a SMB2 request */
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- for (idx=1; idx < count; idx += 3) {
- const uint8_t *inhdr = NULL;
- uint32_t flags;
-
- if (req->in.vector[idx].iov_len != SMB2_HDR_BODY) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (req->in.vector[idx+1].iov_len < 2) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
-
- /* setup the SMB2 header */
- if (IVAL(inhdr, SMB2_HDR_PROTOCOL_ID) != SMB2_MAGIC) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- flags = IVAL(inhdr, SMB2_HDR_FLAGS);
- if (idx == 1) {
- /*
- * the 1st request should never have the
- * SMB2_HDR_FLAG_CHAINED flag set
- */
- if (flags & SMB2_HDR_FLAG_CHAINED) {
- req->next_status = NT_STATUS_INVALID_PARAMETER;
- return NT_STATUS_OK;
- }
- } else if (idx == 4) {
- /*
- * the 2nd request triggers related vs. unrelated
- * compounded requests
- */
- if (flags & SMB2_HDR_FLAG_CHAINED) {
- compound_related = true;
- }
- } else if (idx > 4) {
-#if 0
- /*
- * It seems the this tests are wrong
- * see the SMB2-COMPOUND test
- */
-
- /*
- * all other requests should match the 2nd one
- */
- if (flags & SMB2_HDR_FLAG_CHAINED) {
- if (!compound_related) {
- req->next_status =
- NT_STATUS_INVALID_PARAMETER;
- return NT_STATUS_OK;
- }
- } else {
- if (compound_related) {
- req->next_status =
- NT_STATUS_INVALID_PARAMETER;
- return NT_STATUS_OK;
- }
- }
-#endif
- }
- }
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS smbd_smb2_request_setup_out(struct smbd_smb2_request *req)
-{
- struct iovec *vector;
- int count;
- int idx;
-
- count = req->in.vector_count;
- vector = talloc_array(req, struct iovec, count);
- if (vector == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- vector[0].iov_base = req->out.nbt_hdr;
- vector[0].iov_len = 4;
- SIVAL(req->out.nbt_hdr, 0, 0);
-
- for (idx=1; idx < count; idx += 3) {
- const uint8_t *inhdr = NULL;
- uint32_t in_flags;
- uint8_t *outhdr = NULL;
- uint8_t *outbody = NULL;
- uint32_t next_command_ofs = 0;
- struct iovec *current = &vector[idx];
-
- if ((idx + 3) < count) {
- /* we have a next command */
- next_command_ofs = SMB2_HDR_BODY + 8;
- }
-
- inhdr = (const uint8_t *)req->in.vector[idx].iov_base;
- in_flags = IVAL(inhdr, SMB2_HDR_FLAGS);
-
- outhdr = talloc_array(vector, uint8_t,
- SMB2_HDR_BODY + 8);
- if (outhdr == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- outbody = outhdr + SMB2_HDR_BODY;
-
- current[0].iov_base = (void *)outhdr;
- current[0].iov_len = SMB2_HDR_BODY;
-
- current[1].iov_base = (void *)outbody;
- current[1].iov_len = 8;
-
- current[2].iov_base = NULL;
- current[2].iov_len = 0;
-
- /* setup the SMB2 header */
- SIVAL(outhdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
- SSVAL(outhdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(outhdr, SMB2_HDR_EPOCH, 0);
- SIVAL(outhdr, SMB2_HDR_STATUS,
- NT_STATUS_V(NT_STATUS_INTERNAL_ERROR));
- SSVAL(outhdr, SMB2_HDR_OPCODE,
- SVAL(inhdr, SMB2_HDR_OPCODE));
- /* Make up a number for now... JRA. FIXME ! FIXME !*/
- SSVAL(outhdr, SMB2_HDR_CREDIT, 20);
- SIVAL(outhdr, SMB2_HDR_FLAGS,
- IVAL(inhdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_REDIRECT);
- SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
- SBVAL(outhdr, SMB2_HDR_MESSAGE_ID,
- BVAL(inhdr, SMB2_HDR_MESSAGE_ID));
- SIVAL(outhdr, SMB2_HDR_PID,
- IVAL(inhdr, SMB2_HDR_PID));
- SIVAL(outhdr, SMB2_HDR_TID,
- IVAL(inhdr, SMB2_HDR_TID));
- SBVAL(outhdr, SMB2_HDR_SESSION_ID,
- BVAL(inhdr, SMB2_HDR_SESSION_ID));
- memset(outhdr + SMB2_HDR_SIGNATURE, 0, 16);
-
- /* setup error body header */
- SSVAL(outbody, 0x00, 0x08 + 1);
- SSVAL(outbody, 0x02, 0);
- SIVAL(outbody, 0x04, 0);
- }
-
- req->out.vector = vector;
- req->out.vector_count = count;
-
- /* setup the length of the NBT packet */
- smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
-
- DLIST_ADD_END(req->sconn->smb2.requests, req, struct smbd_smb2_request *);
-
- return NT_STATUS_OK;
-}
-
-void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn,
- const char *reason,
- const char *location)
-{
- DEBUG(10,("smbd_server_connection_terminate_ex: reason[%s] at %s\n",
- reason, location));
- exit_server_cleanly(reason);
-}
-
-struct smbd_smb2_request_pending_state {
- struct smbd_server_connection *sconn;
- uint8_t buf[4 + SMB2_HDR_BODY + 0x08];
- struct iovec vector;
-};
-
-static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq);
-
-NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
- struct tevent_req *subreq)
-{
- struct smbd_smb2_request_pending_state *state;
- uint8_t *outhdr;
- int i = req->current_idx;
- uint32_t flags;
- uint64_t message_id;
- uint64_t async_id;
- uint8_t *hdr;
- uint8_t *body;
-
- if (!tevent_req_is_in_progress(subreq)) {
- return NT_STATUS_OK;
- }
-
- req->subreq = subreq;
- subreq = NULL;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- flags = IVAL(outhdr, SMB2_HDR_FLAGS);
- message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
-
- async_id = message_id; /* keep it simple for now... */
- SIVAL(outhdr, SMB2_HDR_FLAGS, flags | SMB2_HDR_FLAG_ASYNC);
- SBVAL(outhdr, SMB2_HDR_PID, async_id);
-
- /* TODO: add a paramter to delay this */
- state = talloc(req->sconn, struct smbd_smb2_request_pending_state);
- if (state == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- state->sconn = req->sconn;
-
- state->vector.iov_base = (void *)state->buf;
- state->vector.iov_len = sizeof(state->buf);
-
- _smb2_setlen(state->buf, sizeof(state->buf) - 4);
- hdr = state->buf + 4;
- body = hdr + SMB2_HDR_BODY;
-
- SIVAL(hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC);
- SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(hdr, SMB2_HDR_EPOCH, 0);
- SIVAL(hdr, SMB2_HDR_STATUS, NT_STATUS_V(STATUS_PENDING));
- SSVAL(hdr, SMB2_HDR_OPCODE,
- SVAL(outhdr, SMB2_HDR_OPCODE));
- SSVAL(hdr, SMB2_HDR_CREDIT, 1);
- SIVAL(hdr, SMB2_HDR_FLAGS,
- IVAL(outhdr, SMB2_HDR_FLAGS));
- SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
- SBVAL(hdr, SMB2_HDR_MESSAGE_ID,
- BVAL(outhdr, SMB2_HDR_MESSAGE_ID));
- SBVAL(hdr, SMB2_HDR_PID,
- BVAL(outhdr, SMB2_HDR_PID));
- SBVAL(hdr, SMB2_HDR_SESSION_ID,
- BVAL(outhdr, SMB2_HDR_SESSION_ID));
- memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
-
- SSVAL(body, 0x00, 0x08 + 1);
-
- SCVAL(body, 0x02, 0);
- SCVAL(body, 0x03, 0);
- SIVAL(body, 0x04, 0);
-
- subreq = tstream_writev_queue_send(state,
- req->sconn->smb2.event_ctx,
- req->sconn->smb2.stream,
- req->sconn->smb2.send_queue,
- &state->vector, 1);
- if (subreq == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_request_pending_writev_done,
- state);
-
- return NT_STATUS_OK;
-}
-
-static void smbd_smb2_request_pending_writev_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request_pending_state *state =
- tevent_req_callback_data(subreq,
- struct smbd_smb2_request_pending_state);
- struct smbd_server_connection *sconn = state->sconn;
- int ret;
- int sys_errno;
-
- ret = tstream_writev_queue_recv(subreq, &sys_errno);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- NTSTATUS status = map_nt_error_from_unix(sys_errno);
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- TALLOC_FREE(state);
-}
-
-static NTSTATUS smbd_smb2_request_process_cancel(struct smbd_smb2_request *req)
-{
- struct smbd_server_connection *sconn = req->sconn;
- struct smbd_smb2_request *cur;
- const uint8_t *inhdr;
- int i = req->current_idx;
- uint32_t flags;
- uint64_t search_message_id;
- uint64_t search_async_id;
-
- inhdr = (const uint8_t *)req->in.vector[i].iov_base;
-
- flags = IVAL(inhdr, SMB2_HDR_FLAGS);
- search_message_id = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
- search_async_id = BVAL(inhdr, SMB2_HDR_PID);
-
- /*
- * we don't need the request anymore
- * cancel requests never have a response
- */
- TALLOC_FREE(req);
-
- for (cur = sconn->smb2.requests; cur; cur = cur->next) {
- const uint8_t *outhdr;
- uint64_t message_id;
- uint64_t async_id;
-
- i = cur->current_idx;
-
- outhdr = (const uint8_t *)cur->out.vector[i].iov_base;
-
- message_id = BVAL(outhdr, SMB2_HDR_MESSAGE_ID);
- async_id = BVAL(outhdr, SMB2_HDR_PID);
-
- if (flags & SMB2_HDR_FLAG_ASYNC) {
- if (search_async_id == async_id) {
- break;
- }
- } else {
- if (search_message_id == message_id) {
- break;
- }
- }
- }
-
- if (cur && cur->subreq) {
- tevent_req_cancel(cur->subreq);
- }
-
- return NT_STATUS_OK;
-}
-
-static NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- int i = req->current_idx;
- uint16_t opcode;
- uint32_t flags;
- NTSTATUS status;
- NTSTATUS session_status;
- uint32_t allowed_flags;
-
- inhdr = (const uint8_t *)req->in.vector[i].iov_base;
-
- /* TODO: verify more things */
-
- flags = IVAL(inhdr, SMB2_HDR_FLAGS);
- opcode = IVAL(inhdr, SMB2_HDR_OPCODE);
- DEBUG(10,("smbd_smb2_request_dispatch: opcode[%u]\n", opcode));
-
- allowed_flags = SMB2_HDR_FLAG_CHAINED |
- SMB2_HDR_FLAG_SIGNED |
- SMB2_HDR_FLAG_DFS;
- if (opcode == SMB2_OP_CANCEL) {
- allowed_flags |= SMB2_HDR_FLAG_ASYNC;
- }
- if ((flags & ~allowed_flags) != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- session_status = smbd_smb2_request_check_session(req);
-
- req->do_signing = false;
- if (flags & SMB2_HDR_FLAG_SIGNED) {
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
-
- req->do_signing = true;
- status = smb2_signing_check_pdu(req->session->session_key,
- &req->in.vector[i], 3);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- } else if (req->session && req->session->do_signing) {
- return smbd_smb2_request_error(req, NT_STATUS_ACCESS_DENIED);
- }
-
- if (flags & SMB2_HDR_FLAG_CHAINED) {
- /*
- * This check is mostly for giving the correct error code
- * for compounded requests.
- *
- * TODO: we may need to move this after the session
- * and tcon checks.
- */
- if (!NT_STATUS_IS_OK(req->next_status)) {
- return smbd_smb2_request_error(req, req->next_status);
- }
- } else {
- req->compat_chain_fsp = NULL;
- }
-
- switch (opcode) {
- case SMB2_OP_NEGPROT:
- return smbd_smb2_request_process_negprot(req);
-
- case SMB2_OP_SESSSETUP:
- return smbd_smb2_request_process_sesssetup(req);
-
- case SMB2_OP_LOGOFF:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- return smbd_smb2_request_process_logoff(req);
-
- case SMB2_OP_TCON:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_session(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_tcon(req);
-
- case SMB2_OP_TDIS:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_tdis(req);
-
- case SMB2_OP_CREATE:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_create(req);
-
- case SMB2_OP_CLOSE:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_close(req);
-
- case SMB2_OP_FLUSH:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_flush(req);
-
- case SMB2_OP_READ:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_read(req);
-
- case SMB2_OP_WRITE:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_write(req);
-
- case SMB2_OP_LOCK:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_lock(req);
-
- case SMB2_OP_IOCTL:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_ioctl(req);
-
- case SMB2_OP_CANCEL:
- return smbd_smb2_request_process_cancel(req);
-
- case SMB2_OP_KEEPALIVE:
- return smbd_smb2_request_process_keepalive(req);
-
- case SMB2_OP_FIND:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_find(req);
-
- case SMB2_OP_NOTIFY:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_notify(req);
-
- case SMB2_OP_GETINFO:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_getinfo(req);
-
- case SMB2_OP_SETINFO:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_setinfo(req);
-
- case SMB2_OP_BREAK:
- if (!NT_STATUS_IS_OK(session_status)) {
- return smbd_smb2_request_error(req, session_status);
- }
- status = smbd_smb2_request_check_tcon(req);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
- return smbd_smb2_request_process_break(req);
- }
-
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
-}
-
-static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq);
-static void smbd_smb2_request_writev_done(struct tevent_req *subreq);
-
-static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
-{
- struct tevent_req *subreq;
-
- req->subreq = NULL;
-
- smb2_setup_nbt_length(req->out.vector, req->out.vector_count);
-
- if (req->do_signing) {
- int i = req->current_idx;
- NTSTATUS status;
- status = smb2_signing_sign_pdu(req->session->session_key,
- &req->out.vector[i], 3);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
- req->current_idx += 3;
-
- if (req->current_idx < req->out.vector_count) {
- struct timeval zero = timeval_zero();
- subreq = tevent_wakeup_send(req,
- req->sconn->smb2.event_ctx,
- zero);
- if (subreq == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_request_dispatch_compound,
- req);
-
- return NT_STATUS_OK;
- }
-
- subreq = tstream_writev_queue_send(req,
- req->sconn->smb2.event_ctx,
- req->sconn->smb2.stream,
- req->sconn->smb2.send_queue,
- req->out.vector,
- req->out.vector_count);
- if (subreq == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_writev_done, req);
-
- return NT_STATUS_OK;
-}
-
-static void smbd_smb2_request_dispatch_compound(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- struct smbd_server_connection *sconn = req->sconn;
- NTSTATUS status;
-
- tevent_wakeup_recv(subreq);
- TALLOC_FREE(subreq);
-
- DEBUG(10,("smbd_smb2_request_dispatch_compound: idx[%d] of %d vectors\n",
- req->current_idx, req->in.vector_count));
-
- status = smbd_smb2_request_dispatch(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-}
-
-static void smbd_smb2_request_writev_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- struct smbd_server_connection *sconn = req->sconn;
- int ret;
- int sys_errno;
-
- ret = tstream_writev_queue_recv(subreq, &sys_errno);
- TALLOC_FREE(subreq);
- TALLOC_FREE(req);
- if (ret == -1) {
- NTSTATUS status = map_nt_error_from_unix(sys_errno);
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-}
-
-NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req,
- NTSTATUS status,
- DATA_BLOB *info,
- const char *location)
-{
- uint8_t *outhdr;
- uint8_t *outbody;
- int i = req->current_idx;
-
- DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n",
- i, nt_errstr(status), info ? " +info" : "",
- location));
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
-
- outbody = outhdr + SMB2_HDR_BODY;
-
- req->out.vector[i+1].iov_base = (void *)outbody;
- req->out.vector[i+1].iov_len = 8;
-
- if (info) {
- SIVAL(outbody, 0x04, info->length);
- req->out.vector[i+2].iov_base = (void *)info->data;
- req->out.vector[i+2].iov_len = info->length;
- } else {
- req->out.vector[i+2].iov_base = NULL;
- req->out.vector[i+2].iov_len = 0;
- }
-
- /*
- * if a request fails, all other remaining
- * compounded requests should fail too
- */
- req->next_status = NT_STATUS_INVALID_PARAMETER;
-
- return smbd_smb2_request_reply(req);
-}
-
-NTSTATUS smbd_smb2_request_done_ex(struct smbd_smb2_request *req,
- NTSTATUS status,
- DATA_BLOB body, DATA_BLOB *dyn,
- const char *location)
-{
- uint8_t *outhdr;
- uint8_t *outdyn;
- int i = req->current_idx;
- uint32_t next_command_ofs;
-
- DEBUG(10,("smbd_smb2_request_done_ex: "
- "idx[%d] status[%s] body[%u] dyn[%s:%u] at %s\n",
- i, nt_errstr(status), (unsigned int)body.length,
- dyn ? "yes": "no",
- (unsigned int)(dyn ? dyn->length : 0),
- location));
-
- if (body.length < 2) {
- return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
- }
-
- if ((body.length % 2) != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_INTERNAL_ERROR);
- }
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
- /* the fallback dynamic buffer */
- outdyn = outhdr + SMB2_HDR_BODY + 8;
-
- next_command_ofs = IVAL(outhdr, SMB2_HDR_NEXT_COMMAND);
- SIVAL(outhdr, SMB2_HDR_STATUS, NT_STATUS_V(status));
-
- req->out.vector[i+1].iov_base = (void *)body.data;
- req->out.vector[i+1].iov_len = body.length;
-
- if (dyn) {
- req->out.vector[i+2].iov_base = (void *)dyn->data;
- req->out.vector[i+2].iov_len = dyn->length;
- } else {
- req->out.vector[i+2].iov_base = NULL;
- req->out.vector[i+2].iov_len = 0;
- }
-
- /* see if we need to recalculate the offset to the next response */
- if (next_command_ofs > 0) {
- next_command_ofs = SMB2_HDR_BODY;
- next_command_ofs += req->out.vector[i+1].iov_len;
- next_command_ofs += req->out.vector[i+2].iov_len;
- }
-
- if ((next_command_ofs % 8) != 0) {
- size_t pad_size = 8 - (next_command_ofs % 8);
- if (req->out.vector[i+2].iov_len == 0) {
- /*
- * if the dyn buffer is empty
- * we can use it to add padding
- */
- uint8_t *pad;
-
- pad = talloc_zero_array(req->out.vector,
- uint8_t, pad_size);
- if (pad == NULL) {
- return smbd_smb2_request_error(req,
- NT_STATUS_NO_MEMORY);
- }
-
- req->out.vector[i+2].iov_base = (void *)pad;
- req->out.vector[i+2].iov_len = pad_size;
- } else {
- /*
- * For now we copy the dynamic buffer
- * and add the padding to the new buffer
- */
- size_t old_size;
- uint8_t *old_dyn;
- size_t new_size;
- uint8_t *new_dyn;
-
- old_size = req->out.vector[i+2].iov_len;
- old_dyn = (uint8_t *)req->out.vector[i+2].iov_base;
-
- new_size = old_size + pad_size;
- new_dyn = talloc_array(req->out.vector,
- uint8_t, new_size);
- if (new_dyn == NULL) {
- return smbd_smb2_request_error(req,
- NT_STATUS_NO_MEMORY);
- }
-
- memcpy(new_dyn, old_dyn, old_size);
- memset(new_dyn + old_size, 0, pad_size);
-
- req->out.vector[i+2].iov_base = (void *)new_dyn;
- req->out.vector[i+2].iov_len = new_size;
-
- TALLOC_FREE(old_dyn);
- }
- next_command_ofs += pad_size;
- }
-
- SIVAL(outhdr, SMB2_HDR_NEXT_COMMAND, next_command_ofs);
-
- return smbd_smb2_request_reply(req);
-}
-
-struct smbd_smb2_send_oplock_break_state {
- struct smbd_server_connection *sconn;
- uint8_t buf[4 + SMB2_HDR_BODY + 0x18];
- struct iovec vector;
-};
-
-static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq);
-
-NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn,
- uint64_t file_id_persistent,
- uint64_t file_id_volatile,
- uint8_t oplock_level)
-{
- struct smbd_smb2_send_oplock_break_state *state;
- struct tevent_req *subreq;
- uint8_t *hdr;
- uint8_t *body;
-
- state = talloc(sconn, struct smbd_smb2_send_oplock_break_state);
- if (state == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- state->sconn = sconn;
-
- state->vector.iov_base = (void *)state->buf;
- state->vector.iov_len = sizeof(state->buf);
-
- _smb2_setlen(state->buf, sizeof(state->buf) - 4);
- hdr = state->buf + 4;
- body = hdr + SMB2_HDR_BODY;
-
- SIVAL(hdr, 0, SMB2_MAGIC);
- SSVAL(hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY);
- SSVAL(hdr, SMB2_HDR_EPOCH, 0);
- SIVAL(hdr, SMB2_HDR_STATUS, 0);
- SSVAL(hdr, SMB2_HDR_OPCODE, SMB2_OP_BREAK);
- SSVAL(hdr, SMB2_HDR_CREDIT, 0);
- SIVAL(hdr, SMB2_HDR_FLAGS, SMB2_HDR_FLAG_REDIRECT);
- SIVAL(hdr, SMB2_HDR_NEXT_COMMAND, 0);
- SBVAL(hdr, SMB2_HDR_MESSAGE_ID, UINT64_MAX);
- SIVAL(hdr, SMB2_HDR_PID, 0);
- SIVAL(hdr, SMB2_HDR_TID, 0);
- SBVAL(hdr, SMB2_HDR_SESSION_ID, 0);
- memset(hdr+SMB2_HDR_SIGNATURE, 0, 16);
-
- SSVAL(body, 0x00, 0x18);
-
- SCVAL(body, 0x02, oplock_level);
- SCVAL(body, 0x03, 0); /* reserved */
- SIVAL(body, 0x04, 0); /* reserved */
- SBVAL(body, 0x08, file_id_persistent);
- SBVAL(body, 0x10, file_id_volatile);
-
- subreq = tstream_writev_queue_send(state,
- sconn->smb2.event_ctx,
- sconn->smb2.stream,
- sconn->smb2.send_queue,
- &state->vector, 1);
- if (subreq == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_oplock_break_writev_done,
- state);
-
- return NT_STATUS_OK;
-}
-
-static void smbd_smb2_oplock_break_writev_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_send_oplock_break_state *state =
- tevent_req_callback_data(subreq,
- struct smbd_smb2_send_oplock_break_state);
- struct smbd_server_connection *sconn = state->sconn;
- int ret;
- int sys_errno;
-
- ret = tstream_writev_queue_recv(subreq, &sys_errno);
- TALLOC_FREE(subreq);
- if (ret == -1) {
- NTSTATUS status = map_nt_error_from_unix(sys_errno);
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- TALLOC_FREE(state);
-}
-
-struct smbd_smb2_request_read_state {
- size_t missing;
- bool asked_for_header;
- struct smbd_smb2_request *smb2_req;
-};
-
-static int smbd_smb2_request_next_vector(struct tstream_context *stream,
- void *private_data,
- TALLOC_CTX *mem_ctx,
- struct iovec **_vector,
- size_t *_count);
-static void smbd_smb2_request_read_done(struct tevent_req *subreq);
-
-static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_server_connection *sconn)
-{
- struct tevent_req *req;
- struct smbd_smb2_request_read_state *state;
- struct tevent_req *subreq;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_request_read_state);
- if (req == NULL) {
- return NULL;
- }
- state->missing = 0;
- state->asked_for_header = false;
-
- state->smb2_req = smbd_smb2_request_allocate(state);
- if (tevent_req_nomem(state->smb2_req, req)) {
- return tevent_req_post(req, ev);
- }
- state->smb2_req->sconn = sconn;
-
- subreq = tstream_readv_pdu_queue_send(state, ev, sconn->smb2.stream,
- sconn->smb2.recv_queue,
- smbd_smb2_request_next_vector,
- state);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_read_done, req);
-
- return req;
-}
-
-static int smbd_smb2_request_next_vector(struct tstream_context *stream,
- void *private_data,
- TALLOC_CTX *mem_ctx,
- struct iovec **_vector,
- size_t *_count)
-{
- struct smbd_smb2_request_read_state *state =
- talloc_get_type_abort(private_data,
- struct smbd_smb2_request_read_state);
- struct smbd_smb2_request *req = state->smb2_req;
- struct iovec *vector;
- int idx = req->in.vector_count;
- size_t len = 0;
- uint8_t *buf = NULL;
-
- if (req->in.vector_count == 0) {
- /*
- * first we need to get the NBT header
- */
- req->in.vector = talloc_array(req, struct iovec,
- req->in.vector_count + 1);
- if (req->in.vector == NULL) {
- return -1;
- }
- req->in.vector_count += 1;
-
- req->in.vector[idx].iov_base = (void *)req->in.nbt_hdr;
- req->in.vector[idx].iov_len = 4;
-
- vector = talloc_array(mem_ctx, struct iovec, 1);
- if (vector == NULL) {
- return -1;
- }
-
- vector[0] = req->in.vector[idx];
-
- *_vector = vector;
- *_count = 1;
- return 0;
- }
-
- if (req->in.vector_count == 1) {
- /*
- * Now we analyze the NBT header
- */
- state->missing = smb2_len(req->in.vector[0].iov_base);
-
- if (state->missing == 0) {
- /* if there're no remaining bytes, we're done */
- *_vector = NULL;
- *_count = 0;
- return 0;
- }
-
- req->in.vector = talloc_realloc(req, req->in.vector,
- struct iovec,
- req->in.vector_count + 1);
- if (req->in.vector == NULL) {
- return -1;
- }
- req->in.vector_count += 1;
-
- if (CVAL(req->in.vector[0].iov_base, 0) != 0) {
- /*
- * it's a special NBT message,
- * so get all remaining bytes
- */
- len = state->missing;
- } else if (state->missing < (SMB2_HDR_BODY + 2)) {
- /*
- * it's an invalid message, just read what we can get
- * and let the caller handle the error
- */
- len = state->missing;
- } else {
- /*
- * We assume it's a SMB2 request,
- * and we first get the header and the
- * first 2 bytes (the struct size) of the body
- */
- len = SMB2_HDR_BODY + 2;
-
- state->asked_for_header = true;
- }
-
- state->missing -= len;
-
- buf = talloc_array(req->in.vector, uint8_t, len);
- if (buf == NULL) {
- return -1;
- }
-
- req->in.vector[idx].iov_base = (void *)buf;
- req->in.vector[idx].iov_len = len;
-
- vector = talloc_array(mem_ctx, struct iovec, 1);
- if (vector == NULL) {
- return -1;
- }
-
- vector[0] = req->in.vector[idx];
-
- *_vector = vector;
- *_count = 1;
- return 0;
- }
-
- if (state->missing == 0) {
- /* if there're no remaining bytes, we're done */
- *_vector = NULL;
- *_count = 0;
- return 0;
- }
-
- if (state->asked_for_header) {
- const uint8_t *hdr;
- size_t full_size;
- size_t next_command_ofs;
- size_t body_size;
- uint8_t *body;
- size_t dyn_size;
- uint8_t *dyn;
- bool invalid = false;
-
- state->asked_for_header = false;
-
- /*
- * We got the SMB2 header and the first 2 bytes
- * of the body. We fix the size to just the header
- * and manually copy the 2 first bytes to the body section
- */
- req->in.vector[idx-1].iov_len = SMB2_HDR_BODY;
- hdr = (const uint8_t *)req->in.vector[idx-1].iov_base;
-
- /* allocate vectors for body and dynamic areas */
- req->in.vector = talloc_realloc(req, req->in.vector,
- struct iovec,
- req->in.vector_count + 2);
- if (req->in.vector == NULL) {
- return -1;
- }
- req->in.vector_count += 2;
-
- full_size = state->missing + SMB2_HDR_BODY + 2;
- next_command_ofs = IVAL(hdr, SMB2_HDR_NEXT_COMMAND);
- body_size = SVAL(hdr, SMB2_HDR_BODY);
-
- if (next_command_ofs != 0) {
- if (next_command_ofs < (SMB2_HDR_BODY + 2)) {
- /*
- * this is invalid, just return a zero
- * body and let the caller deal with the error
- */
- invalid = true;
- } else if (next_command_ofs > full_size) {
- /*
- * this is invalid, just return a zero
- * body and let the caller deal with the error
- */
- invalid = true;
- } else {
- full_size = next_command_ofs;
- }
- }
-
- if (!invalid) {
- if (body_size < 2) {
- /*
- * this is invalid, just return a zero
- * body and let the caller deal with the error
- */
- invalid = true;
- }
-
- if ((body_size % 2) != 0) {
- body_size -= 1;
- }
-
- if (body_size > (full_size - SMB2_HDR_BODY)) {
- /*
- * this is invalid, just return a zero
- * body and let the caller deal with the error
- */
- invalid = true;
- }
- }
-
- if (invalid) {
- /* the caller should check this */
- body_size = 2;
- }
-
- dyn_size = full_size - (SMB2_HDR_BODY + body_size);
-
- state->missing -= (body_size - 2) + dyn_size;
-
- body = talloc_array(req->in.vector, uint8_t, body_size);
- if (body == NULL) {
- return -1;
- }
-
- dyn = talloc_array(req->in.vector, uint8_t, dyn_size);
- if (dyn == NULL) {
- return -1;
- }
-
- req->in.vector[idx].iov_base = (void *)body;
- req->in.vector[idx].iov_len = body_size;
- req->in.vector[idx+1].iov_base = (void *)dyn;
- req->in.vector[idx+1].iov_len = dyn_size;
-
- vector = talloc_array(mem_ctx, struct iovec, 2);
- if (vector == NULL) {
- return -1;
- }
-
- /*
- * the first 2 bytes of the body were already fetched
- * together with the header
- */
- memcpy(body, hdr + SMB2_HDR_BODY, 2);
- vector[0].iov_base = body + 2;
- vector[0].iov_len = body_size - 2;
-
- vector[1] = req->in.vector[idx+1];
-
- *_vector = vector;
- *_count = 2;
- return 0;
- }
-
- /*
- * when we endup here, we're looking for a new SMB2 request
- * next. And we ask for its header and the first 2 bytes of
- * the body (like we did for the first SMB2 request).
- */
-
- req->in.vector = talloc_realloc(req, req->in.vector,
- struct iovec,
- req->in.vector_count + 1);
- if (req->in.vector == NULL) {
- return -1;
- }
- req->in.vector_count += 1;
-
- /*
- * We assume it's a SMB2 request,
- * and we first get the header and the
- * first 2 bytes (the struct size) of the body
- */
- len = SMB2_HDR_BODY + 2;
-
- if (len > state->missing) {
- /* let the caller handle the error */
- len = state->missing;
- }
-
- state->missing -= len;
- state->asked_for_header = true;
-
- buf = talloc_array(req->in.vector, uint8_t, len);
- if (buf == NULL) {
- return -1;
- }
-
- req->in.vector[idx].iov_base = (void *)buf;
- req->in.vector[idx].iov_len = len;
-
- vector = talloc_array(mem_ctx, struct iovec, 1);
- if (vector == NULL) {
- return -1;
- }
-
- vector[0] = req->in.vector[idx];
-
- *_vector = vector;
- *_count = 1;
- return 0;
-}
-
-static void smbd_smb2_request_read_done(struct tevent_req *subreq)
-{
- struct tevent_req *req =
- tevent_req_callback_data(subreq,
- struct tevent_req);
- int ret;
- int sys_errno;
- NTSTATUS status;
-
- ret = tstream_readv_pdu_queue_recv(subreq, &sys_errno);
- if (ret == -1) {
- status = map_nt_error_from_unix(sys_errno);
- tevent_req_nterror(req, status);
- return;
- }
-
- tevent_req_done(req);
-}
-
-static NTSTATUS smbd_smb2_request_read_recv(struct tevent_req *req,
- TALLOC_CTX *mem_ctx,
- struct smbd_smb2_request **_smb2_req)
-{
- struct smbd_smb2_request_read_state *state =
- tevent_req_data(req,
- struct smbd_smb2_request_read_state);
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- talloc_steal(mem_ctx, state->smb2_req->mem_pool);
- *_smb2_req = state->smb2_req;
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
-
-static void smbd_smb2_request_incoming(struct tevent_req *subreq);
-
-void smbd_smb2_first_negprot(struct smbd_server_connection *sconn,
- const uint8_t *inbuf, size_t size)
-{
- NTSTATUS status;
- struct smbd_smb2_request *req;
- struct tevent_req *subreq;
-
- DEBUG(10,("smbd_smb2_first_negprot: packet length %u\n",
- (unsigned int)size));
-
- status = smbd_initialize_smb2(sconn);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- status = smbd_smb2_request_create(sconn, inbuf, size, &req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- status = smbd_smb2_request_setup_out(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- status = smbd_smb2_request_dispatch(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- /* ask for the next request */
- subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
- if (subreq == NULL) {
- smbd_server_connection_terminate(sconn, "no memory for reading");
- return;
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
-}
-
-static void smbd_smb2_request_incoming(struct tevent_req *subreq)
-{
- struct smbd_server_connection *sconn = tevent_req_callback_data(subreq,
- struct smbd_server_connection);
- NTSTATUS status;
- struct smbd_smb2_request *req = NULL;
-
- status = smbd_smb2_request_read_recv(subreq, sconn, &req);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- if (req->in.nbt_hdr[0] != 0x00) {
- DEBUG(1,("smbd_smb2_request_incoming: ignore NBT[0x%02X] msg\n",
- req->in.nbt_hdr[0]));
- TALLOC_FREE(req);
- goto next;
- }
-
- req->current_idx = 1;
-
- DEBUG(10,("smbd_smb2_request_incoming: idx[%d] of %d vectors\n",
- req->current_idx, req->in.vector_count));
-
- status = smbd_smb2_request_validate(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- status = smbd_smb2_request_setup_out(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
- status = smbd_smb2_request_dispatch(req);
- if (!NT_STATUS_IS_OK(status)) {
- smbd_server_connection_terminate(sconn, nt_errstr(status));
- return;
- }
-
-next:
- /* ask for the next request (this constructs the main loop) */
- subreq = smbd_smb2_request_read_send(sconn, sconn->smb2.event_ctx, sconn);
- if (subreq == NULL) {
- smbd_server_connection_terminate(sconn, "no memory for reading");
- return;
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_incoming, sconn);
-}
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
deleted file mode 100644
index dc24124b54..0000000000
--- a/source3/smbd/smb2_sesssetup.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-#include "../libcli/auth/spnego.h"
-
-static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
- uint64_t in_session_id,
- uint8_t in_security_mode,
- DATA_BLOB in_security_buffer,
- uint16_t *out_session_flags,
- DATA_BLOB *out_security_buffer,
- uint64_t *out_session_id);
-
-NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- size_t expected_body_size = 0x19;
- size_t body_size;
- uint64_t in_session_id;
- uint8_t in_security_mode;
- uint16_t in_security_offset;
- uint16_t in_security_length;
- DATA_BLOB in_security_buffer;
- uint16_t out_session_flags;
- uint64_t out_session_id;
- uint16_t out_security_offset;
- DATA_BLOB out_security_buffer;
- NTSTATUS status;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_security_offset = SVAL(inbody, 0x0C);
- in_security_length = SVAL(inbody, 0x0E);
-
- if (in_security_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_security_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
- in_security_mode = CVAL(inbody, 0x03);
- in_security_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_security_buffer.length = in_security_length;
-
- status = smbd_smb2_session_setup(req,
- in_session_id,
- in_security_mode,
- in_security_buffer,
- &out_session_flags,
- &out_security_buffer,
- &out_session_id);
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- status = nt_status_squash(status);
- return smbd_smb2_request_error(req, status);
- }
-
- out_security_offset = SMB2_HDR_BODY + 0x08;
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x08);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
-
- SSVAL(outbody.data, 0x00, 0x08 + 1); /* struct size */
- SSVAL(outbody.data, 0x02,
- out_session_flags); /* session flags */
- SSVAL(outbody.data, 0x04,
- out_security_offset); /* security buffer offset */
- SSVAL(outbody.data, 0x06,
- out_security_buffer.length); /* security buffer length */
-
- outdyn = out_security_buffer;
-
- return smbd_smb2_request_done_ex(req, status, outbody, &outdyn,
- __location__);
-}
-
-static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
-{
- if (session->sconn == NULL) {
- return 0;
- }
-
- /* first free all tcons */
- while (session->tcons.list) {
- talloc_free(session->tcons.list);
- }
-
- idr_remove(session->sconn->smb2.sessions.idtree, session->vuid);
- DLIST_REMOVE(session->sconn->smb2.sessions.list, session);
- invalidate_vuid(session->sconn, session->vuid);
-
- session->vuid = 0;
- session->status = NT_STATUS_USER_SESSION_DELETED;
- session->sconn = NULL;
-
- return 0;
-}
-
-static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
- uint64_t in_session_id,
- uint8_t in_security_mode,
- DATA_BLOB in_security_buffer,
- uint16_t *out_session_flags,
- DATA_BLOB *out_security_buffer,
- uint64_t *out_session_id)
-{
- struct smbd_smb2_session *session;
- NTSTATUS status;
-
- *out_session_flags = 0;
- *out_session_id = 0;
-
- if (in_session_id == 0) {
- int id;
-
- /* create a new session */
- session = talloc_zero(req->sconn, struct smbd_smb2_session);
- if (session == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
- id = idr_get_new_random(req->sconn->smb2.sessions.idtree,
- session,
- req->sconn->smb2.sessions.limit);
- if (id == -1) {
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
- session->vuid = id;
-
- session->tcons.idtree = idr_init(session);
- if (session->tcons.idtree == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- session->tcons.limit = 0x0000FFFE;
- session->tcons.list = NULL;
-
- DLIST_ADD_END(req->sconn->smb2.sessions.list, session,
- struct smbd_smb2_session *);
- session->sconn = req->sconn;
- talloc_set_destructor(session, smbd_smb2_session_destructor);
- } else {
- void *p;
-
- /* lookup an existing session */
- p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
- if (p == NULL) {
- return NT_STATUS_USER_SESSION_DELETED;
- }
- session = talloc_get_type_abort(p, struct smbd_smb2_session);
- }
-
- if (NT_STATUS_IS_OK(session->status)) {
- return NT_STATUS_REQUEST_NOT_ACCEPTED;
- }
-
- if (session->auth_ntlmssp_state == NULL) {
- status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(session);
- return status;
- }
- }
-
- if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
- DATA_BLOB secblob_in;
- DATA_BLOB chal_out;
- char *kerb_mech = NULL;
-
- status = parse_spnego_mechanisms(in_security_buffer,
- &secblob_in, &kerb_mech);
- if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(session);
- return nt_status_squash(status);
- }
-
- /* For now, just SPNEGO NTLMSSP - krb5 goes here later.. */
- status = auth_ntlmssp_update(session->auth_ntlmssp_state,
- secblob_in,
- &chal_out);
-
- if (!NT_STATUS_IS_OK(status) &&
- !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- auth_ntlmssp_end(&session->auth_ntlmssp_state);
- TALLOC_FREE(session);
- return nt_status_squash(status);
- }
-
- *out_security_buffer = spnego_gen_auth_response(&chal_out,
- status, OID_NTLMSSP);
-
- *out_session_id = session->vuid;
- return status;
- } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
- DATA_BLOB auth = data_blob_null;
- DATA_BLOB auth_out = data_blob_null;
-
- /* its an auth packet */
- if (!spnego_parse_auth(in_security_buffer, &auth)) {
- TALLOC_FREE(session);
- return NT_STATUS_LOGON_FAILURE;
- }
- /* For now, just SPNEGO NTLMSSP - krb5 goes here later.. */
- status = auth_ntlmssp_update(session->auth_ntlmssp_state,
- auth,
- &auth_out);
- if (!NT_STATUS_IS_OK(status)) {
- auth_ntlmssp_end(&session->auth_ntlmssp_state);
- TALLOC_FREE(session);
- return nt_status_squash(status);
- }
-
- *out_security_buffer = spnego_gen_auth_response(&auth_out,
- status, NULL);
-
- *out_session_id = session->vuid;
- } else if (strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
-
- /* RAW NTLMSSP */
- status = auth_ntlmssp_update(session->auth_ntlmssp_state,
- in_security_buffer,
- out_security_buffer);
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- *out_session_id = session->vuid;
- return status;
- }
- if (!NT_STATUS_IS_OK(status)) {
- auth_ntlmssp_end(&session->auth_ntlmssp_state);
- TALLOC_FREE(session);
- return nt_status_squash(status);
- }
- *out_session_id = session->vuid;
- }
-
- /* TODO: setup session key for signing */
-
- if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
- lp_server_signing() == Required) {
- session->do_signing = true;
- }
-
- if (session->auth_ntlmssp_state->server_info->guest) {
- /* we map anonymous to guest internally */
- *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
- *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
- /* force no signing */
- session->do_signing = false;
- }
-
- session->server_info = session->auth_ntlmssp_state->server_info;
- data_blob_free(&session->server_info->user_session_key);
- session->server_info->user_session_key =
- data_blob_talloc(
- session->server_info,
- session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
- session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
- if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
- if (session->server_info->user_session_key.data == NULL) {
- TALLOC_FREE(session);
- return NT_STATUS_NO_MEMORY;
- }
- }
- session->session_key = session->server_info->user_session_key;
-
- session->compat_vuser = talloc_zero(session, user_struct);
- if (session->compat_vuser == NULL) {
- TALLOC_FREE(session);
- return NT_STATUS_NO_MEMORY;
- }
- session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
- session->compat_vuser->homes_snum = -1;
- session->compat_vuser->server_info = session->server_info;
- session->compat_vuser->session_keystr = NULL;
- session->compat_vuser->vuid = session->vuid;
- DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
-
- session->status = NT_STATUS_OK;
-
- /*
- * we attach the session to the request
- * so that the response can be signed
- */
- req->session = session;
- if (session->do_signing) {
- req->do_signing = true;
- }
-
- *out_session_id = session->vuid;
- return status;
-}
-
-NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- int i = req->current_idx;
- uint64_t in_session_id;
- void *p;
- struct smbd_smb2_session *session;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
-
- in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
-
- /* lookup an existing session */
- p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
- if (p == NULL) {
- return NT_STATUS_USER_SESSION_DELETED;
- }
- session = talloc_get_type_abort(p, struct smbd_smb2_session);
-
- if (!NT_STATUS_IS_OK(session->status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- set_current_user_info(session->server_info->sanitized_username,
- session->server_info->unix_name,
- pdb_get_domain(session->server_info->sam_account));
-
- req->session = session;
- return NT_STATUS_OK;
-}
-
-NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- int i = req->current_idx;
- DATA_BLOB outbody;
- size_t expected_body_size = 0x04;
- size_t body_size;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- /*
- * TODO: cancel all outstanding requests on the session
- * and delete all tree connections.
- */
- smbd_smb2_session_destructor(req->session);
- /*
- * we may need to sign the response, so we need to keep
- * the session until the response is sent to the wire.
- */
- talloc_steal(req, req->session);
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x04); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
-
- return smbd_smb2_request_done(req, outbody, NULL);
-}
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
deleted file mode 100644
index f3e3fc964f..0000000000
--- a/source3/smbd/smb2_setinfo.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_info_type,
- uint8_t in_file_info_class,
- DATA_BLOB in_input_buffer,
- uint32_t in_additional_information,
- uint64_t in_file_id_volatile);
-static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req);
-
-static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x21;
- size_t body_size;
- uint8_t in_info_type;
- uint8_t in_file_info_class;
- uint16_t in_input_buffer_offset;
- uint32_t in_input_buffer_length;
- DATA_BLOB in_input_buffer;
- uint32_t in_additional_information;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_info_type = CVAL(inbody, 0x02);
- in_file_info_class = CVAL(inbody, 0x03);
- in_input_buffer_length = IVAL(inbody, 0x04);
- in_input_buffer_offset = SVAL(inbody, 0x08);
- /* 0x0A 2 bytes reserved */
- in_additional_information = IVAL(inbody, 0x0C);
- in_file_id_persistent = BVAL(inbody, 0x10);
- in_file_id_volatile = BVAL(inbody, 0x18);
-
- if (in_input_buffer_offset == 0 && in_input_buffer_length == 0) {
- /* This is ok */
- } else if (in_input_buffer_offset !=
- (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_input_buffer_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_input_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_input_buffer.length = in_input_buffer_length;
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_setinfo_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_info_type,
- in_file_info_class,
- in_input_buffer,
- in_additional_information,
- in_file_id_volatile);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_setinfo_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_setinfo_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- DATA_BLOB outbody;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_setinfo_recv(subreq);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x02);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x02); /* struct size */
-
- error = smbd_smb2_request_done(req, outbody, NULL);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_setinfo_state {
- struct smbd_smb2_request *smb2req;
-};
-
-static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint8_t in_info_type,
- uint8_t in_file_info_class,
- DATA_BLOB in_input_buffer,
- uint32_t in_additional_information,
- uint64_t in_file_id_volatile)
-{
- struct tevent_req *req;
- struct smbd_smb2_setinfo_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_setinfo_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
-
- DEBUG(10,("smbd_smb2_setinfo_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(conn)) {
- tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
- return tevent_req_post(req, ev);
- }
-
- switch (in_info_type) {
- case 0x01:/* SMB2_SETINFO_FILE */
- {
- uint16_t file_info_level;
- char *data;
- int data_size;
- int ret_size = 0;
- NTSTATUS status;
-
-
- file_info_level = in_file_info_class + 1000;
- if (file_info_level == SMB_FILE_RENAME_INFORMATION) {
- file_info_level = 0xFF00 + in_file_info_class;
- }
-
- if (fsp->is_directory || fsp->fh->fd == -1) {
- /*
- * This is actually a SETFILEINFO on a directory
- * handle (returned from an NT SMB). NT5.0 seems
- * to do this call. JRA.
- */
- if (INFO_LEVEL_IS_UNIX(file_info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, fsp->fsp_name)) {
- DEBUG(3,("smbd_smb2_setinfo_send: "
- "SMB_VFS_LSTAT of %s failed "
- "(%s)\n", fsp_str_dbg(fsp),
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- } else {
- if (SMB_VFS_STAT(conn, fsp->fsp_name) != 0) {
- DEBUG(3,("smbd_smb2_setinfo_send: "
- "fileinfo of %s failed (%s)\n",
- fsp_str_dbg(fsp),
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
- } else if (fsp->print_file) {
- /*
- * Doing a DELETE_ON_CLOSE should cancel a print job.
- */
- if ((file_info_level == SMB_SET_FILE_DISPOSITION_INFO)
- && in_input_buffer.length >= 1
- && CVAL(in_input_buffer.data,0)) {
- fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
-
- DEBUG(3,("smbd_smb2_setinfo_send: "
- "Cancelling print job (%s)\n",
- fsp_str_dbg(fsp)));
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
- } else {
- tevent_req_nterror(req,
- NT_STATUS_OBJECT_PATH_INVALID);
- return tevent_req_post(req, ev);
- }
- } else {
- /*
- * Original code - this is an open file.
- */
-
- if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
- DEBUG(3,("smbd_smb2_setinfo_send: fstat "
- "of fnum %d failed (%s)\n", fsp->fnum,
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- }
-
- data = NULL;
- data_size = in_input_buffer.length;
- if (data_size > 0) {
- data = (char *)SMB_MALLOC_ARRAY(char, data_size);
- if (tevent_req_nomem(data, req)) {
-
- }
- memcpy(data, in_input_buffer.data, data_size);
- }
-
- status = smbd_do_setfilepathinfo(conn, smbreq, state,
- file_info_level,
- fsp,
- fsp->fsp_name,
- &data,
- data_size,
- &ret_size);
- SAFE_FREE(data);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) {
- status = NT_STATUS_INVALID_INFO_CLASS;
- }
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
- break;
- }
-
- default:
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static NTSTATUS smbd_smb2_setinfo_recv(struct tevent_req *req)
-{
- NTSTATUS status;
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_signing.c b/source3/smbd/smb2_signing.c
deleted file mode 100644
index a7d2605318..0000000000
--- a/source3/smbd/smb2_signing.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB2 signing
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-#include "../lib/crypto/crypto.h"
-
-NTSTATUS smb2_signing_sign_pdu(DATA_BLOB session_key,
- struct iovec *vector,
- int count)
-{
- uint8_t *hdr;
- uint64_t session_id;
- struct HMACSHA256Context m;
- uint8_t res[SHA256_DIGEST_LENGTH];
- int i;
-
- if (count < 2) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (vector[0].iov_len != SMB2_HDR_BODY) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- hdr = (uint8_t *)vector[0].iov_base;
-
- session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
- if (session_id == 0) {
- /*
- * do not sign messages with a zero session_id.
- * See MS-SMB2 3.2.4.1.1
- */
- return NT_STATUS_OK;
- }
-
- if (session_key.length == 0) {
- DEBUG(2,("Wrong session key length %u for SMB2 signing\n",
- (unsigned)session_key.length));
- return NT_STATUS_ACCESS_DENIED;
- }
-
- memset(hdr + SMB2_HDR_SIGNATURE, 0, 16);
-
- SIVAL(hdr, SMB2_HDR_FLAGS, IVAL(hdr, SMB2_HDR_FLAGS) | SMB2_HDR_FLAG_SIGNED);
-
- ZERO_STRUCT(m);
- hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
- for (i=0; i < count; i++) {
- hmac_sha256_update((const uint8_t *)vector[i].iov_base,
- vector[i].iov_len, &m);
- }
- hmac_sha256_final(res, &m);
- DEBUG(5,("signed SMB2 message\n"));
-
- memcpy(hdr + SMB2_HDR_SIGNATURE, res, 16);
-
- return NT_STATUS_OK;
-}
-
-NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key,
- const struct iovec *vector,
- int count)
-{
- const uint8_t *hdr;
- const uint8_t *sig;
- uint64_t session_id;
- struct HMACSHA256Context m;
- uint8_t res[SHA256_DIGEST_LENGTH];
- static const uint8_t zero_sig[16] = { 0, };
- int i;
-
- if (count < 2) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (vector[0].iov_len != SMB2_HDR_BODY) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- hdr = (const uint8_t *)vector[0].iov_base;
-
- session_id = BVAL(hdr, SMB2_HDR_SESSION_ID);
- if (session_id == 0) {
- /*
- * do not sign messages with a zero session_id.
- * See MS-SMB2 3.2.4.1.1
- */
- return NT_STATUS_OK;
- }
-
- if (session_key.length == 0) {
- /* we don't have the session key yet */
- return NT_STATUS_OK;
- }
-
- sig = hdr+SMB2_HDR_SIGNATURE;
-
- ZERO_STRUCT(m);
- hmac_sha256_init(session_key.data, MIN(session_key.length, 16), &m);
- hmac_sha256_update(hdr, SMB2_HDR_SIGNATURE, &m);
- hmac_sha256_update(zero_sig, 16, &m);
- for (i=1; i < count; i++) {
- hmac_sha256_update((const uint8_t *)vector[i].iov_base,
- vector[i].iov_len, &m);
- }
- hmac_sha256_final(res, &m);
-
- if (memcmp(res, sig, 16) != 0) {
- DEBUG(0,("Bad SMB2 signature for message\n"));
- dump_data(0, sig, 16);
- dump_data(0, res, 16);
- return NT_STATUS_ACCESS_DENIED;
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
deleted file mode 100644
index 70c5e8845e..0000000000
--- a/source3/smbd/smb2_tcon.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
- const char *in_path,
- uint8_t *out_share_type,
- uint32_t *out_share_flags,
- uint32_t *out_capabilities,
- uint32_t *out_maximal_access,
- uint32_t *out_tree_id);
-
-NTSTATUS smbd_smb2_request_process_tcon(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- size_t expected_body_size = 0x09;
- size_t body_size;
- uint16_t in_path_offset;
- uint16_t in_path_length;
- DATA_BLOB in_path_buffer;
- char *in_path_string;
- size_t in_path_string_size;
- uint8_t out_share_type;
- uint32_t out_share_flags;
- uint32_t out_capabilities;
- uint32_t out_maximal_access;
- uint32_t out_tree_id;
- NTSTATUS status;
- bool ok;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_path_offset = SVAL(inbody, 0x04);
- in_path_length = SVAL(inbody, 0x06);
-
- if (in_path_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_path_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_path_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_path_buffer.length = in_path_length;
-
- ok = convert_string_talloc(req, CH_UTF16, CH_UNIX,
- in_path_buffer.data,
- in_path_buffer.length,
- &in_path_string,
- &in_path_string_size, false);
- if (!ok) {
- return smbd_smb2_request_error(req, NT_STATUS_ILLEGAL_CHARACTER);
- }
-
- status = smbd_smb2_tree_connect(req, in_path_string,
- &out_share_type,
- &out_share_flags,
- &out_capabilities,
- &out_maximal_access,
- &out_tree_id);
- if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
- }
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SIVAL(outhdr, SMB2_HDR_TID, out_tree_id);
-
- SSVAL(outbody.data, 0x00, 0x10); /* struct size */
- SCVAL(outbody.data, 0x02,
- out_share_type); /* share type */
- SCVAL(outbody.data, 0x03, 0); /* reserved */
- SIVAL(outbody.data, 0x04,
- out_share_flags); /* share flags */
- SIVAL(outbody.data, 0x08,
- out_capabilities); /* capabilities */
- SIVAL(outbody.data, 0x0C,
- out_maximal_access); /* maximal access */
-
- return smbd_smb2_request_done(req, outbody, NULL);
-}
-
-static int smbd_smb2_tcon_destructor(struct smbd_smb2_tcon *tcon)
-{
- if (tcon->session == NULL) {
- return 0;
- }
-
- idr_remove(tcon->session->tcons.idtree, tcon->tid);
- DLIST_REMOVE(tcon->session->tcons.list, tcon);
-
- if (tcon->compat_conn) {
- conn_free(tcon->compat_conn);
- }
-
- tcon->compat_conn = NULL;
- tcon->tid = 0;
- tcon->session = NULL;
-
- return 0;
-}
-
-static NTSTATUS smbd_smb2_tree_connect(struct smbd_smb2_request *req,
- const char *in_path,
- uint8_t *out_share_type,
- uint32_t *out_share_flags,
- uint32_t *out_capabilities,
- uint32_t *out_maximal_access,
- uint32_t *out_tree_id)
-{
- const char *share = in_path;
- fstring service;
- int snum = -1;
- struct smbd_smb2_tcon *tcon;
- int id;
- NTSTATUS status;
-
- if (strncmp(share, "\\\\", 2) == 0) {
- const char *p = strchr(share+2, '\\');
- if (p) {
- share = p + 1;
- }
- }
-
- DEBUG(10,("smbd_smb2_tree_connect: path[%s] share[%s]\n",
- in_path, share));
-
- fstrcpy(service, share);
-
- strlower_m(service);
-
- snum = find_service(service);
- if (snum < 0) {
- DEBUG(3,("smbd_smb2_tree_connect: couldn't find service %s\n",
- service));
- return NT_STATUS_BAD_NETWORK_NAME;
- }
-
- /* TODO: do more things... */
-
- /* create a new tcon as child of the session */
- tcon = talloc_zero(req->session, struct smbd_smb2_tcon);
- if (tcon == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
- id = idr_get_new_random(req->session->tcons.idtree,
- tcon,
- req->session->tcons.limit);
- if (id == -1) {
- TALLOC_FREE(tcon);
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
- tcon->tid = id;
- tcon->snum = snum;
-
- DLIST_ADD_END(req->session->tcons.list, tcon,
- struct smbd_smb2_tcon *);
- tcon->session = req->session;
- talloc_set_destructor(tcon, smbd_smb2_tcon_destructor);
-
- tcon->compat_conn = make_connection_snum(req->sconn,
- snum, req->session->compat_vuser,
- data_blob_null, "???",
- &status);
- if (tcon->compat_conn == NULL) {
- TALLOC_FREE(tcon);
- return status;
- }
- tcon->compat_conn->cnum = tcon->tid;
-
- *out_share_type = 0x01;
- *out_share_flags = SMB2_SHAREFLAG_ALL;
- *out_capabilities = 0;
- *out_maximal_access = FILE_GENERIC_ALL;
-
- *out_tree_id = tcon->tid;
- return NT_STATUS_OK;
-}
-
-NTSTATUS smbd_smb2_request_check_tcon(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- int i = req->current_idx;
- uint32_t in_tid;
- void *p;
- struct smbd_smb2_tcon *tcon;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
-
- in_tid = IVAL(inhdr, SMB2_HDR_TID);
-
- /* lookup an existing session */
- p = idr_find(req->session->tcons.idtree, in_tid);
- if (p == NULL) {
- return NT_STATUS_NETWORK_NAME_DELETED;
- }
- tcon = talloc_get_type_abort(p, struct smbd_smb2_tcon);
-
- if (!change_to_user(tcon->compat_conn,req->session->vuid)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- /* should we pass FLAG_CASELESS_PATHNAMES here? */
- if (!set_current_service(tcon->compat_conn, 0, true)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- req->tcon = tcon;
- return NT_STATUS_OK;
-}
-
-NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req)
-{
- const uint8_t *inbody;
- int i = req->current_idx;
- DATA_BLOB outbody;
- size_t expected_body_size = 0x04;
- size_t body_size;
-
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- /*
- * TODO: cancel all outstanding requests on the tcon
- * and delete all file handles.
- */
- TALLOC_FREE(req->tcon);
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x04); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
-
- return smbd_smb2_request_done(req, outbody, NULL);
-}
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
deleted file mode 100644
index fa209fafc7..0000000000
--- a/source3/smbd/smb2_write.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Core SMB2 server
-
- Copyright (C) Stefan Metzmacher 2009
-
- 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 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "smbd/globals.h"
-#include "../libcli/smb/smb_common.h"
-
-static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- DATA_BLOB in_data,
- uint64_t in_offset,
- uint32_t in_flags);
-static NTSTATUS smbd_smb2_write_recv(struct tevent_req *req,
- uint32_t *out_count);
-
-static void smbd_smb2_request_write_done(struct tevent_req *subreq);
-NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
-{
- const uint8_t *inhdr;
- const uint8_t *inbody;
- int i = req->current_idx;
- size_t expected_body_size = 0x31;
- size_t body_size;
- uint32_t in_smbpid;
- uint16_t in_data_offset;
- uint32_t in_data_length;
- DATA_BLOB in_data_buffer;
- uint64_t in_offset;
- uint64_t in_file_id_persistent;
- uint64_t in_file_id_volatile;
- uint32_t in_flags;
- struct tevent_req *subreq;
-
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
-
- in_data_offset = SVAL(inbody, 0x02);
- in_data_length = IVAL(inbody, 0x04);
- in_offset = BVAL(inbody, 0x08);
- in_file_id_persistent = BVAL(inbody, 0x10);
- in_file_id_volatile = BVAL(inbody, 0x18);
- in_flags = IVAL(inbody, 0x2C);
-
- if (in_data_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- if (in_data_length > req->in.vector[i+2].iov_len) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- /* check the max write size */
- if (in_data_length > 0x00010000) {
- DEBUG(0,("here:%s: 0x%08X: 0x%08X\n",
- __location__, in_data_length, 0x00010000));
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- in_data_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
- in_data_buffer.length = in_data_length;
-
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
- subreq = smbd_smb2_write_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_smbpid,
- in_file_id_volatile,
- in_data_buffer,
- in_offset,
- in_flags);
- if (subreq == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- tevent_req_set_callback(subreq, smbd_smb2_request_write_done, req);
-
- return smbd_smb2_request_pending_queue(req, subreq);
-}
-
-static void smbd_smb2_request_write_done(struct tevent_req *subreq)
-{
- struct smbd_smb2_request *req = tevent_req_callback_data(subreq,
- struct smbd_smb2_request);
- int i = req->current_idx;
- uint8_t *outhdr;
- DATA_BLOB outbody;
- DATA_BLOB outdyn;
- uint32_t out_count = 0;
- NTSTATUS status;
- NTSTATUS error; /* transport error */
-
- status = smbd_smb2_write_recv(subreq, &out_count);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- error = smbd_smb2_request_error(req, status);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x10);
- if (outbody.data == NULL) {
- error = smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn,
- nt_errstr(error));
- return;
- }
- return;
- }
-
- SSVAL(outbody.data, 0x00, 0x10 + 1); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* reserved */
- SIVAL(outbody.data, 0x04, out_count); /* count */
- SIVAL(outbody.data, 0x08, 0); /* remaining */
- SSVAL(outbody.data, 0x0C, 0); /* write channel info offset */
- SSVAL(outbody.data, 0x0E, 0); /* write channel info length */
-
- outdyn = data_blob_const(NULL, 0);
-
- error = smbd_smb2_request_done(req, outbody, &outdyn);
- if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(req->sconn, nt_errstr(error));
- return;
- }
-}
-
-struct smbd_smb2_write_state {
- struct smbd_smb2_request *smb2req;
- uint32_t in_length;
- uint32_t out_count;
-};
-
-static void smbd_smb2_write_pipe_done(struct tevent_req *subreq);
-
-static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
- DATA_BLOB in_data,
- uint64_t in_offset,
- uint32_t in_flags)
-{
- NTSTATUS status;
- struct tevent_req *req;
- struct smbd_smb2_write_state *state;
- struct smb_request *smbreq;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
- ssize_t nwritten;
- bool write_through = false;
- struct lock_struct lock;
-
- req = tevent_req_create(mem_ctx, &state,
- struct smbd_smb2_write_state);
- if (req == NULL) {
- return NULL;
- }
- state->smb2req = smb2req;
- state->in_length = in_data.length;
- state->out_count = 0;
-
- DEBUG(10,("smbd_smb2_write: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- smbreq = smbd_smb2_fake_smb_request(smb2req);
- if (tevent_req_nomem(smbreq, req)) {
- return tevent_req_post(req, ev);
- }
-
- fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- if (IS_IPC(smbreq->conn)) {
- struct tevent_req *subreq;
-
- if (!fsp_is_np(fsp)) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
-
- subreq = np_write_send(state, smbd_event_context(),
- fsp->fake_file_handle,
- in_data.data,
- in_data.length);
- if (tevent_req_nomem(subreq, req)) {
- return tevent_req_post(req, ev);
- }
- tevent_req_set_callback(subreq,
- smbd_smb2_write_pipe_done,
- req);
- return req;
- }
-
- if (!CHECK_WRITE(fsp)) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return tevent_req_post(req, ev);
- }
-
- init_strict_lock_struct(fsp,
- in_smbpid,
- in_offset,
- in_data.length,
- WRITE_LOCK,
- &lock);
-
- if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- tevent_req_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
- return tevent_req_post(req, ev);
- }
-
- nwritten = write_file(smbreq, fsp,
- (const char *)in_data.data,
- in_offset,
- in_data.length);
-
- if (((nwritten == 0) && (in_data.length != 0)) || (nwritten < 0)) {
- DEBUG(5,("smbd_smb2_write: write_file[%s] disk full\n",
- fsp_str_dbg(fsp)));
- SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
- tevent_req_nterror(req, NT_STATUS_DISK_FULL);
- return tevent_req_post(req, ev);
- }
-
- DEBUG(3,("smbd_smb2_write: fnum=[%d/%s] length=%d offset=%d wrote=%d\n",
- fsp->fnum, fsp_str_dbg(fsp), (int)in_data.length,
- (int)in_offset, (int)nwritten));
-
- if (in_flags & 0x00000001) {
- write_through = true;
- }
-
- status = sync_file(conn, fsp, write_through);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5,("smbd_smb2_write: sync_file for %s returned %s\n",
- fsp_str_dbg(fsp), nt_errstr(status)));
- SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
- }
-
- SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
-
- state->out_count = nwritten;
-
- tevent_req_done(req);
- return tevent_req_post(req, ev);
-}
-
-static void smbd_smb2_write_pipe_done(struct tevent_req *subreq)
-{
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
- struct smbd_smb2_write_state *state = tevent_req_data(req,
- struct smbd_smb2_write_state);
- NTSTATUS status;
- ssize_t nwritten = -1;
-
- status = np_write_recv(subreq, &nwritten);
- TALLOC_FREE(subreq);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return;
- }
-
- if ((nwritten == 0 && state->in_length != 0) || (nwritten < 0)) {
- tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- state->out_count = nwritten;
-
- tevent_req_done(req);
-}
-
-static NTSTATUS smbd_smb2_write_recv(struct tevent_req *req,
- uint32_t *out_count)
-{
- NTSTATUS status;
- struct smbd_smb2_write_state *state = tevent_req_data(req,
- struct smbd_smb2_write_state);
-
- if (tevent_req_is_nterror(req, &status)) {
- tevent_req_received(req);
- return status;
- }
-
- *out_count = state->out_count;
-
- tevent_req_received(req);
- return NT_STATUS_OK;
-}
diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c
index d3f341138c..62b0fe1617 100644
--- a/source3/smbd/srvstr.c
+++ b/source3/smbd/srvstr.c
@@ -32,8 +32,8 @@ size_t srvstr_push_fn(const char *function, unsigned int line,
}
/* 'normal' push into size-specified buffer */
- return push_string_base(function, line, base_ptr, smb_flags2, dest, src,
- dest_len, flags);
+ return push_string_fn(function, line, base_ptr, smb_flags2, dest, src,
+ dest_len, flags);
}
/*******************************************************************
diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c
index db347b5b7e..72fed008a2 100644
--- a/source3/smbd/statcache.c
+++ b/source3/smbd/statcache.c
@@ -175,7 +175,6 @@ bool stat_cache_lookup(connection_struct *conn,
DATA_BLOB data_val;
char *name;
TALLOC_CTX *ctx = talloc_tos();
- struct smb_filename smb_fname;
*pp_dirpath = NULL;
*pp_start = *pp_name;
@@ -206,7 +205,7 @@ bool stat_cache_lookup(connection_struct *conn,
} else {
chk_name = talloc_strdup_upper(ctx,name);
if (!chk_name) {
- DEBUG(0, ("stat_cache_lookup: talloc_strdup_upper failed!\n"));
+ DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n"));
return False;
}
@@ -275,10 +274,7 @@ bool stat_cache_lookup(connection_struct *conn,
"-> [%s]\n", chk_name, translated_path ));
DO_PROFILE_INC(statcache_hits);
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = translated_path;
-
- if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
+ if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
memcache_delete(smbd_memcache(), STAT_CACHE,
data_blob_const(chk_name, strlen(chk_name)));
@@ -286,7 +282,6 @@ bool stat_cache_lookup(connection_struct *conn,
TALLOC_FREE(translated_path);
return False;
}
- *pst = smb_fname.st;
if (!sizechanged) {
memcpy(*pp_name, translated_path,
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 5620a2fd0d..e6d2b0ab8d 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -26,7 +26,8 @@
#include "includes.h"
#include "version.h"
#include "smbd/globals.h"
-#include "../libcli/auth/libcli_auth.h"
+
+extern enum protocol_types Protocol;
#define DIR_ENTRY_SAFETY_MARGIN 4096
@@ -70,8 +71,6 @@ static bool samba_private_attr_name(const char *unix_ea_name)
static const char * const prohibited_ea_names[] = {
SAMBA_POSIX_INHERITANCE_EA_NAME,
SAMBA_XATTR_DOS_ATTRIB,
- SAMBA_XATTR_MARKER,
- XATTR_NTACL_NAME,
NULL
};
@@ -155,9 +154,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
ssize_t sizeret = -1;
if (!lp_ea_support(SNUM(conn))) {
- if (pnames) {
- *pnames = NULL;
- }
+ *pnames = NULL;
*pnum_names = 0;
return NT_STATUS_OK;
}
@@ -208,9 +205,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
if (sizeret == 0) {
TALLOC_FREE(names);
- if (pnames) {
- *pnames = NULL;
- }
+ *pnames = NULL;
*pnum_names = 0;
return NT_STATUS_OK;
}
@@ -247,11 +242,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
names[num_names++] = p;
}
- if (pnames) {
- *pnames = names;
- } else {
- TALLOC_FREE(names);
- }
+ *pnames = names;
*pnum_names = num_names;
return NT_STATUS_OK;
}
@@ -375,69 +366,6 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in
return ret_data_size;
}
-static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
- char *pdata,
- unsigned int total_data_size,
- unsigned int *ret_data_size,
- connection_struct *conn,
- struct ea_list *ea_list)
-{
- uint8_t *p = (uint8_t *)pdata;
- uint8_t *last_start = NULL;
-
- *ret_data_size = 0;
-
- if (!lp_ea_support(SNUM(conn))) {
- return NT_STATUS_NO_EAS_ON_FILE;
- }
-
- for (; ea_list; ea_list = ea_list->next) {
- size_t dos_namelen;
- fstring dos_ea_name;
- size_t this_size;
-
- if (last_start) {
- SIVAL(last_start, 0, PTR_DIFF(p, last_start));
- }
- last_start = p;
-
- push_ascii_fstring(dos_ea_name, ea_list->ea.name);
- dos_namelen = strlen(dos_ea_name);
- if (dos_namelen > 255 || dos_namelen == 0) {
- return NT_STATUS_INTERNAL_ERROR;
- }
- if (ea_list->ea.value.length > 65535) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
-
- if (ea_list->next) {
- size_t pad = 4 - (this_size % 4);
- this_size += pad;
- }
-
- if (this_size > total_data_size) {
- return NT_STATUS_INFO_LENGTH_MISMATCH;
- }
-
- /* We know we have room. */
- SIVAL(p, 0x00, 0); /* next offset */
- SCVAL(p, 0x04, ea_list->ea.flags);
- SCVAL(p, 0x05, dos_namelen);
- SSVAL(p, 0x06, ea_list->ea.value.length);
- fstrcpy((char *)(p+0x08), dos_ea_name);
- memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
-
- total_data_size -= this_size;
- p += this_size;
- }
-
- *ret_data_size = PTR_DIFF(p, pdata);
- DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
- return NT_STATUS_OK;
-}
-
static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
{
size_t total_ea_len = 0;
@@ -475,18 +403,12 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con
Set or delete an extended attribute.
****************************************************************************/
-NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
- const struct smb_filename *smb_fname, struct ea_list *ea_list)
+NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
{
- char *fname = NULL;
-
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
}
- /* For now setting EAs on streams isn't supported. */
- fname = smb_fname->base_name;
-
for (;ea_list; ea_list = ea_list->next) {
int ret;
fstring unix_ea_name;
@@ -506,9 +428,8 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
if (ea_list->ea.value.length == 0) {
/* Remove the attribute. */
if (fsp && (fsp->fh->fd != -1)) {
- DEBUG(10,("set_ea: deleting ea name %s on "
- "file %s by file descriptor.\n",
- unix_ea_name, fsp_str_dbg(fsp)));
+ DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
+ unix_ea_name, fsp->fsp_name));
ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
} else {
DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
@@ -525,9 +446,8 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
#endif
} else {
if (fsp && (fsp->fh->fd != -1)) {
- DEBUG(10,("set_ea: setting ea name %s on file "
- "%s by file descriptor.\n",
- unix_ea_name, fsp_str_dbg(fsp)));
+ DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
+ unix_ea_name, fsp->fsp_name));
ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
ea_list->ea.value.data, ea_list->ea.value.length, 0);
} else {
@@ -761,8 +681,6 @@ void send_trans2_replies(connection_struct *conn,
int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
int data_alignment_offset = 0;
bool overflow = False;
- struct smbd_server_connection *sconn = smbd_server_conn;
- int max_send = sconn->smb1.sessions.max_send;
/* Modify the data_to_send and datasize and set the error if
we're trying to send more than max_data_bytes. We still send
@@ -781,14 +699,6 @@ void send_trans2_replies(connection_struct *conn,
if(params_to_send == 0 && data_to_send == 0) {
reply_outbuf(req, 10, 0);
show_msg((char *)req->outbuf);
- if (!srv_send_smb(smbd_server_fd(),
- (char *)req->outbuf,
- true, req->seqnum+1,
- IS_CONN_ENCRYPTED(conn),
- &req->pcd)) {
- exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
- }
- TALLOC_FREE(req->outbuf);
return;
}
@@ -922,7 +832,6 @@ void send_trans2_replies(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
- true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
&req->pcd))
exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
@@ -956,7 +865,6 @@ static void call_trans2open(connection_struct *conn,
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- struct smb_filename *smb_fname = NULL;
char *params = *pparams;
char *pdata = *ppdata;
int deny_mode;
@@ -974,6 +882,7 @@ static void call_trans2open(connection_struct *conn,
SMB_OFF_T size=0;
int fattr=0,mtime=0;
SMB_INO_T inode = 0;
+ SMB_STRUCT_STAT sbuf;
int smb_action = 0;
files_struct *fsp;
struct ea_list *ea_list = NULL;
@@ -985,13 +894,15 @@ static void call_trans2open(connection_struct *conn,
uint32 create_options = 0;
TALLOC_CTX *ctx = talloc_tos();
+ SET_STAT_INVALID(sbuf);
+
/*
* Ensure we have enough parameters to perform the operation.
*/
if (total_params < 29) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
flags = SVAL(params, 0);
@@ -1012,8 +923,8 @@ static void call_trans2open(connection_struct *conn,
pname = &params[28];
if (IS_IPC(conn)) {
- reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
- goto out;
+ reply_doserror(req, ERRSRV, ERRaccess);
+ return;
}
srvstr_get_path(ctx, params, req->flags2, &fname, pname,
@@ -1021,79 +932,63 @@ static void call_trans2open(connection_struct *conn,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ return;
}
DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
fname, (unsigned int)deny_mode, (unsigned int)open_attr,
(unsigned int)open_ofun, open_size));
- status = filename_convert(ctx,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- goto out;
- }
- reply_nterror(req, status);
- goto out;
- }
-
if (open_ofun == 0) {
reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
- goto out;
+ return;
}
- if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
- &access_mask, &share_mode,
- &create_disposition,
- &create_options)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
+ &access_mask,
+ &share_mode,
+ &create_disposition,
+ &create_options)) {
+ reply_doserror(req, ERRDOS, ERRbadaccess);
+ return;
}
/* Any data in this call is an EA list. */
if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- goto out;
+ return;
}
if (total_data != 4) {
if (total_data < 10) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
if (IVAL(pdata,0) > total_data) {
DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
IVAL(pdata,0), (unsigned int)total_data));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
ea_list = read_ea_list(talloc_tos(), pdata + 4,
total_data - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
} else if (IVAL(pdata,0) != 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
access_mask, /* access_mask */
share_mode, /* share_access */
create_disposition, /* create_disposition*/
@@ -1104,32 +999,33 @@ static void call_trans2open(connection_struct *conn,
NULL, /* sd */
ea_list, /* ea_list */
&fsp, /* result */
- &smb_action); /* psbuf */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
- goto out;
+ return;
}
reply_openerror(req, status);
- goto out;
+ return;
}
- size = get_file_size_stat(&smb_fname->st);
- fattr = dos_mode(conn, smb_fname);
- mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
- inode = smb_fname->st.st_ex_ino;
+ size = get_file_size_stat(&sbuf);
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
+ mtime = sbuf.st_mtime;
+ inode = sbuf.st_ino;
if (fattr & aDIR) {
close_file(req, fsp, ERROR_CLOSE);
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- goto out;
+ reply_doserror(req, ERRDOS,ERRnoaccess);
+ return;
}
/* Realloc the size of parameters and data we will return */
*pparams = (char *)SMB_REALLOC(*pparams, 30);
if(*pparams == NULL ) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
params = *pparams;
@@ -1153,8 +1049,7 @@ static void call_trans2open(connection_struct *conn,
SIVAL(params,20,inode);
SSVAL(params,24,0); /* Padding. */
if (flags & 8) {
- uint32 ea_size = estimate_ea_size(conn, fsp,
- fsp->fsp_name->base_name);
+ uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
SIVAL(params, 26, ea_size);
} else {
SIVAL(params, 26, 0);
@@ -1162,8 +1057,6 @@ static void call_trans2open(connection_struct *conn,
/* Send the required number of replies */
send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
- out:
- TALLOC_FREE(smb_fname);
}
/*********************************************************
@@ -1173,24 +1066,19 @@ static void call_trans2open(connection_struct *conn,
Case can be significant or not.
**********************************************************/
-static bool exact_match(bool has_wild,
- bool case_sensitive,
- const char *str,
- const char *mask)
+static bool exact_match(connection_struct *conn,
+ const char *str,
+ const char *mask)
{
- if (mask[0] == '.' && mask[1] == 0) {
- return false;
- }
-
- if (has_wild) {
- return false;
+ if (mask[0] == '.' && mask[1] == 0)
+ return False;
+ if (dptr_has_wild(conn->dirptr)) {
+ return False;
}
-
- if (case_sensitive) {
+ if (conn->case_sensitive)
return strcmp(str,mask)==0;
- } else {
+ else
return StrCaseCmp(str,mask) == 0;
- }
}
/****************************************************************************
@@ -1235,7 +1123,7 @@ static uint32 unix_filetype(mode_t mode)
enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
static NTSTATUS unix_perms_from_wire( connection_struct *conn,
- const SMB_STRUCT_STAT *psbuf,
+ SMB_STRUCT_STAT *psbuf,
uint32 perms,
enum perm_type ptype,
mode_t *ret_perms)
@@ -1246,7 +1134,7 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
if (!VALID_STAT(*psbuf)) {
return NT_STATUS_INVALID_PARAMETER;
} else {
- *ret_perms = psbuf->st_ex_mode;
+ *ret_perms = psbuf->st_mode;
return NT_STATUS_OK;
}
}
@@ -1317,7 +1205,7 @@ static bool check_msdfs_link(connection_struct *conn,
DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
"as a directory\n",
pathname));
- psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
+ psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
errno = saved_errno;
return true;
}
@@ -1330,699 +1218,640 @@ static bool check_msdfs_link(connection_struct *conn,
Get a level dependent lanman2 dir entry.
****************************************************************************/
-struct smbd_dirptr_lanman2_state {
- connection_struct *conn;
- uint32_t info_level;
- bool check_mangled_names;
- bool has_wild;
- bool got_exact_match;
-};
-
-static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
- void *private_data,
- const char *dname,
- const char *mask,
- char **_fname)
+static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
+ connection_struct *conn,
+ uint16 flags2,
+ const char *path_mask,
+ uint32 dirtype,
+ int info_level,
+ int requires_resume_key,
+ bool dont_descend,
+ bool ask_sharemode,
+ char **ppdata,
+ char *base_data,
+ char *end_data,
+ int space_remaining,
+ bool *out_of_space,
+ bool *got_exact_match,
+ int *last_entry_off,
+ struct ea_list *name_list)
{
- struct smbd_dirptr_lanman2_state *state =
- (struct smbd_dirptr_lanman2_state *)private_data;
- bool ok;
+ char *dname;
+ bool found = False;
+ SMB_STRUCT_STAT sbuf;
+ const char *mask = NULL;
+ char *pathreal = NULL;
+ char *fname = NULL;
+ char *p, *q, *pdata = *ppdata;
+ uint32 reskey=0;
+ long prev_dirpos=0;
+ uint32 mode=0;
+ SMB_OFF_T file_size = 0;
+ uint64_t allocation_size = 0;
+ uint32 len;
+ struct timespec mdate_ts, adate_ts, create_date_ts;
+ time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
+ char *nameptr;
+ char *last_entry_ptr;
+ bool was_8_3;
+ bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
+ bool check_mangled_names = lp_manglednames(conn->params);
char mangled_name[13]; /* mangled 8.3 name. */
- bool got_match;
- const char *fname;
- /* Mangle fname if it's an illegal name. */
- if (mangle_must_mangle(dname, state->conn->params)) {
- ok = name_to_8_3(dname, mangled_name,
- true, state->conn->params);
- if (!ok) {
- return false;
+ *out_of_space = False;
+ *got_exact_match = False;
+
+ ZERO_STRUCT(mdate_ts);
+ ZERO_STRUCT(adate_ts);
+ ZERO_STRUCT(create_date_ts);
+
+ if (!conn->dirptr) {
+ return(False);
+ }
+
+ p = strrchr_m(path_mask,'/');
+ if(p != NULL) {
+ if(p[1] == '\0') {
+ mask = talloc_strdup(ctx,"*.*");
+ } else {
+ mask = p+1;
}
- fname = mangled_name;
} else {
- fname = dname;
+ mask = path_mask;
}
- got_match = exact_match(state->has_wild,
- state->conn->case_sensitive,
- fname, mask);
- state->got_exact_match = got_match;
- if (!got_match) {
- got_match = mask_match(fname, mask,
- state->conn->case_sensitive);
- }
+ while (!found) {
+ bool got_match;
+ bool ms_dfs_link = False;
+
+ /* Needed if we run out of space */
+ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
+ dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
- if(!got_match && state->check_mangled_names &&
- !mangle_is_8_3(fname, false, state->conn->params)) {
/*
- * It turns out that NT matches wildcards against
- * both long *and* short names. This may explain some
- * of the wildcard wierdness from old DOS clients
- * that some people have been seeing.... JRA.
+ * Due to bugs in NT client redirectors we are not using
+ * resume keys any more - set them to zero.
+ * Check out the related comments in findfirst/findnext.
+ * JRA.
*/
- /* Force the mangling into 8.3. */
- ok = name_to_8_3(fname, mangled_name,
- false, state->conn->params);
- if (!ok) {
- return false;
- }
- got_match = exact_match(state->has_wild,
- state->conn->case_sensitive,
- mangled_name, mask);
- state->got_exact_match = got_match;
- if (!got_match) {
- got_match = mask_match(mangled_name, mask,
- state->conn->case_sensitive);
- }
- }
+ reskey = 0;
- if (!got_match) {
- return false;
- }
+ DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
+ (long)conn->dirptr,curr_dirpos));
- *_fname = talloc_strdup(ctx, fname);
- if (*_fname == NULL) {
- return false;
- }
+ if (!dname) {
+ return(False);
+ }
- return true;
-}
+ /*
+ * fname may get mangled, dname is never mangled.
+ * Whenever we're accessing the filesystem we use
+ * pathreal which is composed from dname.
+ */
-static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
- void *private_data,
- struct smb_filename *smb_fname,
- uint32_t *_mode)
-{
- struct smbd_dirptr_lanman2_state *state =
- (struct smbd_dirptr_lanman2_state *)private_data;
- bool ms_dfs_link = false;
- uint32_t mode = 0;
+ pathreal = NULL;
+ fname = dname;
- if (INFO_LEVEL_IS_UNIX(state->info_level)) {
- if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
- DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
- "Couldn't lstat [%s] (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- return false;
+ /* Mangle fname if it's an illegal name. */
+ if (mangle_must_mangle(dname,conn->params)) {
+ if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
+ TALLOC_FREE(fname);
+ continue; /* Error - couldn't mangle. */
+ }
+ fname = talloc_strdup(ctx, mangled_name);
+ if (!fname) {
+ return False;
+ }
}
- } else if (!VALID_STAT(smb_fname->st) &&
- SMB_VFS_STAT(state->conn, smb_fname) != 0) {
- /* Needed to show the msdfs symlinks as
- * directories */
- ms_dfs_link = check_msdfs_link(state->conn,
- smb_fname->base_name,
- &smb_fname->st);
- if (!ms_dfs_link) {
- DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
- "Couldn't stat [%s] (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- return false;
+ if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
+ got_match = mask_match(fname, mask, conn->case_sensitive);
}
- }
- if (ms_dfs_link) {
- mode = dos_mode_msdfs(state->conn, smb_fname);
- } else {
- mode = dos_mode(state->conn, smb_fname);
- }
+ if(!got_match && check_mangled_names &&
+ !mangle_is_8_3(fname, False, conn->params)) {
+ /*
+ * It turns out that NT matches wildcards against
+ * both long *and* short names. This may explain some
+ * of the wildcard wierdness from old DOS clients
+ * that some people have been seeing.... JRA.
+ */
+ /* Force the mangling into 8.3. */
+ if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+ TALLOC_FREE(fname);
+ continue; /* Error - couldn't mangle. */
+ }
- *_mode = mode;
- return true;
-}
+ if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
+ got_match = mask_match(mangled_name, mask, conn->case_sensitive);
+ }
+ }
-static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
- connection_struct *conn,
- uint16_t flags2,
- uint32_t info_level,
- struct ea_list *name_list,
- bool check_mangled_names,
- bool requires_resume_key,
- uint32_t mode,
- const char *fname,
- const struct smb_filename *smb_fname,
- uint64_t space_remaining,
- uint8_t align,
- bool do_pad,
- char *base_data,
- char **ppdata,
- char *end_data,
- bool *out_of_space,
- uint64_t *last_entry_off)
-{
- char *p, *q, *pdata = *ppdata;
- uint32_t reskey=0;
- uint64_t file_size = 0;
- uint64_t allocation_size = 0;
- uint32_t len;
- struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
- time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
- time_t c_date = (time_t)0;
- char *nameptr;
- char *last_entry_ptr;
- bool was_8_3;
- off_t off;
- off_t pad = 0;
+ if (got_match) {
+ bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
- *out_of_space = false;
+ if (dont_descend && !isdots) {
+ TALLOC_FREE(fname);
+ continue;
+ }
- ZERO_STRUCT(mdate_ts);
- ZERO_STRUCT(adate_ts);
- ZERO_STRUCT(create_date_ts);
- ZERO_STRUCT(cdate_ts);
+ if (needslash) {
+ pathreal = NULL;
+ pathreal = talloc_asprintf(ctx,
+ "%s/%s",
+ conn->dirpath,
+ dname);
+ } else {
+ pathreal = talloc_asprintf(ctx,
+ "%s%s",
+ conn->dirpath,
+ dname);
+ }
- if (!(mode & aDIR)) {
- file_size = get_file_size_stat(&smb_fname->st);
- }
- allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
+ if (!pathreal) {
+ TALLOC_FREE(fname);
+ return False;
+ }
- mdate_ts = smb_fname->st.st_ex_mtime;
- adate_ts = smb_fname->st.st_ex_atime;
- create_date_ts = get_create_timespec(conn, NULL, smb_fname);
- cdate_ts = get_change_timespec(conn, NULL, smb_fname);
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
+ DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
+ pathreal,strerror(errno)));
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(fname);
+ continue;
+ }
+ } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+ /* Needed to show the msdfs symlinks as
+ * directories */
+
+ ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
+ if (!ms_dfs_link) {
+ DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
+ pathreal,strerror(errno)));
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(fname);
+ continue;
+ }
+ }
- if (lp_dos_filetime_resolution(SNUM(conn))) {
- dos_filetime_timespec(&create_date_ts);
- dos_filetime_timespec(&mdate_ts);
- dos_filetime_timespec(&adate_ts);
- dos_filetime_timespec(&cdate_ts);
- }
+ if (ms_dfs_link) {
+ mode = dos_mode_msdfs(conn,pathreal,&sbuf);
+ } else {
+ mode = dos_mode(conn,pathreal,&sbuf);
+ }
+
+ if (!dir_check_ftype(conn,mode,dirtype)) {
+ DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
+ TALLOC_FREE(pathreal);
+ TALLOC_FREE(fname);
+ continue;
+ }
+
+ if (!(mode & aDIR)) {
+ file_size = get_file_size_stat(&sbuf);
+ }
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
+
+ mdate_ts = get_mtimespec(&sbuf);
+ adate_ts = get_atimespec(&sbuf);
+ create_date_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
+
+ if (ask_sharemode) {
+ struct timespec write_time_ts;
+ struct file_id fileid;
+
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ get_file_infos(fileid, NULL, &write_time_ts);
+ if (!null_timespec(write_time_ts)) {
+ mdate_ts = write_time_ts;
+ }
+ }
+
+ if (lp_dos_filetime_resolution(SNUM(conn))) {
+ dos_filetime_timespec(&create_date_ts);
+ dos_filetime_timespec(&mdate_ts);
+ dos_filetime_timespec(&adate_ts);
+ }
+
+ create_date = convert_timespec_to_time_t(create_date_ts);
+ mdate = convert_timespec_to_time_t(mdate_ts);
+ adate = convert_timespec_to_time_t(adate_ts);
+
+ DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
+ pathreal,fname));
+
+ found = True;
- create_date = convert_timespec_to_time_t(create_date_ts);
- mdate = convert_timespec_to_time_t(mdate_ts);
- adate = convert_timespec_to_time_t(adate_ts);
- c_date = convert_timespec_to_time_t(cdate_ts);
+ dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
+ }
- /* align the record */
- off = PTR_DIFF(pdata, base_data);
- pad = (off + (align-1)) & ~(align-1);
- pad -= off;
- off += pad;
- /* initialize padding to 0 */
- if (pad) {
- memset(pdata, 0, pad);
+ if (!found)
+ TALLOC_FREE(fname);
}
- space_remaining -= pad;
- pdata += pad;
p = pdata;
last_entry_ptr = p;
- pad = 0;
- off = 0;
-
switch (info_level) {
- case SMB_FIND_INFO_STANDARD:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
- if(requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- p += 23;
- nameptr = p;
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- p += ucs2_align(base_data, p, 0);
- }
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- SCVAL(nameptr, -1, len - 2);
- } else {
- SCVAL(nameptr, -1, 0);
+ case SMB_FIND_INFO_STANDARD:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
+ if(requires_resume_key) {
+ SIVAL(p,0,reskey);
+ p += 4;
}
- } else {
- if (len > 1) {
- SCVAL(nameptr, -1, len - 1);
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
+ p += 23;
+ nameptr = p;
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ p += ucs2_align(base_data, p, 0);
+ }
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ SCVAL(nameptr, -1, len - 2);
+ } else {
+ SCVAL(nameptr, -1, 0);
+ }
} else {
- SCVAL(nameptr, -1, 0);
+ if (len > 1) {
+ SCVAL(nameptr, -1, len - 1);
+ } else {
+ SCVAL(nameptr, -1, 0);
+ }
}
- }
- p += len;
- break;
+ p += len;
+ break;
- case SMB_FIND_EA_SIZE:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
- if (requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,22,ea_size); /* Extended attributes */
- }
- p += 27;
- nameptr = p - 1;
- len = srvstr_push(base_data, flags2,
- p, fname, PTR_DIFF(end_data, p),
- STR_TERMINATE | STR_NOALIGN);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- len -= 2;
- } else {
- len = 0;
+ case SMB_FIND_EA_SIZE:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
+ if(requires_resume_key) {
+ SIVAL(p,0,reskey);
+ p += 4;
}
- } else {
- if (len > 1) {
- len -= 1;
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
+ SIVAL(p,22,ea_size); /* Extended attributes */
+ }
+ p += 27;
+ nameptr = p - 1;
+ len = srvstr_push(base_data, flags2,
+ p, fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE | STR_NOALIGN);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ len -= 2;
+ } else {
+ len = 0;
+ }
} else {
- len = 0;
+ if (len > 1) {
+ len -= 1;
+ } else {
+ len = 0;
+ }
}
- }
- SCVAL(nameptr,0,len);
- p += len;
- SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
- break;
+ SCVAL(nameptr,0,len);
+ p += len;
+ SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
+ break;
- case SMB_FIND_EA_LIST:
- {
- struct ea_list *file_list = NULL;
- size_t ea_len = 0;
+ case SMB_FIND_EA_LIST:
+ {
+ struct ea_list *file_list = NULL;
+ size_t ea_len = 0;
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
- if (!name_list) {
- return false;
- }
- if (requires_resume_key) {
- SIVAL(p,0,reskey);
- p += 4;
- }
- srv_put_dos_date2(p,0,create_date);
- srv_put_dos_date2(p,4,adate);
- srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
- SSVAL(p,20,mode);
- p += 22; /* p now points to the EA area. */
-
- file_list = get_ea_list_from_file(ctx, conn, NULL,
- smb_fname->base_name,
- &ea_len);
- name_list = ea_list_union(name_list, file_list, &ea_len);
-
- /* We need to determine if this entry will fit in the space available. */
- /* Max string size is 255 bytes. */
- if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
- *out_of_space = true;
- DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
- return False; /* Not finished - just out of space */
- }
-
- /* Push the ea_data followed by the name. */
- p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
- nameptr = p;
- len = srvstr_push(base_data, flags2,
- p + 1, fname, PTR_DIFF(end_data, p+1),
- STR_TERMINATE | STR_NOALIGN);
- if (flags2 & FLAGS2_UNICODE_STRINGS) {
- if (len > 2) {
- len -= 2;
- } else {
- len = 0;
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
+ if (!name_list) {
+ return False;
}
- } else {
- if (len > 1) {
- len -= 1;
+ if(requires_resume_key) {
+ SIVAL(p,0,reskey);
+ p += 4;
+ }
+ srv_put_dos_date2(p,0,create_date);
+ srv_put_dos_date2(p,4,adate);
+ srv_put_dos_date2(p,8,mdate);
+ SIVAL(p,12,(uint32)file_size);
+ SIVAL(p,16,(uint32)allocation_size);
+ SSVAL(p,20,mode);
+ p += 22; /* p now points to the EA area. */
+
+ file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
+ name_list = ea_list_union(name_list, file_list, &ea_len);
+
+ /* We need to determine if this entry will fit in the space available. */
+ /* Max string size is 255 bytes. */
+ if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
+ /* Move the dirptr back to prev_dirpos */
+ dptr_SeekDir(conn->dirptr, prev_dirpos);
+ *out_of_space = True;
+ DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
+ return False; /* Not finished - just out of space */
+ }
+
+ /* Push the ea_data followed by the name. */
+ p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
+ nameptr = p;
+ len = srvstr_push(base_data, flags2,
+ p + 1, fname, PTR_DIFF(end_data, p+1),
+ STR_TERMINATE | STR_NOALIGN);
+ if (flags2 & FLAGS2_UNICODE_STRINGS) {
+ if (len > 2) {
+ len -= 2;
+ } else {
+ len = 0;
+ }
} else {
- len = 0;
+ if (len > 1) {
+ len -= 1;
+ } else {
+ len = 0;
+ }
}
+ SCVAL(nameptr,0,len);
+ p += len + 1;
+ SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
+ break;
}
- SCVAL(nameptr,0,len);
- p += len + 1;
- SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
- break;
- }
- case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
- was_8_3 = mangle_is_8_3(fname, True, conn->params);
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,mode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
+ case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
p += 4;
- }
- /* Clear the short name buffer. This is
- * IMPORTANT as not doing so will trigger
- * a Win2k client bug. JRA.
- */
- if (!was_8_3 && check_mangled_names) {
- char mangled_name[13]; /* mangled 8.3 name. */
- if (!name_to_8_3(fname,mangled_name,True,
- conn->params)) {
- /* Error - mangle failed ! */
- memset(mangled_name,'\0',12);
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,mode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p += 4;
}
- mangled_name[12] = 0;
- len = srvstr_push(base_data, flags2,
- p+2, mangled_name, 24,
- STR_UPPER|STR_UNICODE);
- if (len < 24) {
- memset(p + 2 + len,'\0',24 - len);
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
+ if (!was_8_3 && check_mangled_names) {
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
+ }
+ mangled_name[12] = 0;
+ len = srvstr_push(base_data, flags2,
+ p+2, mangled_name, 24,
+ STR_UPPER|STR_UNICODE);
+ if (len < 24) {
+ memset(p + 2 + len,'\0',24 - len);
+ }
+ SSVAL(p, 0, len);
+ } else {
+ memset(p,'\0',26);
}
- SSVAL(p, 0, len);
- } else {
- memset(p,'\0',26);
- }
- p += 2 + 24;
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q,0,len);
- p += len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ p += 2 + 24;
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q,0,len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- case SMB_FIND_FILE_DIRECTORY_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,mode); p += 4;
- len = srvstr_push(base_data, flags2,
- p + 4, fname, PTR_DIFF(end_data, p+4),
- STR_TERMINATE_ASCII);
- SIVAL(p,0,len);
- p += 4 + len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ case SMB_FIND_FILE_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,mode); p += 4;
+ len = srvstr_push(base_data, flags2,
+ p + 4, fname, PTR_DIFF(end_data, p+4),
+ STR_TERMINATE_ASCII);
+ SIVAL(p,0,len);
+ p += 4 + len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,mode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
- }
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q, 0, len);
- p += len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,mode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
+ }
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q, 0, len);
+ p += len;
+
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- case SMB_FIND_FILE_NAMES_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- p += 4;
- /* this must *not* be null terminated or w2k gets in a loop trying to set an
- acl on a dir (tridge) */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(p, -4, len);
- p += len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ case SMB_FIND_FILE_NAMES_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ p += 4;
+ /* this must *not* be null terminated or w2k gets in a loop trying to set an
+ acl on a dir (tridge) */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(p, -4, len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- case SMB_FIND_ID_FULL_DIRECTORY_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,mode); p += 4;
- q = p; p += 4; /* q is placeholder for name length. */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
- }
- SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q, 0, len);
- p += len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ case SMB_FIND_ID_FULL_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,mode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length. */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
+ }
+ SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
+ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
+ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q, 0, len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
- was_8_3 = mangle_is_8_3(fname, True, conn->params);
- p += 4;
- SIVAL(p,0,reskey); p += 4;
- put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
- put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
- SOFF_T(p,0,file_size); p += 8;
- SOFF_T(p,0,allocation_size); p += 8;
- SIVAL(p,0,mode); p += 4;
- q = p; p += 4; /* q is placeholder for name length */
- {
- unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
- SIVAL(p,0,ea_size); /* Extended attributes */
- p +=4;
- }
- /* Clear the short name buffer. This is
- * IMPORTANT as not doing so will trigger
- * a Win2k client bug. JRA.
- */
- if (!was_8_3 && check_mangled_names) {
- char mangled_name[13]; /* mangled 8.3 name. */
- if (!name_to_8_3(fname,mangled_name,True,
- conn->params)) {
- /* Error - mangle failed ! */
- memset(mangled_name,'\0',12);
+ case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
+ was_8_3 = mangle_is_8_3(fname, True, conn->params);
+ p += 4;
+ SIVAL(p,0,reskey); p += 4;
+ put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
+ SOFF_T(p,0,file_size); p += 8;
+ SOFF_T(p,0,allocation_size); p += 8;
+ SIVAL(p,0,mode); p += 4;
+ q = p; p += 4; /* q is placeholder for name length */
+ {
+ unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
+ SIVAL(p,0,ea_size); /* Extended attributes */
+ p +=4;
}
- mangled_name[12] = 0;
- len = srvstr_push(base_data, flags2,
- p+2, mangled_name, 24,
- STR_UPPER|STR_UNICODE);
- SSVAL(p, 0, len);
- if (len < 24) {
- memset(p + 2 + len,'\0',24 - len);
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
+ if (!was_8_3 && check_mangled_names) {
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
+ }
+ mangled_name[12] = 0;
+ len = srvstr_push(base_data, flags2,
+ p+2, mangled_name, 24,
+ STR_UPPER|STR_UNICODE);
+ SSVAL(p, 0, len);
+ if (len < 24) {
+ memset(p + 2 + len,'\0',24 - len);
+ }
+ SSVAL(p, 0, len);
+ } else {
+ memset(p,'\0',26);
}
- SSVAL(p, 0, len);
- } else {
- memset(p,'\0',26);
- }
- p += 26;
- SSVAL(p,0,0); p += 2; /* Reserved ? */
- SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
- SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE_ASCII);
- SIVAL(q,0,len);
- p += len;
-
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ p += 26;
+ SSVAL(p,0,0); p += 2; /* Reserved ? */
+ SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
+ SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE_ASCII);
+ SIVAL(q,0,len);
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len);
p = pdata + len;
- }
- break;
+ break;
- /* CIFS UNIX Extension. */
+ /* CIFS UNIX Extension. */
- case SMB_FIND_FILE_UNIX:
- case SMB_FIND_FILE_UNIX_INFO2:
- p+= 4;
- SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
+ case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
+ p+= 4;
+ SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
- /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
+ /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
- if (info_level == SMB_FIND_FILE_UNIX) {
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
- p = store_file_unix_basic(conn, p,
- NULL, &smb_fname->st);
- len = srvstr_push(base_data, flags2, p,
- fname, PTR_DIFF(end_data, p),
- STR_TERMINATE);
- } else {
- DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
- p = store_file_unix_basic_info2(conn, p,
- NULL, &smb_fname->st);
- nameptr = p;
- p += 4;
- len = srvstr_push(base_data, flags2, p, fname,
- PTR_DIFF(end_data, p), 0);
- SIVAL(nameptr, 0, len);
- }
+ if (info_level == SMB_FIND_FILE_UNIX) {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ p = store_file_unix_basic(conn, p,
+ NULL, &sbuf);
+ len = srvstr_push(base_data, flags2, p,
+ fname, PTR_DIFF(end_data, p),
+ STR_TERMINATE);
+ } else {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
+ p = store_file_unix_basic_info2(conn, p,
+ NULL, &sbuf);
+ nameptr = p;
+ p += 4;
+ len = srvstr_push(base_data, flags2, p, fname,
+ PTR_DIFF(end_data, p), 0);
+ SIVAL(nameptr, 0, len);
+ }
- p += len;
+ p += len;
+ SIVAL(p,0,0); /* Ensure any padding is null. */
- len = PTR_DIFF(p, pdata);
- pad = (len + (align-1)) & ~(align-1);
- /*
- * offset to the next entry, the caller
- * will overwrite it for the last entry
- * that's why we always include the padding
- */
- SIVAL(pdata,0,pad);
- /*
- * set padding to zero
- */
- if (do_pad) {
- memset(p, 0, pad - len);
- p = pdata + pad;
- } else {
+ len = PTR_DIFF(p, pdata);
+ len = (len + 3) & ~3;
+ SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
p = pdata + len;
- }
- /* End of SMB_QUERY_FILE_UNIX_BASIC */
+ /* End of SMB_QUERY_FILE_UNIX_BASIC */
- break;
+ break;
- default:
- return false;
+ default:
+ TALLOC_FREE(fname);
+ return(False);
}
+ TALLOC_FREE(fname);
if (PTR_DIFF(p,pdata) > space_remaining) {
- *out_of_space = true;
- DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
- return false; /* Not finished - just out of space */
+ /* Move the dirptr back to prev_dirpos */
+ dptr_SeekDir(conn->dirptr, prev_dirpos);
+ *out_of_space = True;
+ DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
+ return False; /* Not finished - just out of space */
}
/* Setup the last entry pointer, as an offset from base_data */
@@ -2030,147 +1859,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
/* Advance the data pointer to the next slot */
*ppdata = p;
- return true;
-}
-
-bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct dptr_struct *dirptr,
- uint16 flags2,
- const char *path_mask,
- uint32 dirtype,
- int info_level,
- int requires_resume_key,
- bool dont_descend,
- bool ask_sharemode,
- uint8_t align,
- bool do_pad,
- char **ppdata,
- char *base_data,
- char *end_data,
- int space_remaining,
- bool *out_of_space,
- bool *got_exact_match,
- int *_last_entry_off,
- struct ea_list *name_list)
-{
- const char *p;
- const char *mask = NULL;
- long prev_dirpos = 0;
- uint32_t mode = 0;
- char *fname = NULL;
- struct smb_filename *smb_fname = NULL;
- struct smbd_dirptr_lanman2_state state;
- bool ok;
- uint64_t last_entry_off = 0;
-
- ZERO_STRUCT(state);
- state.conn = conn;
- state.info_level = info_level;
- state.check_mangled_names = lp_manglednames(conn->params);
- state.has_wild = dptr_has_wild(dirptr);
- state.got_exact_match = false;
-
- *out_of_space = false;
- *got_exact_match = false;
-
- p = strrchr_m(path_mask,'/');
- if(p != NULL) {
- if(p[1] == '\0') {
- mask = "*.*";
- } else {
- mask = p+1;
- }
- } else {
- mask = path_mask;
- }
-
- ok = smbd_dirptr_get_entry(ctx,
- dirptr,
- mask,
- dirtype,
- dont_descend,
- ask_sharemode,
- smbd_dirptr_lanman2_match_fn,
- smbd_dirptr_lanman2_mode_fn,
- &state,
- &fname,
- &smb_fname,
- &mode,
- &prev_dirpos);
- if (!ok) {
- return false;
- }
-
- *got_exact_match = state.got_exact_match;
-
- ok = smbd_marshall_dir_entry(ctx,
- conn,
- flags2,
- info_level,
- name_list,
- state.check_mangled_names,
- requires_resume_key,
- mode,
- fname,
- smb_fname,
- space_remaining,
- align,
- do_pad,
- base_data,
- ppdata,
- end_data,
- out_of_space,
- &last_entry_off);
- TALLOC_FREE(fname);
- TALLOC_FREE(smb_fname);
- if (*out_of_space) {
- dptr_SeekDir(dirptr, prev_dirpos);
- return false;
- }
- if (!ok) {
- return false;
- }
-
- *_last_entry_off = last_entry_off;
- return true;
-}
-
-static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct dptr_struct *dirptr,
- uint16 flags2,
- const char *path_mask,
- uint32 dirtype,
- int info_level,
- bool requires_resume_key,
- bool dont_descend,
- bool ask_sharemode,
- char **ppdata,
- char *base_data,
- char *end_data,
- int space_remaining,
- bool *out_of_space,
- bool *got_exact_match,
- int *last_entry_off,
- struct ea_list *name_list)
-{
- uint8_t align = 4;
- const bool do_pad = true;
-
- if (info_level >= 1 && info_level <= 3) {
- /* No alignment on earlier info levels. */
- align = 1;
- }
-
- return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
- path_mask, dirtype, info_level,
- requires_resume_key, dont_descend, ask_sharemode,
- align, do_pad,
- ppdata, base_data, end_data,
- space_remaining,
- out_of_space, got_exact_match,
- last_entry_off, name_list);
+ return(found);
}
/****************************************************************************
@@ -2188,7 +1877,6 @@ static void call_trans2findfirst(connection_struct *conn,
maxentries then so be it. We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested. */
- struct smb_filename *smb_dname = NULL;
char *params = *pparams;
char *pdata = *ppdata;
char *data_end;
@@ -2211,16 +1899,15 @@ static void call_trans2findfirst(connection_struct *conn,
bool out_of_space = False;
int space_remaining;
bool mask_contains_wcard = False;
+ SMB_STRUCT_STAT sbuf;
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
TALLOC_CTX *ctx = talloc_tos();
- struct dptr_struct *dirptr = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
dirtype = SVAL(params,0);
@@ -2258,12 +1945,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
ask_sharemode = false;
if (!lp_unix_extensions()) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
- goto out;
+ return;
}
break;
default:
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
- goto out;
+ return;
}
srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
@@ -2271,29 +1958,35 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
- goto out;
+ return;
}
- ntstatus = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- directory,
- (UCF_SAVE_LCOMP |
- UCF_ALWAYS_ALLOW_WCARD_LCOMP),
- &mask_contains_wcard,
- &smb_dname);
+ ntstatus = resolve_dfspath_wcard(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ directory,
+ &directory,
+ &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
ERRSRV, ERRbadpath);
- goto out;
+ return;
}
reply_nterror(req, ntstatus);
- goto out;
+ return;
}
- mask = smb_dname->original_lcomp;
+ ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ reply_nterror(req, ntstatus);
+ return;
+ }
- directory = smb_dname->base_name;
+ ntstatus = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ reply_nterror(req, ntstatus);
+ return;
+ }
p = strrchr_m(directory,'/');
if(p == NULL) {
@@ -2302,14 +1995,14 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
mask = talloc_strdup(ctx,"*");
if (!mask) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
mask_contains_wcard = True;
}
directory = talloc_strdup(talloc_tos(), "./");
if (!directory) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
} else {
*p = 0;
@@ -2322,7 +2015,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
if (total_data < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
ea_size = IVAL(pdata,0);
@@ -2330,19 +2023,19 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
if (!lp_ea_support(SNUM(conn))) {
- reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- goto out;
+ reply_doserror(req, ERRDOS, ERReasnotsupported);
+ return;
}
/* Pull out the list of names. */
ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
}
@@ -2350,7 +2043,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if(*ppdata == NULL ) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
pdata = *ppdata;
data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
@@ -2359,7 +2052,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
*pparams = (char *)SMB_REALLOC(*pparams, 10);
if (*pparams == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
params = *pparams;
@@ -2374,25 +2067,24 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
mask,
mask_contains_wcard,
dirtype,
- &dirptr);
+ &conn->dirptr);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
- goto out;
+ return;
}
- dptr_num = dptr_dnum(dirptr);
+ dptr_num = dptr_dnum(conn->dirptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
/* Initialize per TRANS2_FIND_FIRST operation data */
- dptr_init_search_op(dirptr);
+ dptr_init_search_op(conn->dirptr);
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
@@ -2410,7 +2102,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
} else {
finished = !get_lanman2_dir_entry(ctx,
conn,
- dirptr,
req->flags2,
mask,dirtype,info_level,
requires_resume_key,dont_descend,
@@ -2449,7 +2140,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
/* Check if we can close the dirptr */
if(close_after_first || (finished && close_if_end)) {
DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
}
/*
@@ -2460,14 +2151,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
*/
if(numentries == 0) {
- dptr_close(sconn, &dptr_num);
- if (get_Protocol() < PROTOCOL_NT1) {
- reply_force_doserror(req, ERRDOS, ERRnofiles);
- goto out;
+ dptr_close(&dptr_num);
+ if (Protocol < PROTOCOL_NT1) {
+ reply_doserror(req, ERRDOS, ERRnofiles);
+ return;
} else {
reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
ERRDOS, ERRbadfile);
- goto out;
+ return;
}
}
@@ -2483,8 +2174,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
- if ((! *directory) && dptr_path(sconn, dptr_num)) {
- directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
+ if ((! *directory) && dptr_path(dptr_num)) {
+ directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
if (!directory) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
}
@@ -2506,8 +2197,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
char mangled_name[13];
name_to_8_3(mask, mangled_name, True, conn->params);
}
- out:
- TALLOC_FREE(smb_dname);
+
return;
}
@@ -2554,8 +2244,6 @@ static void call_trans2findnext(connection_struct *conn,
NTSTATUS ntstatus = NT_STATUS_OK;
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
TALLOC_CTX *ctx = talloc_tos();
- struct dptr_struct *dirptr;
- struct smbd_server_connection *sconn = smbd_server_conn;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2649,7 +2337,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
if (!lp_ea_support(SNUM(conn))) {
- reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
+ reply_doserror(req, ERRDOS, ERReasnotsupported);
return;
}
@@ -2681,39 +2369,39 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
params = *pparams;
/* Check that the dptr is valid */
- if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
- reply_nterror(req, STATUS_NO_MORE_FILES);
+ if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
+ reply_doserror(req, ERRDOS, ERRnofiles);
return;
}
- directory = dptr_path(sconn, dptr_num);
+ string_set(&conn->dirpath,dptr_path(dptr_num));
/* Get the wildcard mask from the dptr */
- if((p = dptr_wcard(sconn, dptr_num))== NULL) {
+ if((p = dptr_wcard(dptr_num))== NULL) {
DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
- reply_nterror(req, STATUS_NO_MORE_FILES);
+ reply_doserror(req, ERRDOS, ERRnofiles);
return;
}
mask = p;
+ directory = conn->dirpath;
/* Get the attr mask from the dptr */
- dirtype = dptr_attr(sconn, dptr_num);
+ dirtype = dptr_attr(dptr_num);
DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
dptr_num, mask, dirtype,
- (long)dirptr,
- dptr_TellDir(dirptr)));
+ (long)conn->dirptr,
+ dptr_TellDir(conn->dirptr)));
/* Initialize per TRANS2_FIND_NEXT operation data */
- dptr_init_search_op(dirptr);
+ dptr_init_search_op(conn->dirptr);
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
- DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
+ if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
@@ -2755,7 +2443,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
* should already be at the correct place.
*/
- finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
+ finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
} /* end if resume_name && !continue_bit */
for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
@@ -2769,7 +2457,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
} else {
finished = !get_lanman2_dir_entry(ctx,
conn,
- dirptr,
req->flags2,
mask,dirtype,info_level,
requires_resume_key,dont_descend,
@@ -2806,7 +2493,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
/* Check if we can close the dirptr */
if(close_after_request || (finished && close_if_end)) {
DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
- dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
+ dptr_close(&dptr_num); /* This frees up the saved mask */
}
/* Set up the return parameter block */
@@ -2862,48 +2549,67 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info)
"%s", samba_version_string());
}
-NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- uint16_t flags2,
- unsigned int max_data_bytes,
- char **ppdata,
- int *ret_data_len)
+/****************************************************************************
+ Reply to a TRANS2_QFSINFO (query filesystem info).
+****************************************************************************/
+
+static void call_trans2qfsinfo(connection_struct *conn,
+ struct smb_request *req,
+ char **pparams, int total_params,
+ char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *pdata, *end_data;
- int data_len = 0, len;
+ char *params = *pparams;
+ uint16 info_level;
+ int data_len, len;
+ SMB_STRUCT_STAT st;
const char *vname = volume_label(SNUM(conn));
int snum = SNUM(conn);
char *fstype = lp_fstype(SNUM(conn));
uint32 additional_flags = 0;
- struct smb_filename smb_fname_dot;
- SMB_STRUCT_STAT st;
+
+ if (total_params < 2) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ info_level = SVAL(params,0);
if (IS_IPC(conn)) {
if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
- DEBUG(0,("smbd_do_qfsinfo: not an allowed "
+ DEBUG(0,("call_trans2qfsinfo: not an allowed "
"info level (0x%x) on IPC$.\n",
(unsigned int)info_level));
- return NT_STATUS_ACCESS_DENIED;
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ return;
}
}
- DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
+ if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
+ DEBUG(0,("call_trans2qfsinfo: encryption required "
+ "and info level 0x%x sent.\n",
+ (unsigned int)info_level));
+ exit_server_cleanly("encryption required "
+ "on connection");
+ return;
+ }
+ }
- ZERO_STRUCT(smb_fname_dot);
- smb_fname_dot.base_name = discard_const_p(char, ".");
+ DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
- if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
- DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
- return map_nt_error_from_unix(errno);
+ if(SMB_VFS_STAT(conn,".",&st)!=0) {
+ DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
+ reply_doserror(req, ERRSRV, ERRinvdevice);
+ return;
}
- st = smb_fname_dot.st;
-
*ppdata = (char *)SMB_REALLOC(
*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
- if (*ppdata == NULL) {
- return NT_STATUS_NO_MEMORY;
+ if (*ppdata == NULL ) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
}
pdata = *ppdata;
@@ -2916,7 +2622,8 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 18;
if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
- return map_nt_error_from_unix(errno);
+ reply_unixerror(req, ERRHRD, ERRgeneral);
+ return;
}
block_size = lp_block_size(snum);
@@ -2935,11 +2642,11 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
- DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
-cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
+ DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
+cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
- SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
+ SIVAL(pdata,l1_idFileSystem,st.st_dev);
SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
SIVAL(pdata,l1_cUnit,dsize);
SIVAL(pdata,l1_cUnitAvail,dfree);
@@ -2961,15 +2668,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
* the pushed string. The change here was adding the STR_TERMINATE. JRA.
*/
len = srvstr_push(
- pdata, flags2,
+ pdata, req->flags2,
pdata+l2_vol_szVolLabel, vname,
PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
STR_NOALIGN|STR_TERMINATE);
SCVAL(pdata,l2_vol_cch,len);
data_len = l2_vol_szVolLabel + len;
- DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
- (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
- len, vname));
+ DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
+ (unsigned)st.st_ctime, len, vname));
break;
case SMB_QUERY_FS_ATTRIBUTE_INFO:
@@ -2997,7 +2703,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
SIVAL(pdata,4,255); /* Max filename component length */
/* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
and will think we can't do long filenames */
- len = srvstr_push(pdata, flags2, pdata+12, fstype,
+ len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
PTR_DIFF(end_data, pdata+12),
STR_UNICODE);
SIVAL(pdata,8,len);
@@ -3006,7 +2712,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
case SMB_QUERY_FS_LABEL_INFO:
case SMB_FS_LABEL_INFORMATION:
- len = srvstr_push(pdata, flags2, pdata+4, vname,
+ len = srvstr_push(pdata, req->flags2, pdata+4, vname,
PTR_DIFF(end_data, pdata+4), 0);
data_len = 4 + len;
SIVAL(pdata,0,len);
@@ -3023,13 +2729,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
(str_checksum(get_local_machine_name())<<16));
/* Max label len is 32 characters. */
- len = srvstr_push(pdata, flags2, pdata+18, vname,
+ len = srvstr_push(pdata, req->flags2, pdata+18, vname,
PTR_DIFF(end_data, pdata+18),
STR_UNICODE);
SIVAL(pdata,12,len);
data_len = 18+len;
- DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
(int)strlen(vname),vname, lp_servicename(snum)));
break;
@@ -3039,7 +2745,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 24;
if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
- return map_nt_error_from_unix(errno);
+ reply_unixerror(req, ERRHRD, ERRgeneral);
+ return;
}
block_size = lp_block_size(snum);
if (bsize < block_size) {
@@ -3056,7 +2763,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
}
bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
- DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
SBIG_UINT(pdata,0,dsize);
@@ -3071,7 +2778,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 32;
if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
- return map_nt_error_from_unix(errno);
+ reply_unixerror(req, ERRHRD, ERRgeneral);
+ return;
}
block_size = lp_block_size(snum);
if (bsize < block_size) {
@@ -3088,7 +2796,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
- DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
@@ -3133,50 +2841,51 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
*/
files_struct fsp;
SMB_NTQUOTA_STRUCT quotas;
-
+
ZERO_STRUCT(fsp);
ZERO_STRUCT(quotas);
-
+
fsp.conn = conn;
fsp.fnum = -1;
-
+
/* access check */
- if (conn->server_info->utok.uid != sec_initial_uid()) {
+ if (conn->server_info->utok.uid != 0) {
DEBUG(0,("set_user_quota: access_denied "
"service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
- return NT_STATUS_ACCESS_DENIED;
+ reply_doserror(req, ERRDOS, ERRnoaccess);
+ return;
}
-
+
if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
- return map_nt_error_from_unix(errno);
+ reply_doserror(req, ERRSRV, ERRerror);
+ return;
}
data_len = 48;
- DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
- lp_servicename(SNUM(conn))));
-
+ DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
+
/* Unknown1 24 NULL bytes*/
SBIG_UINT(pdata,0,(uint64_t)0);
SBIG_UINT(pdata,8,(uint64_t)0);
SBIG_UINT(pdata,16,(uint64_t)0);
-
+
/* Default Soft Quota 8 bytes */
SBIG_UINT(pdata,24,quotas.softlim);
/* Default Hard Quota 8 bytes */
SBIG_UINT(pdata,32,quotas.hardlim);
-
+
/* Quota flag 2 bytes */
SSVAL(pdata,40,quotas.qflags);
-
+
/* Unknown3 6 NULL bytes */
SSVAL(pdata,42,0);
SIVAL(pdata,44,0);
-
+
break;
}
#endif /* HAVE_SYS_QUOTAS */
@@ -3203,12 +2912,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
case SMB_QUERY_CIFS_UNIX_INFO:
{
bool large_write = lp_min_receive_file_size() &&
- !srv_is_signing_active(smbd_server_conn);
- bool large_read = !srv_is_signing_active(smbd_server_conn);
+ !srv_is_signing_active();
+ bool large_read = !srv_is_signing_active();
int encrypt_caps = 0;
if (!lp_unix_extensions()) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
switch (conn->encrypt_level) {
@@ -3253,7 +2963,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
vfs_statvfs_struct svfs;
if (!lp_unix_extensions()) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
rc = SMB_VFS_STATVFS(conn, ".", &svfs);
@@ -3268,14 +2979,16 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SBIG_UINT(pdata,32,svfs.TotalFileNodes);
SBIG_UINT(pdata,40,svfs.FreeFileNodes);
SBIG_UINT(pdata,48,svfs.FsIdentifier);
- DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
+ DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
#ifdef EOPNOTSUPP
} else if (rc == EOPNOTSUPP) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
#endif /* EOPNOTSUPP */
} else {
DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
- return NT_STATUS_DOS(ERRSRV, ERRerror);
+ reply_doserror(req, ERRSRV, ERRerror);
+ return;
}
break;
}
@@ -3287,11 +3000,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
int i;
if (!lp_unix_extensions()) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
if (max_data_bytes < 40) {
- return NT_STATUS_BUFFER_TOO_SMALL;
+ reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
+ return;
}
/* We ARE guest if global_sid_Builtin_Guests is
@@ -3405,59 +3120,12 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
/* drop through */
default:
- return NT_STATUS_INVALID_LEVEL;
- }
-
- *ret_data_len = data_len;
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Reply to a TRANS2_QFSINFO (query filesystem info).
-****************************************************************************/
-
-static void call_trans2qfsinfo(connection_struct *conn,
- struct smb_request *req,
- char **pparams, int total_params,
- char **ppdata, int total_data,
- unsigned int max_data_bytes)
-{
- char *params = *pparams;
- uint16_t info_level;
- int data_len = 0;
- NTSTATUS status;
-
- if (total_params < 2) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- info_level = SVAL(params,0);
-
- if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
- if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
- DEBUG(0,("call_trans2qfsinfo: encryption required "
- "and info level 0x%x sent.\n",
- (unsigned int)info_level));
- exit_server_cleanly("encryption required "
- "on connection");
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
- }
}
- DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
-
- status = smbd_do_qfsinfo(conn, req,
- info_level,
- req->flags2,
- max_data_bytes,
- ppdata, &data_len);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
- send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
+ send_trans2_replies(conn, req, params, 0, pdata, data_len,
max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n",
@@ -3624,16 +3292,16 @@ cap_low = 0x%x, cap_high = 0x%x\n",
{
files_struct *fsp = NULL;
SMB_NTQUOTA_STRUCT quotas;
-
+
ZERO_STRUCT(quotas);
/* access check */
- if ((conn->server_info->utok.uid != sec_initial_uid())
+ if ((conn->server_info->utok.uid != 0)
||!CAN_WRITE(conn)) {
DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return;
}
@@ -3659,9 +3327,9 @@ cap_low = 0x%x, cap_high = 0x%x\n",
NT_STATUS_INVALID_PARAMETER);
return;
}
-
+
/* unknown_1 24 NULL bytes in pdata*/
-
+
/* the soft quotas 8 bytes (uint64_t)*/
quotas.softlim = (uint64_t)IVAL(pdata,24);
#ifdef LARGE_SMB_OFF_T
@@ -3677,7 +3345,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
return;
}
#endif /* LARGE_SMB_OFF_T */
-
+
/* the hard quotas 8 bytes (uint64_t)*/
quotas.hardlim = (uint64_t)IVAL(pdata,32);
#ifdef LARGE_SMB_OFF_T
@@ -3693,19 +3361,19 @@ cap_low = 0x%x, cap_high = 0x%x\n",
return;
}
#endif /* LARGE_SMB_OFF_T */
-
+
/* quota_flags 2 bytes **/
quotas.qflags = SVAL(pdata,40);
-
+
/* unknown_2 6 NULL bytes follow*/
-
+
/* now set the quotas */
if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_doserror(req, ERRSRV, ERRerror);
return;
}
-
+
break;
}
default:
@@ -3785,7 +3453,7 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
switch (tagtype) {
case SMB_ACL_USER_OBJ:
SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
- own_grp = (unsigned int)pst->st_ex_uid;
+ own_grp = (unsigned int)pst->st_uid;
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
break;
@@ -3805,7 +3473,7 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
}
case SMB_ACL_GROUP_OBJ:
SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
- own_grp = (unsigned int)pst->st_ex_gid;
+ own_grp = (unsigned int)pst->st_gid;
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
break;
@@ -3854,7 +3522,7 @@ static char *store_file_unix_basic(connection_struct *conn,
const SMB_STRUCT_STAT *psbuf)
{
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
- DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
+ DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
pdata += 8;
@@ -3862,38 +3530,38 @@ static char *store_file_unix_basic(connection_struct *conn,
SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
pdata += 8;
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
pdata += 24;
- SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
+ SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
+ SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
+ SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
pdata += 4;
- SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
+ SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
+ SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
- SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
+ SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
pdata += 8;
-
- SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
+
+ SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
+ SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
SIVAL(pdata,4,0);
pdata += 8;
@@ -3937,14 +3605,16 @@ static const struct {unsigned stat_fflag; unsigned smb_fflag;}
static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
uint32 *smb_fflags, uint32 *smb_fmask)
{
+#ifdef HAVE_STAT_ST_FLAGS
int i;
for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
*smb_fmask |= info2_flags_map[i].smb_fflag;
- if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
+ if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
*smb_fflags |= info2_flags_map[i].smb_fflag;
}
}
+#endif /* HAVE_STAT_ST_FLAGS */
}
static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
@@ -3952,10 +3622,11 @@ static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
const uint32 smb_fmask,
int *stat_fflags)
{
+#ifdef HAVE_STAT_ST_FLAGS
uint32 max_fmask = 0;
int i;
- *stat_fflags = psbuf->st_ex_flags;
+ *stat_fflags = psbuf->st_flags;
/* For each flags requested in smb_fmask, check the state of the
* corresponding flag in smb_fflags and set or clear the matching
@@ -3981,6 +3652,9 @@ static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
}
return True;
+#else
+ return False;
+#endif /* HAVE_STAT_ST_FLAGS */
}
@@ -3998,7 +3672,7 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
/* Create (birth) time 64 bit */
- put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
+ put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, get_create_timespec(psbuf, False));
pdata += 8;
map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
@@ -4137,55 +3811,277 @@ static void call_trans2qpipeinfo(connection_struct *conn,
return;
}
-NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- files_struct *fsp,
- struct smb_filename *smb_fname,
- bool delete_pending,
- struct timespec write_time_ts,
- bool ms_dfs_link,
- struct ea_list *ea_list,
- int lock_data_count,
- char *lock_data,
- uint16_t flags2,
- unsigned int max_data_bytes,
- char **ppdata,
- unsigned int *pdata_size)
+/****************************************************************************
+ Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
+ file name or file id).
+****************************************************************************/
+
+static void call_trans2qfilepathinfo(connection_struct *conn,
+ struct smb_request *req,
+ unsigned int tran_call,
+ char **pparams, int total_params,
+ char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
+ char *params = *pparams;
char *pdata = *ppdata;
char *dstart, *dend;
- unsigned int data_size;
- struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
- time_t create_time, mtime, atime, c_time;
- SMB_STRUCT_STAT *psbuf = &smb_fname->st;
- char *p;
- char *base_name;
- char *dos_fname;
- int mode;
+ uint16 info_level;
+ int mode=0;
int nlink;
- NTSTATUS status;
- uint64_t file_size = 0;
- uint64_t pos = 0;
- uint64_t allocation_size = 0;
- uint64_t file_index = 0;
- uint32_t access_mask = 0;
+ SMB_OFF_T file_size=0;
+ uint64_t allocation_size=0;
+ unsigned int data_size = 0;
+ unsigned int param_size = 2;
+ SMB_STRUCT_STAT sbuf;
+ char *dos_fname = NULL;
+ char *fname = NULL;
+ char *fullpathname;
+ char *base_name;
+ char *p;
+ SMB_OFF_T pos = 0;
+ bool delete_pending = False;
+ int len;
+ time_t create_time, mtime, atime;
+ struct timespec create_time_ts, mtime_ts, atime_ts;
+ struct timespec write_time_ts;
+ files_struct *fsp = NULL;
+ struct file_id fileid;
+ struct ea_list *ea_list = NULL;
+ char *lock_data = NULL;
+ bool ms_dfs_link = false;
+ TALLOC_CTX *ctx = talloc_tos();
+
+ if (!params) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ ZERO_STRUCT(sbuf);
+ ZERO_STRUCT(write_time_ts);
+
+ if (tran_call == TRANSACT2_QFILEINFO) {
+ if (total_params < 4) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ if (IS_IPC(conn)) {
+ call_trans2qpipeinfo(conn, req, tran_call,
+ pparams, total_params,
+ ppdata, total_data,
+ max_data_bytes);
+ return;
+ }
+
+ fsp = file_fsp(req, SVAL(params,0));
+ info_level = SVAL(params,2);
+
+ DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
+
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
+ }
+
+ /* Initial check for valid fsp ptr. */
+ if (!check_fsp_open(conn, req, fsp)) {
+ return;
+ }
+
+ fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+ if (!fname) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ if(fsp->fake_file_handle) {
+ /*
+ * This is actually for the QUOTA_FAKE_FILE --metze
+ */
+
+ /* We know this name is ok, it's already passed the checks. */
+
+ } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+ /*
+ * This is actually a QFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadpath);
+ return;
+ }
+
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ get_file_infos(fileid, &delete_pending, &write_time_ts);
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+ if (!check_fsp(conn, req, fsp)) {
+ return;
+ }
+
+ if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
+ DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadfid);
+ return;
+ }
+ pos = fsp->fh->position_information;
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ get_file_infos(fileid, &delete_pending, &write_time_ts);
+ }
+
+ } else {
+ NTSTATUS status = NT_STATUS_OK;
+
+ /* qpathinfo */
+ if (total_params < 7) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ info_level = SVAL(params,0);
+
+ DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
+
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
+ }
+
+ srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
+ total_params - 6,
+ STR_TERMINATE, &status);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = resolve_dfspath(ctx,
+ conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req,
+ NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ }
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
+ reply_nterror(req, status);
+ return;
+ }
+
+ if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
+ && is_ntfs_stream_name(fname)) {
+ char *base;
+ SMB_STRUCT_STAT bsbuf;
+
+ status = split_ntfs_stream_name(talloc_tos(), fname,
+ &base, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("create_file_unixpath: "
+ "split_ntfs_stream_name failed: %s\n",
+ nt_errstr(status)));
+ reply_nterror(req, status);
+ return;
+ }
+
+ SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ } else {
+ if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
+ DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ }
+
+ fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
+ get_file_infos(fileid, &delete_pending, NULL);
+ if (delete_pending) {
+ reply_nterror(req, NT_STATUS_DELETE_PENDING);
+ return;
+ }
+ }
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadpath);
+ return;
+ }
+
+ } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
+ ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
+
+ if (!ms_dfs_link) {
+ DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadpath);
+ return;
+ }
+ }
+
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ get_file_infos(fileid, &delete_pending, &write_time_ts);
+ if (delete_pending) {
+ reply_nterror(req, NT_STATUS_DELETE_PENDING);
+ return;
+ }
+ }
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
- DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
- smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
- info_level, max_data_bytes));
+ DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
+ fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
+
+ p = strrchr_m(fname,'/');
+ if (!p)
+ base_name = fname;
+ else
+ base_name = p+1;
if (ms_dfs_link) {
- mode = dos_mode_msdfs(conn, smb_fname);
+ mode = dos_mode_msdfs(conn,fname,&sbuf);
} else {
- mode = dos_mode(conn, smb_fname);
+ mode = dos_mode(conn,fname,&sbuf);
}
- nlink = psbuf->st_ex_nlink;
+ nlink = sbuf.st_nlink;
if (nlink && (mode&aDIR)) {
nlink = 1;
@@ -4195,105 +4091,142 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
nlink -= 1;
}
+ fullpathname = fname;
+ if (!(mode & aDIR))
+ file_size = get_file_size_stat(&sbuf);
+
+ /* Pull out any data sent here before we realloc. */
+ switch (info_level) {
+ case SMB_INFO_QUERY_EAS_FROM_LIST:
+ {
+ /* Pull any EA list from the data portion. */
+ uint32 ea_size;
+
+ if (total_data < 4) {
+ reply_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ ea_size = IVAL(pdata,0);
+
+ if (total_data > 0 && ea_size != total_data) {
+ DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
+total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
+ reply_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ if (!lp_ea_support(SNUM(conn))) {
+ reply_doserror(req, ERRDOS,
+ ERReasnotsupported);
+ return;
+ }
+
+ /* Pull out the list of names. */
+ ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
+ if (!ea_list) {
+ reply_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ break;
+ }
+
+ case SMB_QUERY_POSIX_LOCK:
+ {
+ if (fsp == NULL || fsp->fh->fd == -1) {
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ return;
+ }
+
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ reply_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ /* Copy the lock range data. */
+ lock_data = (char *)TALLOC_MEMDUP(
+ ctx, pdata, total_data);
+ if (!lock_data) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ }
+ default:
+ break;
+ }
+
+ *pparams = (char *)SMB_REALLOC(*pparams,2);
+ if (*pparams == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ params = *pparams;
+ SSVAL(params,0,0);
data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
*ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
- if (*ppdata == NULL) {
- return NT_STATUS_NO_MEMORY;
+ if (*ppdata == NULL ) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
}
pdata = *ppdata;
dstart = pdata;
dend = dstart + data_size - 1;
- if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
- update_stat_ex_mtime(psbuf, write_time_ts);
+ create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ mtime_ts = get_mtimespec(&sbuf);
+ atime_ts = get_atimespec(&sbuf);
+
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
+
+ if (!fsp) {
+ /* Do we have this path open ? */
+ files_struct *fsp1;
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ fsp1 = file_find_di_first(fileid);
+ if (fsp1 && fsp1->initial_allocation_size) {
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
+ }
}
- create_time_ts = get_create_timespec(conn, fsp, smb_fname);
- mtime_ts = psbuf->st_ex_mtime;
- atime_ts = psbuf->st_ex_atime;
- ctime_ts = get_change_timespec(conn, fsp, smb_fname);
+ if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
+ mtime_ts = write_time_ts;
+ }
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_time_ts);
dos_filetime_timespec(&mtime_ts);
dos_filetime_timespec(&atime_ts);
- dos_filetime_timespec(&ctime_ts);
}
create_time = convert_timespec_to_time_t(create_time_ts);
mtime = convert_timespec_to_time_t(mtime_ts);
atime = convert_timespec_to_time_t(atime_ts);
- c_time = convert_timespec_to_time_t(ctime_ts);
-
- p = strrchr_m(smb_fname->base_name,'/');
- if (!p)
- base_name = smb_fname->base_name;
- else
- base_name = p+1;
/* NT expects the name to be in an exact form of the *full*
filename. See the trans2 torture test */
if (ISDOT(base_name)) {
- dos_fname = talloc_strdup(mem_ctx, "\\");
+ dos_fname = talloc_strdup(ctx, "\\");
if (!dos_fname) {
- return NT_STATUS_NO_MEMORY;
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
}
} else {
- dos_fname = talloc_asprintf(mem_ctx,
+ dos_fname = talloc_asprintf(ctx,
"\\%s",
- smb_fname->base_name);
+ fname);
if (!dos_fname) {
- return NT_STATUS_NO_MEMORY;
- }
- if (is_ntfs_stream_smb_fname(smb_fname)) {
- dos_fname = talloc_asprintf(dos_fname, "%s",
- smb_fname->stream_name);
- if (!dos_fname) {
- return NT_STATUS_NO_MEMORY;
- }
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
}
-
string_replace(dos_fname, '/', '\\');
}
- allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
-
- if (!fsp) {
- /* Do we have this path open ? */
- files_struct *fsp1;
- struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
- fsp1 = file_find_di_first(fileid);
- if (fsp1 && fsp1->initial_allocation_size) {
- allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
- }
- }
-
- if (!(mode & aDIR)) {
- file_size = get_file_size_stat(psbuf);
- }
-
- if (fsp) {
- pos = fsp->fh->position_information;
- }
-
- if (fsp) {
- access_mask = fsp->access_mask;
- } else {
- /* GENERIC_EXECUTE mapping from Windows */
- access_mask = 0x12019F;
- }
-
- /* This should be an index number - looks like
- dev/ino to me :-)
-
- I think this causes us to fail the IFSKIT
- BasicFileInformationTest. -tpot */
- file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
- file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
-
switch (info_level) {
case SMB_INFO_STANDARD:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
data_size = 22;
srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
@@ -4305,10 +4238,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_INFO_QUERY_EA_SIZE:
{
- unsigned int ea_size =
- estimate_ea_size(conn, fsp,
- smb_fname->base_name);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
+ unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
data_size = 26;
srv_put_dos_date2(pdata,0,create_time);
srv_put_dos_date2(pdata,4,atime);
@@ -4321,13 +4252,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
}
case SMB_INFO_IS_NAME_VALID:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
- if (fsp) {
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
+ if (tran_call == TRANSACT2_QFILEINFO) {
/* os/2 needs this ? really ?*/
- return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
+ return;
}
- /* This is only reached for qpathinfo */
data_size = 0;
+ param_size = 0;
break;
case SMB_INFO_QUERY_EAS_FROM_LIST:
@@ -4335,12 +4267,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
size_t total_ea_len = 0;
struct ea_list *ea_file_list = NULL;
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
- ea_file_list =
- get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
@@ -4349,7 +4278,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
break;
}
- data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
+ data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
break;
}
@@ -4358,50 +4287,16 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0;
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
- ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
data_size = 4;
SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
break;
}
- data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
- break;
- }
-
- case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
- {
- /* This is FileFullEaInformation - 0xF which maps to
- * 1015 (decimal) in smbd_do_setfilepathinfo. */
-
- /* We have data_size bytes to put EA's into. */
- size_t total_ea_len = 0;
- struct ea_list *ea_file_list = NULL;
-
- DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
-
- /*TODO: add filtering and index handling */
-
- ea_file_list =
- get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
- if (!ea_file_list) {
- return NT_STATUS_NO_EAS_ON_FILE;
- }
-
- status = fill_ea_chained_buffer(mem_ctx,
- pdata,
- data_size,
- &data_size,
- conn, ea_file_list);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
break;
}
@@ -4409,31 +4304,31 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_BASIC_INFO:
if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
} else {
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
data_size = 40;
SIVAL(pdata,36,0);
}
- put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
- put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
- put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
+ put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
SIVAL(pdata,32,mode);
DEBUG(5,("SMB_QFBI - "));
DEBUG(5,("create: %s ", ctime(&create_time)));
DEBUG(5,("access: %s ", ctime(&atime)));
DEBUG(5,("write: %s ", ctime(&mtime)));
- DEBUG(5,("change: %s ", ctime(&c_time)));
+ DEBUG(5,("change: %s ", ctime(&mtime)));
DEBUG(5,("mode: %x\n", mode));
break;
case SMB_FILE_STANDARD_INFORMATION:
case SMB_QUERY_FILE_STANDARD_INFO:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
data_size = 24;
SOFF_T(pdata,0,allocation_size);
SOFF_T(pdata,8,file_size);
@@ -4446,9 +4341,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_FILE_EA_INFORMATION:
case SMB_QUERY_FILE_EA_INFO:
{
- unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
+ unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
data_size = 4;
SIVAL(pdata,0,ea_size);
break;
@@ -4458,14 +4352,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_ALT_NAME_INFO:
case SMB_FILE_ALTERNATE_NAME_INFORMATION:
{
- int len;
char mangled_name[13];
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
if (!name_to_8_3(base_name,mangled_name,
True,conn->params)) {
- return NT_STATUS_NO_MEMORY;
+ reply_nterror(
+ req,
+ NT_STATUS_NO_MEMORY);
}
- len = srvstr_push(dstart, flags2,
+ len = srvstr_push(dstart, req->flags2,
pdata+4, mangled_name,
PTR_DIFF(dend, pdata+4),
STR_UNICODE);
@@ -4475,31 +4370,28 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
}
case SMB_QUERY_FILE_NAME_INFO:
- {
- int len;
/*
this must be *exactly* right for ACLs on mapped drives to work
*/
- len = srvstr_push(dstart, flags2,
+ len = srvstr_push(dstart, req->flags2,
pdata+4, dos_fname,
PTR_DIFF(dend, pdata+4),
STR_UNICODE);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
data_size = 4 + len;
SIVAL(pdata,0,len);
break;
- }
case SMB_FILE_ALLOCATION_INFORMATION:
case SMB_QUERY_FILE_ALLOCATION_INFO:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
data_size = 8;
SOFF_T(pdata,0,allocation_size);
break;
case SMB_FILE_END_OF_FILE_INFORMATION:
case SMB_QUERY_FILE_END_OF_FILEINFO:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
data_size = 8;
SOFF_T(pdata,0,file_size);
break;
@@ -4507,14 +4399,12 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_ALL_INFO:
case SMB_FILE_ALL_INFORMATION:
{
- int len;
- unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
- put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
- put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
- put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
+ unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
+ put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
SIVAL(pdata,32,mode);
SIVAL(pdata,36,0); /* padding. */
pdata += 40;
@@ -4527,44 +4417,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
pdata += 24;
SIVAL(pdata,0,ea_size);
pdata += 4; /* EA info */
- len = srvstr_push(dstart, flags2,
- pdata+4, dos_fname,
- PTR_DIFF(dend, pdata+4),
- STR_UNICODE);
- SIVAL(pdata,0,len);
- pdata += 4 + len;
- data_size = PTR_DIFF(pdata,(*ppdata));
- break;
- }
-
- case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
- {
- int len;
- unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
- put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
- put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
- put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
- put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
- SIVAL(pdata, 0x20, mode);
- SIVAL(pdata, 0x24, 0); /* padding. */
- SBVAL(pdata, 0x28, allocation_size);
- SBVAL(pdata, 0x30, file_size);
- SIVAL(pdata, 0x38, nlink);
- SCVAL(pdata, 0x3C, delete_pending);
- SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
- SSVAL(pdata, 0x3E, 0); /* padding */
- SBVAL(pdata, 0x40, file_index);
- SIVAL(pdata, 0x48, ea_size);
- SIVAL(pdata, 0x4C, access_mask);
- SBVAL(pdata, 0x50, pos);
- SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
- SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
-
- pdata += 0x60;
-
- len = srvstr_push(dstart, flags2,
+ len = srvstr_push(dstart, req->flags2,
pdata+4, dos_fname,
PTR_DIFF(dend, pdata+4),
STR_UNICODE);
@@ -4574,15 +4427,26 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
break;
}
case SMB_FILE_INTERNAL_INFORMATION:
+ /* This should be an index number - looks like
+ dev/ino to me :-)
+
+ I think this causes us to fail the IFSKIT
+ BasicFileInformationTest. -tpot */
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
- SBVAL(pdata, 0, file_index);
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
+ SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
+ SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
data_size = 8;
break;
case SMB_FILE_ACCESS_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
- SIVAL(pdata, 0, access_mask);
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
+ if (fsp) {
+ SIVAL(pdata,0,fsp->access_mask);
+ } else {
+ /* GENERIC_EXECUTE mapping from Windows */
+ SIVAL(pdata,0,0x12019F);
+ }
data_size = 4;
break;
@@ -4591,32 +4455,32 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
size_t byte_len;
byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
SIVAL(pdata,0,byte_len);
data_size = 4 + byte_len;
break;
}
case SMB_FILE_DISPOSITION_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
data_size = 1;
SCVAL(pdata,0,delete_pending);
break;
case SMB_FILE_POSITION_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
data_size = 8;
SOFF_T(pdata,0,pos);
break;
case SMB_FILE_MODE_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
SIVAL(pdata,0,mode);
data_size = 4;
break;
case SMB_FILE_ALIGNMENT_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
SIVAL(pdata,0,0); /* No alignment needed. */
data_size = 4;
break;
@@ -4633,22 +4497,20 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_FILE_STREAM_INFORMATION: {
unsigned int num_streams;
struct stream_struct *streams;
+ NTSTATUS status;
- DEBUG(10,("smbd_do_qfilepathinfo: "
+ DEBUG(10,("call_trans2qfilepathinfo: "
"SMB_FILE_STREAM_INFORMATION\n"));
- if (is_ntfs_stream_smb_fname(smb_fname)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
status = SMB_VFS_STREAMINFO(
- conn, fsp, smb_fname->base_name, talloc_tos(),
+ conn, fsp, fname, talloc_tos(),
&num_streams, &streams);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("could not get stream info: %s\n",
nt_errstr(status)));
- return status;
+ reply_nterror(req, status);
+ return;
}
status = marshall_stream_info(num_streams, streams,
@@ -4658,7 +4520,8 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("marshall_stream_info failed: %s\n",
nt_errstr(status)));
- return status;
+ reply_nterror(req, status);
+ return;
}
TALLOC_FREE(streams);
@@ -4667,7 +4530,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
}
case SMB_QUERY_COMPRESSION_INFO:
case SMB_FILE_COMPRESSION_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
SOFF_T(pdata,0,file_size);
SIVAL(pdata,8,0); /* ??? */
SIVAL(pdata,12,0); /* ??? */
@@ -4675,11 +4538,11 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
break;
case SMB_FILE_NETWORK_OPEN_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
- put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
- put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
- put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
- put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
+ put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
+ put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
+ put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
+ put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
SOFF_T(pdata,32,allocation_size);
SOFF_T(pdata,40,file_size);
SIVAL(pdata,48,mode);
@@ -4688,7 +4551,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
break;
case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
SIVAL(pdata,0,mode);
SIVAL(pdata,4,0);
data_size = 8;
@@ -4700,12 +4563,12 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_BASIC:
- pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
+ pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
data_size = PTR_DIFF(pdata,(*ppdata));
{
int i;
- DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
for (i=0; i<100; i++)
DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
@@ -4716,12 +4579,12 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_INFO2:
- pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
+ pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
data_size = PTR_DIFF(pdata,(*ppdata));
{
int i;
- DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
for (i=0; i<100; i++)
DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
@@ -4732,29 +4595,33 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_LINK:
{
- int len;
- char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
+ char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
if (!buffer) {
- return NT_STATUS_NO_MEMORY;
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
}
- DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
+ DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
#ifdef S_ISLNK
- if(!S_ISLNK(psbuf->st_ex_mode)) {
- return NT_STATUS_DOS(ERRSRV, ERRbadlink);
+ if(!S_ISLNK(sbuf.st_mode)) {
+ reply_unixerror(req, ERRSRV,
+ ERRbadlink);
+ return;
}
#else
- return NT_STATUS_DOS(ERRDOS, ERRbadlink);
+ reply_unixerror(req, ERRDOS, ERRbadlink);
+ return;
#endif
- len = SMB_VFS_READLINK(conn,
- smb_fname->base_name,
- buffer, PATH_MAX);
+ len = SMB_VFS_READLINK(conn,fullpathname,
+ buffer, PATH_MAX);
if (len == -1) {
- return map_nt_error_from_unix(errno);
+ reply_unixerror(req, ERRDOS,
+ ERRnoaccess);
+ return;
}
buffer[len] = 0;
- len = srvstr_push(dstart, flags2,
+ len = srvstr_push(dstart, req->flags2,
pdata, buffer,
PTR_DIFF(dend, pdata),
STR_TERMINATE);
@@ -4775,33 +4642,23 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
} else {
- file_acl =
- SMB_VFS_SYS_ACL_GET_FILE(conn,
- smb_fname->base_name,
- SMB_ACL_TYPE_ACCESS);
+ file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
}
if (file_acl == NULL && no_acl_syscall_error(errno)) {
- DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
- "not implemented on "
- "filesystem containing %s\n",
- smb_fname->base_name));
- return NT_STATUS_NOT_IMPLEMENTED;
+ DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
+ fname ));
+ reply_nterror(
+ req,
+ NT_STATUS_NOT_IMPLEMENTED);
+ return;
}
- if (S_ISDIR(psbuf->st_ex_mode)) {
+ if (S_ISDIR(sbuf.st_mode)) {
if (fsp && fsp->is_directory) {
- def_acl =
- SMB_VFS_SYS_ACL_GET_FILE(
- conn,
- fsp->fsp_name->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
} else {
- def_acl =
- SMB_VFS_SYS_ACL_GET_FILE(
- conn,
- smb_fname->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
}
def_acl = free_empty_sys_acl(conn, def_acl);
}
@@ -4810,7 +4667,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
num_def_acls = count_acl_entries(conn, def_acl);
if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
- DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
+ DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
data_size,
(unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
SMB_POSIX_ACL_HEADER_SIZE) ));
@@ -4820,29 +4677,37 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
if (def_acl) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
}
- return NT_STATUS_BUFFER_TOO_SMALL;
+ reply_nterror(
+ req,
+ NT_STATUS_BUFFER_TOO_SMALL);
+ return;
}
SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
SSVAL(pdata,2,num_file_acls);
SSVAL(pdata,4,num_def_acls);
- if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
+ if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
if (file_acl) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
}
if (def_acl) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
}
- return NT_STATUS_INTERNAL_ERROR;
+ reply_nterror(
+ req, NT_STATUS_INTERNAL_ERROR);
+ return;
}
- if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
+ if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
if (file_acl) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
}
if (def_acl) {
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
}
- return NT_STATUS_INTERNAL_ERROR;
+ reply_nterror(
+ req,
+ NT_STATUS_INTERNAL_ERROR);
+ return;
}
if (file_acl) {
@@ -4859,18 +4724,16 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_POSIX_LOCK:
{
+ NTSTATUS status = NT_STATUS_INVALID_LEVEL;
uint64_t count;
uint64_t offset;
uint32 lock_pid;
enum brl_type lock_type;
- /* We need an open file with a real fd for this. */
- if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
- return NT_STATUS_INVALID_PARAMETER;
+ if (total_data != POSIX_LOCK_DATA_SIZE) {
+ reply_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return;
}
switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
@@ -4883,7 +4746,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case POSIX_LOCK_TYPE_UNLOCK:
default:
/* There's no point in asking for an unlock... */
- return NT_STATUS_INVALID_PARAMETER;
+ reply_nterror(
+ req,
+ NT_STATUS_INVALID_PARAMETER);
+ return;
}
lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
@@ -4928,394 +4794,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
} else {
- return status;
- }
- break;
- }
-
- default:
- return NT_STATUS_INVALID_LEVEL;
- }
-
- *pdata_size = data_size;
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
- file name or file id).
-****************************************************************************/
-
-static void call_trans2qfilepathinfo(connection_struct *conn,
- struct smb_request *req,
- unsigned int tran_call,
- char **pparams, int total_params,
- char **ppdata, int total_data,
- unsigned int max_data_bytes)
-{
- char *params = *pparams;
- char *pdata = *ppdata;
- uint16 info_level;
- unsigned int data_size = 0;
- unsigned int param_size = 2;
- struct smb_filename *smb_fname = NULL;
- bool delete_pending = False;
- struct timespec write_time_ts;
- files_struct *fsp = NULL;
- struct file_id fileid;
- struct ea_list *ea_list = NULL;
- int lock_data_count = 0;
- char *lock_data = NULL;
- bool ms_dfs_link = false;
- NTSTATUS status = NT_STATUS_OK;
-
- if (!params) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- ZERO_STRUCT(write_time_ts);
-
- if (tran_call == TRANSACT2_QFILEINFO) {
- if (total_params < 4) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- if (IS_IPC(conn)) {
- call_trans2qpipeinfo(conn, req, tran_call,
- pparams, total_params,
- ppdata, total_data,
- max_data_bytes);
- return;
- }
-
- fsp = file_fsp(req, SVAL(params,0));
- info_level = SVAL(params,2);
-
- DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
-
- if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
- return;
- }
-
- /* Initial check for valid fsp ptr. */
- if (!check_fsp_open(conn, req, fsp)) {
- return;
- }
-
- status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- if(fsp->fake_file_handle) {
- /*
- * This is actually for the QUOTA_FAKE_FILE --metze
- */
-
- /* We know this name is ok, it's already passed the checks. */
-
- } else if(fsp->is_directory || fsp->fh->fd == -1) {
- /*
- * This is actually a QFILEINFO on a directory
- * handle (returned from an NT SMB). NT5.0 seems
- * to do this call. JRA.
- */
-
- if (INFO_LEVEL_IS_UNIX(info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, smb_fname)) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "SMB_VFS_LSTAT of %s failed "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
- } else if (SMB_VFS_STAT(conn, smb_fname)) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "SMB_VFS_STAT of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
-
- fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
- get_file_infos(fileid, &delete_pending, &write_time_ts);
- } else {
- /*
- * Original code - this is an open file.
- */
- if (!check_fsp(conn, req, fsp)) {
- return;
- }
-
- if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
- DEBUG(3, ("fstat of fnum %d failed (%s)\n",
- fsp->fnum, strerror(errno)));
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
- fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
- get_file_infos(fileid, &delete_pending, &write_time_ts);
- }
-
- } else {
- char *fname = NULL;
-
- /* qpathinfo */
- if (total_params < 7) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- info_level = SVAL(params,0);
-
- DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
-
- if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
- return;
- }
-
- srvstr_get_path(req, params, req->flags2, &fname, &params[6],
- total_params - 6,
- STR_TERMINATE, &status);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- status = filename_convert(req,
- conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- return;
- }
- reply_nterror(req, status);
- return;
- }
-
- /* If this is a stream, check if there is a delete_pending. */
- if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
- && is_ntfs_stream_smb_fname(smb_fname)) {
- struct smb_filename *smb_fname_base = NULL;
-
- /* Create an smb_filename with stream_name == NULL. */
- status =
- create_synthetic_smb_fname(talloc_tos(),
- smb_fname->base_name,
- NULL, NULL,
- &smb_fname_base);
- if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
-
- if (INFO_LEVEL_IS_UNIX(info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "SMB_VFS_LSTAT of %s failed "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname_base),
- strerror(errno)));
- TALLOC_FREE(smb_fname_base);
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
- } else {
- if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "fileinfo of %s failed "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname_base),
- strerror(errno)));
- TALLOC_FREE(smb_fname_base);
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
- }
-
- fileid = vfs_file_id_from_sbuf(conn,
- &smb_fname_base->st);
- TALLOC_FREE(smb_fname_base);
- get_file_infos(fileid, &delete_pending, NULL);
- if (delete_pending) {
- reply_nterror(req, NT_STATUS_DELETE_PENDING);
- return;
- }
- }
-
- if (INFO_LEVEL_IS_UNIX(info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, smb_fname)) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "SMB_VFS_LSTAT of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
-
- } else if (!VALID_STAT(smb_fname->st) &&
- SMB_VFS_STAT(conn, smb_fname) &&
- (info_level != SMB_INFO_IS_NAME_VALID)) {
- ms_dfs_link = check_msdfs_link(conn,
- smb_fname->base_name,
- &smb_fname->st);
-
- if (!ms_dfs_link) {
- DEBUG(3,("call_trans2qfilepathinfo: "
- "SMB_VFS_STAT of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req,
- map_nt_error_from_unix(errno));
- return;
- }
- }
-
- fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
- get_file_infos(fileid, &delete_pending, &write_time_ts);
- if (delete_pending) {
- reply_nterror(req, NT_STATUS_DELETE_PENDING);
- return;
- }
- }
-
- DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
- "total_data=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
-
- /* Pull out any data sent here before we realloc. */
- switch (info_level) {
- case SMB_INFO_QUERY_EAS_FROM_LIST:
- {
- /* Pull any EA list from the data portion. */
- uint32 ea_size;
-
- if (total_data < 4) {
- reply_nterror(
- req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
- ea_size = IVAL(pdata,0);
-
- if (total_data > 0 && ea_size != total_data) {
- DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
-total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
- reply_nterror(
- req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- if (!lp_ea_support(SNUM(conn))) {
- reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- return;
- }
-
- /* Pull out the list of names. */
- ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
- if (!ea_list) {
- reply_nterror(
- req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
break;
}
- case SMB_QUERY_POSIX_LOCK:
- {
- if (fsp == NULL || fsp->fh->fd == -1) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
- return;
- }
-
- if (total_data != POSIX_LOCK_DATA_SIZE) {
- reply_nterror(
- req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- /* Copy the lock range data. */
- lock_data = (char *)TALLOC_MEMDUP(
- req, pdata, total_data);
- if (!lock_data) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- lock_data_count = total_data;
- }
default:
- break;
- }
-
- *pparams = (char *)SMB_REALLOC(*pparams,2);
- if (*pparams == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
- }
- params = *pparams;
- SSVAL(params,0,0);
-
- /*
- * draft-leach-cifs-v1-spec-02.txt
- * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
- * says:
- *
- * The requested information is placed in the Data portion of the
- * transaction response. For the information levels greater than 0x100,
- * the transaction response has 1 parameter word which should be
- * ignored by the client.
- *
- * However Windows only follows this rule for the IS_NAME_VALID call.
- */
- switch (info_level) {
- case SMB_INFO_IS_NAME_VALID:
- param_size = 0;
- break;
- }
-
- if ((info_level & 0xFF00) == 0xFF00) {
- /*
- * We use levels that start with 0xFF00
- * internally to represent SMB2 specific levels
- */
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
- return;
- }
-
- status = smbd_do_qfilepathinfo(conn, req, info_level,
- fsp, smb_fname,
- delete_pending, write_time_ts,
- ms_dfs_link, ea_list,
- lock_data_count, lock_data,
- req->flags2, max_data_bytes,
- ppdata, &data_size);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
@@ -5331,42 +4818,70 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
connection_struct *conn,
- const struct smb_filename *smb_fname_old,
- const struct smb_filename *smb_fname_new)
+ const char *oldname_in,
+ const char *newname_in)
{
+ SMB_STRUCT_STAT sbuf1, sbuf2;
+ char *last_component_oldname = NULL;
+ char *last_component_newname = NULL;
+ char *oldname = NULL;
+ char *newname = NULL;
NTSTATUS status = NT_STATUS_OK;
+ ZERO_STRUCT(sbuf1);
+ ZERO_STRUCT(sbuf2);
+
+ status = unix_convert(ctx, conn, oldname_in, False, &oldname,
+ &last_component_oldname, &sbuf1);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* source must already exist. */
- if (!VALID_STAT(smb_fname_old->st)) {
+ if (!VALID_STAT(sbuf1)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ status = unix_convert(ctx, conn, newname_in, False, &newname,
+ &last_component_newname, &sbuf2);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* Disallow if newname already exists. */
- if (VALID_STAT(smb_fname_new->st)) {
+ if (VALID_STAT(sbuf2)) {
return NT_STATUS_OBJECT_NAME_COLLISION;
}
/* No links from a directory. */
- if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
+ if (S_ISDIR(sbuf1.st_mode)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- /* Setting a hardlink to/from a stream isn't currently supported. */
- if (is_ntfs_stream_smb_fname(smb_fname_old) ||
- is_ntfs_stream_smb_fname(smb_fname_new)) {
- return NT_STATUS_INVALID_PARAMETER;
+ /* Ensure this is within the share. */
+ status = check_reduced_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
- smb_fname_old->base_name, smb_fname_new->base_name));
+ DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
- if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
- smb_fname_new->base_name) != 0) {
+ if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
status = map_nt_error_from_unix(errno);
DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
- nt_errstr(status), smb_fname_old->base_name,
- smb_fname_new->base_name));
+ nt_errstr(status), newname, oldname));
}
+
return status;
}
@@ -5376,30 +4891,34 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
NTSTATUS smb_set_file_time(connection_struct *conn,
files_struct *fsp,
- const struct smb_filename *smb_fname,
+ const char *fname,
+ const SMB_STRUCT_STAT *psbuf,
struct smb_file_time *ft,
bool setting_write_time)
{
- struct smb_filename smb_fname_base;
+ struct smb_file_time ft_stat;
uint32 action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
|FILE_NOTIFY_CHANGE_LAST_WRITE
|FILE_NOTIFY_CHANGE_CREATION;
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
/* get some defaults (no modifications) if any info is zero or -1. */
if (null_timespec(ft->create_time)) {
+ ft->create_time = get_create_timespec(psbuf, lp_fake_dir_create_times(SNUM(conn)));
action &= ~FILE_NOTIFY_CHANGE_CREATION;
}
if (null_timespec(ft->atime)) {
+ ft->atime= get_atimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
if (null_timespec(ft->mtime)) {
+ ft->mtime = get_mtimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
@@ -5412,7 +4931,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
* what we can store on this filesystem. */
round_timespec(conn->ts_res, &ft->create_time);
- round_timespec(conn->ts_res, &ft->ctime);
round_timespec(conn->ts_res, &ft->atime);
round_timespec(conn->ts_res, &ft->mtime);
@@ -5420,8 +4938,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
time_to_asc(convert_timespec_to_time_t(ft->atime))));
DEBUG(5,("smb_set_filetime: modtime: %s\n ",
time_to_asc(convert_timespec_to_time_t(ft->mtime))));
- DEBUG(5,("smb_set_filetime: ctime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->ctime))));
DEBUG(5,("smb_set_file_time: createtime: %s\n ",
time_to_asc(convert_timespec_to_time_t(ft->create_time))));
@@ -5447,24 +4963,35 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
set_sticky_write_time_fsp(fsp, ft->mtime);
}
} else {
- set_sticky_write_time_path(
- vfs_file_id_from_sbuf(conn, &smb_fname->st),
- ft->mtime);
+ set_sticky_write_time_path(conn, fname,
+ vfs_file_id_from_sbuf(conn, psbuf),
+ ft->mtime);
}
}
- DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
+ ft_stat.create_time = get_create_timespec(psbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
+ ft_stat.atime= get_atimespec(psbuf);
+ ft_stat.mtime = get_mtimespec(psbuf);
- /* Always call ntimes on the base, even if a stream was passed in. */
- smb_fname_base = *smb_fname;
- smb_fname_base.stream_name = NULL;
+ round_timespec(conn->ts_res, &ft_stat.create_time);
+ round_timespec(conn->ts_res, &ft_stat.atime);
+ round_timespec(conn->ts_res, &ft_stat.mtime);
- if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
- return map_nt_error_from_unix(errno);
+ if (fsp && fsp->base_fsp) {
+ fname = fsp->base_fsp->fsp_name;
}
- notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
- smb_fname->base_name);
+ if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
+ timespec_compare(&ft_stat.atime, &ft->atime) ||
+ timespec_compare(&ft_stat.mtime, &ft->mtime)) {
+ DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
+ if(file_ntimes(conn, fname, ft)!=0) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
+
return NT_STATUS_OK;
}
@@ -5473,26 +5000,25 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
- const struct smb_filename *smb_fname,
- uint32 dosmode)
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ uint32 dosmode)
{
- struct smb_filename *smb_fname_base = NULL;
- NTSTATUS status;
-
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- /* Always operate on the base_name, even if a stream was passed in. */
- status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
- NULL, &smb_fname->st,
- &smb_fname_base);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (fsp) {
+ if (fsp->base_fsp) {
+ fname = fsp->base_fsp->fsp_name;
+ } else {
+ fname = fsp->fsp_name;
+ }
}
-
+
if (dosmode) {
- if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
+ if (S_ISDIR(psbuf->st_mode)) {
dosmode |= aDIR;
} else {
dosmode &= ~aDIR;
@@ -5502,25 +5028,18 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
/* check the mode isn't different, before changing it */
- if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
- DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
- "0x%x\n", smb_fname_str_dbg(smb_fname_base),
- (unsigned int)dosmode));
-
- if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
- false)) {
- DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
- "%s failed (%s)\n",
- smb_fname_str_dbg(smb_fname_base),
- strerror(errno)));
- status = map_nt_error_from_unix(errno);
- goto out;
+ if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
+
+ DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
+ fname, (unsigned int)dosmode ));
+
+ if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
+ DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
+ fname, strerror(errno)));
+ return map_nt_error_from_unix(errno);
}
}
- status = NT_STATUS_OK;
- out:
- TALLOC_FREE(smb_fname_base);
- return status;
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -5529,14 +5048,12 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
static NTSTATUS smb_set_file_size(connection_struct *conn,
struct smb_request *req,
- files_struct *fsp,
- const struct smb_filename *smb_fname,
- const SMB_STRUCT_STAT *psbuf,
- SMB_OFF_T size,
- bool fail_after_createfile)
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
+ SMB_OFF_T size)
{
NTSTATUS status = NT_STATUS_OK;
- struct smb_filename *smb_fname_tmp = NULL;
files_struct *new_fsp = NULL;
if (!VALID_STAT(*psbuf)) {
@@ -5550,7 +5067,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
}
DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
- smb_fname_str_dbg(smb_fname), (double)size));
+ fname, (double)size ));
if (fsp && fsp->fh->fd != -1) {
/* Handle based call. */
@@ -5561,18 +5078,12 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
return NT_STATUS_OK;
}
- status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- smb_fname_tmp->st = *psbuf;
-
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname_tmp, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
FILE_WRITE_ATTRIBUTES, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -5584,21 +5095,14 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&new_fsp, /* result */
- NULL); /* pinfo */
-
- TALLOC_FREE(smb_fname_tmp);
+ NULL, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
return status;
}
- /* See RAW-SFILEINFO-END-OF-FILE */
- if (fail_after_createfile) {
- close_file(req, new_fsp,NORMAL_CLOSE);
- return NT_STATUS_INVALID_LEVEL;
- }
-
if (vfs_set_filelen(new_fsp, size) == -1) {
status = map_nt_error_from_unix(errno);
close_file(req, new_fsp,NORMAL_CLOSE);
@@ -5618,7 +5122,7 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname)
{
struct ea_list *ea_list = NULL;
TALLOC_CTX *ctx = NULL;
@@ -5648,59 +5152,12 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn,
if (!ea_list) {
return NT_STATUS_INVALID_PARAMETER;
}
- status = set_ea(conn, fsp, smb_fname, ea_list);
+ status = set_ea(conn, fsp, fname, ea_list);
return status;
}
/****************************************************************************
- Deal with SMB_FILE_FULL_EA_INFORMATION set.
-****************************************************************************/
-
-static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
- const char *pdata,
- int total_data,
- files_struct *fsp)
-{
- struct ea_list *ea_list = NULL;
- NTSTATUS status;
-
- if (!fsp) {
- return NT_STATUS_INVALID_HANDLE;
- }
-
- if (!lp_ea_support(SNUM(conn))) {
- DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
- "EA's not supported.\n",
- (unsigned int)total_data));
- return NT_STATUS_EAS_NOT_SUPPORTED;
- }
-
- if (total_data < 10) {
- DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
- "too small.\n",
- (unsigned int)total_data));
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- ea_list = read_nttrans_ea_list(talloc_tos(),
- pdata,
- total_data);
-
- if (!ea_list) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
-
- DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
- smb_fname_str_dbg(fsp->fsp_name),
- nt_errstr(status) ));
-
- return status;
-}
-
-
-/****************************************************************************
Deal with SMB_SET_FILE_DISPOSITION_INFO.
****************************************************************************/
@@ -5708,7 +5165,8 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
NTSTATUS status = NT_STATUS_OK;
bool delete_on_close;
@@ -5723,19 +5181,18 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
}
delete_on_close = (CVAL(pdata,0) ? True : False);
- dosmode = dos_mode(conn, smb_fname);
+ dosmode = dos_mode(conn, fname, psbuf);
DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
"delete_on_close = %u\n",
- smb_fname_str_dbg(smb_fname),
+ fsp->fsp_name,
(unsigned int)dosmode,
(unsigned int)delete_on_close ));
- if (delete_on_close) {
- status = can_set_delete_on_close(fsp, dosmode);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* The set is across all open files on this dev/inode pair. */
@@ -5776,9 +5233,8 @@ static NTSTATUS smb_file_position_information(connection_struct *conn,
}
#endif /* LARGE_SMB_OFF_T */
- DEBUG(10,("smb_file_position_information: Set file position "
- "information for file %s to %.0f\n", fsp_str_dbg(fsp),
- (double)position_information));
+ DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
+ fsp->fsp_name, (double)position_information ));
fsp->fh->position_information = position_information;
return NT_STATUS_OK;
}
@@ -5811,10 +5267,10 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
struct smb_request *req,
const char *pdata,
int total_data,
- const struct smb_filename *smb_fname)
+ const char *fname)
{
char *link_target = NULL;
- const char *newname = smb_fname->base_name;
+ const char *newname = fname;
TALLOC_CTX *ctx = talloc_tos();
/* Set a symbolic link. */
@@ -5852,10 +5308,9 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
struct smb_request *req,
const char *pdata, int total_data,
- const struct smb_filename *smb_fname_new)
+ const char *fname)
{
char *oldname = NULL;
- struct smb_filename *smb_fname_old = NULL;
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
@@ -5870,21 +5325,18 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
return status;
}
- DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
- smb_fname_str_dbg(smb_fname_new), oldname));
-
- status = filename_convert(ctx,
- conn,
+ status = resolve_dfspath(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
oldname,
- 0,
- NULL,
- &smb_fname_old);
+ &oldname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
+ DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
+ fname, oldname));
+
+ return hardlink_internals(ctx, conn, oldname, fname);
}
/****************************************************************************
@@ -5896,14 +5348,16 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- struct smb_filename *smb_fname_src)
+ const char *fname)
{
bool overwrite;
uint32 root_fid;
uint32 len;
char *newname = NULL;
- struct smb_filename *smb_fname_dst = NULL;
+ char *base_name = NULL;
bool dest_has_wcard = False;
+ SMB_STRUCT_STAT sbuf;
+ char *newname_last_component = NULL;
NTSTATUS status = NT_STATUS_OK;
char *p;
TALLOC_CTX *ctx = talloc_tos();
@@ -5912,6 +5366,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
+ ZERO_STRUCT(sbuf);
+
overwrite = (CVAL(pdata,0) ? True : False);
root_fid = IVAL(pdata,4);
len = IVAL(pdata,8);
@@ -5949,44 +5405,20 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
if (newname[0] != ':') {
return NT_STATUS_NOT_SUPPORTED;
}
-
- /* Create an smb_fname to call rename_internals_fsp() with. */
- status = create_synthetic_smb_fname(talloc_tos(),
- fsp->base_fsp->fsp_name->base_name, newname, NULL,
- &smb_fname_dst);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
-
- /*
- * Set the original last component, since
- * rename_internals_fsp() requires it.
- */
- smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
- newname);
- if (smb_fname_dst->original_lcomp == NULL) {
- status = NT_STATUS_NO_MEMORY;
- goto out;
+ base_name = talloc_asprintf(ctx, "%s%s",
+ fsp->base_fsp->fsp_name,
+ newname);
+ if (!base_name) {
+ return NT_STATUS_NO_MEMORY;
}
-
} else {
- /*
- * Build up an smb_fname_dst based on the filename passed in.
- * We basically just strip off the last component, and put on
- * the newname instead.
- */
- char *base_name = NULL;
-
/* newname must *not* be a stream name. */
- if (newname[0] == ':') {
+ if (is_ntfs_stream_name(newname)) {
return NT_STATUS_NOT_SUPPORTED;
}
- /*
- * Strip off the last component (filename) of the path passed
- * in.
- */
- base_name = talloc_strdup(ctx, smb_fname_src->base_name);
+ /* Create the base directory. */
+ base_name = talloc_strdup(ctx, fname);
if (!base_name) {
return NT_STATUS_NO_MEMORY;
}
@@ -6007,50 +5439,35 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_NO_MEMORY;
}
- status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
- (UCF_SAVE_LCOMP |
- (dest_has_wcard ?
- UCF_ALWAYS_ALLOW_WCARD_LCOMP :
- 0)));
+ status = unix_convert(ctx, conn, newname, False,
+ &newname,
+ &newname_last_component,
+ &sbuf);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
- if (!NT_STATUS_IS_OK(status)) {
- if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
- status)) {
- goto out;
- }
- /* Create an smb_fname to call rename_internals_fsp() */
- status = create_synthetic_smb_fname(ctx,
- base_name, NULL,
- NULL,
- &smb_fname_dst);
- if (!NT_STATUS_IS_OK(status)) {
- goto out;
- }
+ if (!NT_STATUS_IS_OK(status)
+ && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
+ status)) {
+ return status;
}
}
if (fsp) {
- DEBUG(10,("smb_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
- smb_fname_str_dbg(smb_fname_dst)));
- status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
+ DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
+ fsp->fnum, fsp->fsp_name, base_name ));
+ status = rename_internals_fsp(conn, fsp, base_name,
+ newname_last_component, 0,
overwrite);
} else {
- DEBUG(10,("smb_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
- smb_fname_str_dbg(smb_fname_src),
- smb_fname_str_dbg(smb_fname_dst)));
- status = rename_internals(ctx, conn, req, smb_fname_src,
- smb_fname_dst, 0, overwrite, false,
- dest_has_wcard,
- FILE_WRITE_ATTRIBUTES);
- }
- out:
- TALLOC_FREE(smb_fname_dst);
+ DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
+ fname, base_name ));
+ status = rename_internals(ctx, conn, req, fname, base_name, 0,
+ overwrite, False, dest_has_wcard,
+ FILE_WRITE_ATTRIBUTES);
+ }
+
return status;
}
@@ -6063,7 +5480,8 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
uint16 posix_acl_version;
uint16 num_file_acls;
@@ -6098,20 +5516,18 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
}
DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
- smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
+ fname ? fname : fsp->fsp_name,
(unsigned int)num_file_acls,
(unsigned int)num_def_acls));
- if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
- smb_fname->base_name, num_file_acls,
- pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
+ if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
return map_nt_error_from_unix(errno);
}
- if (valid_def_acls && !set_unix_posix_default_acl(conn,
- smb_fname->base_name, &smb_fname->st, num_def_acls,
- pdata + SMB_POSIX_ACL_HEADER_SIZE +
- (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
+ if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE +
+ (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
return map_nt_error_from_unix(errno);
}
return NT_STATUS_OK;
@@ -6187,7 +5603,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
"lock_pid = %u, count = %.0f, offset = %.0f\n",
- fsp_str_dbg(fsp),
+ fsp->fsp_name,
(unsigned int)lock_type,
(unsigned int)lock_pid,
(double)count,
@@ -6243,85 +5659,111 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
}
/****************************************************************************
- Deal with SMB_SET_FILE_BASIC_INFO.
+ Deal with SMB_INFO_STANDARD.
****************************************************************************/
-static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
+static NTSTATUS smb_set_info_standard(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ const SMB_STRUCT_STAT *psbuf)
{
- /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
struct smb_file_time ft;
- uint32 dosmode = 0;
- NTSTATUS status = NT_STATUS_OK;
-
ZERO_STRUCT(ft);
- if (total_data < 36) {
+ if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
- /* Set the attributes */
- dosmode = IVAL(pdata,32);
- status = smb_set_file_dosmode(conn, smb_fname, dosmode);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
/* create time */
- ft.create_time = interpret_long_date(pdata);
+ ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
/* access time */
- ft.atime = interpret_long_date(pdata+8);
-
- /* write time. */
- ft.mtime = interpret_long_date(pdata+16);
+ ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
- /* change time. */
- ft.ctime = interpret_long_date(pdata+24);
+ /* write time */
+ ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
- DEBUG(10, ("smb_set_file_basic_info: file %s\n",
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(10,("smb_set_info_standard: file %s\n",
+ fname ? fname : fsp->fsp_name ));
- return smb_set_file_time(conn, fsp, smb_fname, &ft,
- true);
+ return smb_set_file_time(conn,
+ fsp,
+ fname,
+ psbuf,
+ &ft,
+ true);
}
/****************************************************************************
- Deal with SMB_INFO_STANDARD.
+ Deal with SMB_SET_FILE_BASIC_INFO.
****************************************************************************/
-static NTSTATUS smb_set_info_standard(connection_struct *conn,
+static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
+ /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
+ struct timespec write_time;
+ struct timespec changed_time;
struct smb_file_time ft;
+ uint32 dosmode = 0;
+ NTSTATUS status = NT_STATUS_OK;
+ bool setting_write_time = true;
ZERO_STRUCT(ft);
- if (total_data < 12) {
+ if (total_data < 36) {
return NT_STATUS_INVALID_PARAMETER;
}
- /* create time */
- ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
+ /* Set the attributes */
+ dosmode = IVAL(pdata,32);
+ status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* access time */
- ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
- /* write time */
- ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
+ ft.atime = interpret_long_date(pdata+8);
- DEBUG(10,("smb_set_info_standard: file %s\n",
- smb_fname_str_dbg(smb_fname)));
+ write_time = interpret_long_date(pdata+16);
+ changed_time = interpret_long_date(pdata+24);
+
+ /* mtime */
+ ft.mtime = timespec_min(&write_time, &changed_time);
+
+ /* create time */
+ ft.create_time = interpret_long_date(pdata);
+
+ if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
+ !null_timespec(write_time)) {
+ ft.mtime = write_time;
+ }
+
+ /* Prefer a defined time to an undefined one. */
+ if (null_timespec(ft.mtime)) {
+ if (null_timespec(write_time)) {
+ ft.mtime = changed_time;
+ setting_write_time = false;
+ } else {
+ ft.mtime = write_time;
+ }
+ }
+
+ DEBUG(10,("smb_set_file_basic_info: file %s\n",
+ fname ? fname : fsp->fsp_name ));
- return smb_set_file_time(conn,
- fsp,
- smb_fname,
+ return smb_set_file_time(conn,
+ fsp,
+ fname,
+ psbuf,
&ft,
- true);
+ setting_write_time);
}
/****************************************************************************
@@ -6333,13 +5775,14 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
uint64_t allocation_size = 0;
NTSTATUS status = NT_STATUS_OK;
files_struct *new_fsp = NULL;
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -6357,22 +5800,20 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
#endif /* LARGE_SMB_OFF_T */
- DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
- "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
- (double)allocation_size));
+ DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
+ fname, (double)allocation_size ));
if (allocation_size) {
allocation_size = smb_roundup(conn, allocation_size);
}
- DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
- "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
- (double)allocation_size));
+ DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
+ fname, (double)allocation_size ));
if (fsp && fsp->fh->fd != -1) {
/* Open file handle. */
/* Only change if needed. */
- if (allocation_size != get_file_size_stat(&smb_fname->st)) {
+ if (allocation_size != get_file_size_stat(psbuf)) {
if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
return map_nt_error_from_unix(errno);
}
@@ -6387,11 +5828,13 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
/* Pathname or stat or directory file. */
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
FILE_WRITE_DATA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -6403,7 +5846,8 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&new_fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
@@ -6411,7 +5855,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
/* Only change if needed. */
- if (allocation_size != get_file_size_stat(&smb_fname->st)) {
+ if (allocation_size != get_file_size_stat(psbuf)) {
if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
status = map_nt_error_from_unix(errno);
close_file(req, new_fsp, NORMAL_CLOSE);
@@ -6439,8 +5883,8 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname,
- bool fail_after_createfile)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
SMB_OFF_T size;
@@ -6458,15 +5902,13 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
}
#endif /* LARGE_SMB_OFF_T */
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
- "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
- (double)size));
+ "file %s to %.0f\n", fname, (double)size ));
return smb_set_file_size(conn, req,
fsp,
- smb_fname,
- &smb_fname->st,
- size,
- fail_after_createfile);
+ fname,
+ psbuf,
+ size);
}
/****************************************************************************
@@ -6476,7 +5918,8 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
static NTSTATUS smb_unix_mknod(connection_struct *conn,
const char *pdata,
int total_data,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
uint32 file_type = IVAL(pdata,56);
#if defined(HAVE_MAKEDEV)
@@ -6492,8 +5935,7 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
- PERM_NEW_FILE, &unixmode);
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -6527,12 +5969,11 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
- "%.0f mode 0%o for file %s\n", (double)dev,
- (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
+ DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
+0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
/* Ok - do the mknod. */
- if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
+ if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
return map_nt_error_from_unix(errno);
}
@@ -6542,15 +5983,18 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
if (lp_inherit_perms(SNUM(conn))) {
char *parent;
- if (!parent_dirname(talloc_tos(), smb_fname->base_name,
- &parent, NULL)) {
+ if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
return NT_STATUS_NO_MEMORY;
}
- inherit_access_posix_acl(conn, parent, smb_fname->base_name,
- unixmode);
+ inherit_access_posix_acl(conn, parent, fname, unixmode);
TALLOC_FREE(parent);
}
+ if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ status = map_nt_error_from_unix(errno);
+ SMB_VFS_UNLINK(conn,fname);
+ return status;
+ }
return NT_STATUS_OK;
}
@@ -6563,7 +6007,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
struct smb_file_time ft;
uint32 raw_unixmode;
@@ -6577,7 +6022,6 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
files_struct *all_fsps = NULL;
bool modify_mtime = true;
struct file_id id;
- SMB_STRUCT_STAT sbuf;
ZERO_STRUCT(ft);
@@ -6604,8 +6048,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
- if (VALID_STAT(smb_fname->st)) {
- if (S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (VALID_STAT(*psbuf)) {
+ if (S_ISDIR(psbuf->st_mode)) {
ptype = PERM_EXISTING_DIR;
} else {
ptype = PERM_EXISTING_FILE;
@@ -6614,22 +6058,16 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
ptype = PERM_NEW_FILE;
}
- status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
- ptype, &unixmode);
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
- "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
- smb_fname_str_dbg(smb_fname), (double)size,
- (unsigned int)set_owner, (unsigned int)set_grp,
- (int)raw_unixmode));
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
+size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
+ fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
- sbuf = smb_fname->st;
-
- if (!VALID_STAT(sbuf)) {
- struct smb_filename *smb_fname_tmp = NULL;
+ if (!VALID_STAT(*psbuf)) {
/*
* The only valid use of this is to create character and block
* devices, and named pipes. This is deprecated (IMHO) and
@@ -6639,32 +6077,17 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
status = smb_unix_mknod(conn,
pdata,
total_data,
- smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = copy_smb_filename(talloc_tos(), smb_fname,
- &smb_fname_tmp);
+ fname,
+ psbuf);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
- status = map_nt_error_from_unix(errno);
- TALLOC_FREE(smb_fname_tmp);
- SMB_VFS_UNLINK(conn, smb_fname);
- return status;
- }
-
- sbuf = smb_fname_tmp->st;
- TALLOC_FREE(smb_fname_tmp);
-
/* Ensure we don't try and change anything else. */
raw_unixmode = SMB_MODE_NO_CHANGE;
- size = get_file_size_stat(&sbuf);
- ft.atime = sbuf.st_ex_atime;
- ft.mtime = sbuf.st_ex_mtime;
+ size = get_file_size_stat(psbuf);
+ ft.atime = get_atimespec(psbuf);
+ ft.mtime = get_mtimespec(psbuf);
/*
* We continue here as we might want to change the
* owner uid/gid.
@@ -6678,7 +6101,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
* */
if (!size) {
- size = get_file_size_stat(&sbuf);
+ size = get_file_size_stat(psbuf);
}
#endif
@@ -6687,11 +6110,9 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
*/
if (raw_unixmode != SMB_MODE_NO_CHANGE) {
- DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
- "setting mode 0%o for file %s\n",
- (unsigned int)unixmode,
- smb_fname_str_dbg(smb_fname)));
- if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
+ (unsigned int)unixmode, fname ));
+ if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
return map_nt_error_from_unix(errno);
}
}
@@ -6700,27 +6121,22 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
* Deal with the UNIX specific uid set.
*/
- if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
- (sbuf.st_ex_uid != set_owner)) {
+ if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
int ret;
- DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
- "changing owner %u for path %s\n",
- (unsigned int)set_owner,
- smb_fname_str_dbg(smb_fname)));
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
+ (unsigned int)set_owner, fname ));
- if (S_ISLNK(sbuf.st_ex_mode)) {
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
- set_owner, (gid_t)-1);
+ if (S_ISLNK(psbuf->st_mode)) {
+ ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
} else {
- ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
- set_owner, (gid_t)-1);
+ ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
}
if (ret != 0) {
status = map_nt_error_from_unix(errno);
if (delete_on_fail) {
- SMB_VFS_UNLINK(conn, smb_fname);
+ SMB_VFS_UNLINK(conn,fname);
}
return status;
}
@@ -6730,17 +6146,13 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
* Deal with the UNIX specific gid set.
*/
- if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
- (sbuf.st_ex_gid != set_grp)) {
- DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
- "changing group %u for file %s\n",
- (unsigned int)set_owner,
- smb_fname_str_dbg(smb_fname)));
- if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
- set_grp) != 0) {
+ if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
+ (unsigned int)set_owner, fname ));
+ if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
status = map_nt_error_from_unix(errno);
if (delete_on_fail) {
- SMB_VFS_UNLINK(conn, smb_fname);
+ SMB_VFS_UNLINK(conn,fname);
}
return status;
}
@@ -6749,22 +6161,16 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
/* Deal with any size changes. */
status = smb_set_file_size(conn, req,
- fsp,
- smb_fname,
- &sbuf,
- size,
- false);
+ fsp,
+ fname,
+ psbuf,
+ size);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* Deal with any time changes. */
- if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
- /* No change, don't cancel anything. */
- return status;
- }
-
- id = vfs_file_id_from_sbuf(conn, &sbuf);
+ id = vfs_file_id_from_sbuf(conn, psbuf);
for(all_fsps = file_find_di_first(id); all_fsps;
all_fsps = file_find_di_next(all_fsps)) {
/*
@@ -6787,12 +6193,13 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
status = smb_set_file_time(conn,
fsp,
- smb_fname,
+ fname,
+ psbuf,
&ft,
false);
if (modify_mtime) {
notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
}
return status;
}
@@ -6806,7 +6213,8 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
NTSTATUS status;
uint32 smb_fflags;
@@ -6820,7 +6228,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
* and UNIX_INFO2.
*/
status = smb_set_file_unix_basic(conn, req, pdata, total_data,
- fsp, smb_fname);
+ fsp, fname, psbuf);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -6834,8 +6242,8 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
if (smb_fmask != 0) {
int stat_fflags = 0;
- if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
- smb_fmask, &stat_fflags)) {
+ if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
+ &stat_fflags)) {
/* Client asked to alter a flag we don't understand. */
return NT_STATUS_INVALID_PARAMETER;
}
@@ -6844,8 +6252,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
/* XXX: we should be using SMB_VFS_FCHFLAGS here. */
return NT_STATUS_NOT_SUPPORTED;
} else {
- if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
- stat_fflags) != 0) {
+ if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
return map_nt_error_from_unix(errno);
}
}
@@ -6867,7 +6274,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
struct smb_request *req,
char **ppdata,
int total_data,
- struct smb_filename *smb_fname,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
int *pdata_return_size)
{
NTSTATUS status = NT_STATUS_OK;
@@ -6886,8 +6294,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
raw_unixmode = IVAL(pdata,8);
/* Next 4 bytes are not yet defined. */
- status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
- PERM_NEW_DIR, &unixmode);
+ status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -6895,13 +6302,14 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
- smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
+ fname, (unsigned int)unixmode ));
- status = SMB_VFS_CREATE_FILE(
+ status = SMB_VFS_CREATE_FILE(
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
FILE_READ_ATTRIBUTES, /* access_mask */
FILE_SHARE_NONE, /* share_access */
FILE_CREATE, /* create_disposition*/
@@ -6912,7 +6320,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
@@ -6944,14 +6353,12 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_BASIC:
SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
SSVAL(pdata,10,0); /* Padding. */
- store_file_unix_basic(conn, pdata + 12, fsp,
- &smb_fname->st);
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
break;
case SMB_QUERY_FILE_UNIX_INFO2:
SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
SSVAL(pdata,10,0); /* Padding. */
- store_file_unix_basic_info2(conn, pdata + 12, fsp,
- &smb_fname->st);
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
break;
default:
SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
@@ -6970,7 +6377,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
struct smb_request *req,
char **ppdata,
int total_data,
- struct smb_filename *smb_fname,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf,
int *pdata_return_size)
{
bool extended_oplock_granted = False;
@@ -7005,7 +6413,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
return smb_posix_mkdir(conn, req,
ppdata,
total_data,
- smb_fname,
+ fname,
+ psbuf,
pdata_return_size);
}
@@ -7044,10 +6453,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
raw_unixmode = IVAL(pdata,8);
/* Next 4 bytes are not yet defined. */
- status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
- (VALID_STAT(smb_fname->st) ?
- PERM_EXISTING_FILE : PERM_NEW_FILE),
- &unixmode);
+ status = unix_perms_from_wire(conn,
+ psbuf,
+ raw_unixmode,
+ VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
+ &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -7066,7 +6476,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
}
DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
- smb_fname_str_dbg(smb_fname),
+ fname,
(unsigned int)wire_open_mode,
(unsigned int)unixmode ));
@@ -7074,7 +6484,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
access_mask, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -7086,7 +6497,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -7140,14 +6552,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_BASIC:
SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
SSVAL(pdata,10,0); /* padding. */
- store_file_unix_basic(conn, pdata + 12, fsp,
- &smb_fname->st);
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
break;
case SMB_QUERY_FILE_UNIX_INFO2:
SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
SSVAL(pdata,10,0); /* padding. */
- store_file_unix_basic_info2(conn, pdata + 12, fsp,
- &smb_fname->st);
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
break;
default:
SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
@@ -7165,7 +6575,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
struct smb_request *req,
const char *pdata,
int total_data,
- struct smb_filename *smb_fname)
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
@@ -7182,20 +6593,20 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
flags = SVAL(pdata,0);
- if (!VALID_STAT(smb_fname->st)) {
+ if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
- !VALID_STAT_OF_DIR(smb_fname->st)) {
+ !VALID_STAT_OF_DIR(*psbuf)) {
return NT_STATUS_NOT_A_DIRECTORY;
}
DEBUG(10,("smb_posix_unlink: %s %s\n",
(flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
- smb_fname_str_dbg(smb_fname)));
+ fname));
- if (VALID_STAT_OF_DIR(smb_fname->st)) {
+ if (VALID_STAT_OF_DIR(*psbuf)) {
create_options |= FILE_DIRECTORY_FILE;
}
@@ -7203,7 +6614,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
conn, /* conn */
req, /* req */
0, /* root_dir_fid */
- smb_fname, /* fname */
+ fname, /* fname */
+ 0, /* create_file_flags */
DELETE_ACCESS, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
@@ -7215,7 +6627,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ psbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -7230,7 +6643,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
NULL);
if (lck == NULL) {
DEBUG(0, ("smb_posix_unlink: Could not get share mode "
- "lock for file %s\n", fsp_str_dbg(fsp)));
+ "lock for file %s\n", fsp->fsp_name));
close_file(req, fsp, NORMAL_CLOSE);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -7260,7 +6673,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
&del,
1,
fsp,
- smb_fname);
+ fname,
+ psbuf);
if (!NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
@@ -7271,36 +6685,190 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
return close_file(req, fsp, NORMAL_CLOSE);
}
-NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
- struct smb_request *req,
- TALLOC_CTX *mem_ctx,
- uint16_t info_level,
- files_struct *fsp,
- struct smb_filename *smb_fname,
- char **ppdata, int total_data,
- int *ret_data_size)
+/****************************************************************************
+ Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
+****************************************************************************/
+
+static void call_trans2setfilepathinfo(connection_struct *conn,
+ struct smb_request *req,
+ unsigned int tran_call,
+ char **pparams, int total_params,
+ char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
+ char *params = *pparams;
char *pdata = *ppdata;
+ uint16 info_level;
+ SMB_STRUCT_STAT sbuf;
+ char *fname = NULL;
+ files_struct *fsp = NULL;
NTSTATUS status = NT_STATUS_OK;
int data_return_size = 0;
+ TALLOC_CTX *ctx = talloc_tos();
+
+ if (!params) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ ZERO_STRUCT(sbuf);
+
+ if (tran_call == TRANSACT2_SETFILEINFO) {
+ if (total_params < 4) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ fsp = file_fsp(req, SVAL(params,0));
+ /* Basic check for non-null fsp. */
+ if (!check_fsp_open(conn, req, fsp)) {
+ return;
+ }
+ info_level = SVAL(params,2);
+
+ fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+ if (!fname) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ if(fsp->is_directory || fsp->fh->fd == -1) {
+ /*
+ * This is actually a SETFILEINFO on a directory
+ * handle (returned from an NT SMB). NT5.0 seems
+ * to do this call. JRA.
+ */
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /* Always do lstat for UNIX calls. */
+ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ } else {
+ if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req,ERRDOS,ERRbadpath);
+ return;
+ }
+ }
+ } else if (fsp->print_file) {
+ /*
+ * Doing a DELETE_ON_CLOSE should cancel a print job.
+ */
+ if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
+ fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
+
+ DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
+
+ SSVAL(params,0,0);
+ send_trans2_replies(conn, req, params, 2,
+ *ppdata, 0,
+ max_data_bytes);
+ return;
+ } else {
+ reply_unixerror(req, ERRDOS, ERRbadpath);
+ return;
+ }
+ } else {
+ /*
+ * Original code - this is an open file.
+ */
+ if (!check_fsp(conn, req, fsp)) {
+ return;
+ }
+
+ if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
+ DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadfid);
+ return;
+ }
+ }
+ } else {
+ /* set path info */
+ if (total_params < 7) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
+ info_level = SVAL(params,0);
+ srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
+ total_params - 6, STR_TERMINATE,
+ &status);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = resolve_dfspath(ctx, conn,
+ req->flags2 & FLAGS2_DFS_PATHNAMES,
+ fname,
+ &fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ reply_botherror(req,
+ NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
+ return;
+ }
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = unix_convert(ctx, conn, fname, False,
+ &fname, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ /*
+ * For CIFS UNIX extensions the target name may not exist.
+ */
+
+ /* Always do lstat for UNIX calls. */
+ SMB_VFS_LSTAT(conn,fname,&sbuf);
- *ret_data_size = 0;
+ } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
+ DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
+ reply_unixerror(req, ERRDOS, ERRbadpath);
+ return;
+ }
+ }
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
if (!CAN_WRITE(conn)) {
/* Allow POSIX opens. The open path will deny
* any non-readonly opens. */
if (info_level != SMB_POSIX_PATH_OPEN) {
- return NT_STATUS_DOS(ERRSRV, ERRaccess);
+ reply_doserror(req, ERRSRV, ERRaccess);
+ return;
}
}
- DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
- "totdata=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level, total_data));
+ DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
+ tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
+
+ /* Realloc the parameter size */
+ *pparams = (char *)SMB_REALLOC(*pparams,2);
+ if (*pparams == NULL) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ params = *pparams;
+
+ SSVAL(params,0,0);
switch (info_level) {
@@ -7310,7 +6878,8 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
@@ -7320,7 +6889,7 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname);
break;
}
@@ -7331,7 +6900,8 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
@@ -7342,29 +6912,20 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
case SMB_FILE_END_OF_FILE_INFORMATION:
case SMB_SET_FILE_END_OF_FILE_INFO:
{
- /*
- * XP/Win7 both fail after the createfile with
- * SMB_SET_FILE_END_OF_FILE_INFO but not
- * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
- * The level is known here, so pass it down
- * appropriately.
- */
- bool should_fail =
- (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
-
status = smb_set_file_end_of_file_info(conn, req,
pdata,
total_data,
fsp,
- smb_fname,
- should_fail);
+ fname,
+ &sbuf);
break;
}
@@ -7384,7 +6945,8 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
@@ -7397,15 +6959,6 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
break;
}
- case SMB_FILE_FULL_EA_INFORMATION:
- {
- status = smb_set_file_full_ea_info(conn,
- pdata,
- total_data,
- fsp);
- break;
- }
-
/* From tridge Samba4 :
* MODE_INFORMATION in setfileinfo (I have no
* idea what "mode information" on a file is - it takes a value of 0,
@@ -7430,7 +6983,8 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
@@ -7440,30 +6994,33 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
case SMB_SET_FILE_UNIX_LINK:
{
- if (fsp) {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
/* We must have a pathname for this. */
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
status = smb_set_file_unix_link(conn, req, pdata,
- total_data, smb_fname);
+ total_data, fname);
break;
}
case SMB_SET_FILE_UNIX_HLINK:
{
- if (fsp) {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
/* We must have a pathname for this. */
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
status = smb_set_file_unix_hlink(conn, req,
pdata, total_data,
- smb_fname);
+ fname);
break;
}
@@ -7471,7 +7028,7 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
{
status = smb_file_rename_information(conn, req,
pdata, total_data,
- fsp, smb_fname);
+ fsp, fname);
break;
}
@@ -7482,15 +7039,17 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
pdata,
total_data,
fsp,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
#endif
case SMB_SET_POSIX_LOCK:
{
- if (!fsp) {
- return NT_STATUS_INVALID_LEVEL;
+ if (tran_call != TRANSACT2_SETFILEINFO) {
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
status = smb_set_posix_lock(conn, req,
pdata, total_data, fsp);
@@ -7499,227 +7058,43 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
case SMB_POSIX_PATH_OPEN:
{
- if (fsp) {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
/* We must have a pathname for this. */
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
status = smb_posix_open(conn, req,
ppdata,
total_data,
- smb_fname,
+ fname,
+ &sbuf,
&data_return_size);
break;
}
case SMB_POSIX_PATH_UNLINK:
{
- if (fsp) {
+ if (tran_call != TRANSACT2_SETPATHINFO) {
/* We must have a pathname for this. */
- return NT_STATUS_INVALID_LEVEL;
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
}
status = smb_posix_unlink(conn, req,
pdata,
total_data,
- smb_fname);
+ fname,
+ &sbuf);
break;
}
default:
- return NT_STATUS_INVALID_LEVEL;
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- *ret_data_size = data_return_size;
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
-****************************************************************************/
-
-static void call_trans2setfilepathinfo(connection_struct *conn,
- struct smb_request *req,
- unsigned int tran_call,
- char **pparams, int total_params,
- char **ppdata, int total_data,
- unsigned int max_data_bytes)
-{
- char *params = *pparams;
- char *pdata = *ppdata;
- uint16 info_level;
- struct smb_filename *smb_fname = NULL;
- files_struct *fsp = NULL;
- NTSTATUS status = NT_STATUS_OK;
- int data_return_size = 0;
-
- if (!params) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- if (tran_call == TRANSACT2_SETFILEINFO) {
- if (total_params < 4) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- fsp = file_fsp(req, SVAL(params,0));
- /* Basic check for non-null fsp. */
- if (!check_fsp_open(conn, req, fsp)) {
- return;
- }
- info_level = SVAL(params,2);
-
- status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- if(fsp->is_directory || fsp->fh->fd == -1) {
- /*
- * This is actually a SETFILEINFO on a directory
- * handle (returned from an NT SMB). NT5.0 seems
- * to do this call. JRA.
- */
- if (INFO_LEVEL_IS_UNIX(info_level)) {
- /* Always do lstat for UNIX calls. */
- if (SMB_VFS_LSTAT(conn, smb_fname)) {
- DEBUG(3,("call_trans2setfilepathinfo: "
- "SMB_VFS_LSTAT of %s failed "
- "(%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req, map_nt_error_from_unix(errno));
- return;
- }
- } else {
- if (SMB_VFS_STAT(conn, smb_fname) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: "
- "fileinfo of %s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req, map_nt_error_from_unix(errno));
- return;
- }
- }
- } else if (fsp->print_file) {
- /*
- * Doing a DELETE_ON_CLOSE should cancel a print job.
- */
- if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
- fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
-
- DEBUG(3,("call_trans2setfilepathinfo: "
- "Cancelling print job (%s)\n",
- fsp_str_dbg(fsp)));
-
- SSVAL(params,0,0);
- send_trans2_replies(conn, req, params, 2,
- *ppdata, 0,
- max_data_bytes);
- return;
- } else {
- reply_nterror(req,
- NT_STATUS_OBJECT_PATH_NOT_FOUND);
- return;
- }
- } else {
- /*
- * Original code - this is an open file.
- */
- if (!check_fsp(conn, req, fsp)) {
- return;
- }
-
- if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
- DEBUG(3,("call_trans2setfilepathinfo: fstat "
- "of fnum %d failed (%s)\n", fsp->fnum,
- strerror(errno)));
- reply_nterror(req, map_nt_error_from_unix(errno));
- return;
- }
- }
- } else {
- char *fname = NULL;
-
- /* set path info */
- if (total_params < 7) {
- reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- info_level = SVAL(params,0);
- srvstr_get_path(req, params, req->flags2, &fname, &params[6],
- total_params - 6, STR_TERMINATE,
- &status);
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- status = filename_convert(req, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname,
- 0,
- NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
- reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- return;
- }
- reply_nterror(req, status);
- return;
- }
-
- if (INFO_LEVEL_IS_UNIX(info_level)) {
- /*
- * For CIFS UNIX extensions the target name may not exist.
- */
-
- /* Always do lstat for UNIX calls. */
- SMB_VFS_LSTAT(conn, smb_fname);
-
- } else if (!VALID_STAT(smb_fname->st) &&
- SMB_VFS_STAT(conn, smb_fname)) {
- DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
- "%s failed (%s)\n",
- smb_fname_str_dbg(smb_fname),
- strerror(errno)));
- reply_nterror(req, map_nt_error_from_unix(errno));
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
return;
- }
- }
-
- DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
- "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,total_data));
-
- /* Realloc the parameter size */
- *pparams = (char *)SMB_REALLOC(*pparams,2);
- if (*pparams == NULL) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- return;
}
- params = *pparams;
-
- SSVAL(params,0,0);
- status = smbd_do_setfilepathinfo(conn, req, req,
- info_level,
- fsp,
- smb_fname,
- ppdata, total_data,
- &data_return_size);
+
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
@@ -7743,9 +7118,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
+ SSVAL(params,0,0);
send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
max_data_bytes);
-
+
return;
}
@@ -7758,16 +7134,16 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- struct smb_filename *smb_dname = NULL;
char *params = *pparams;
char *pdata = *ppdata;
char *directory = NULL;
+ SMB_STRUCT_STAT sbuf;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
TALLOC_CTX *ctx = talloc_tos();
if (!CAN_WRITE(conn)) {
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
return;
}
@@ -7786,29 +7162,38 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
- status = filename_convert(ctx,
+ status = resolve_dfspath(ctx,
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- 0,
- NULL,
- &smb_dname);
-
+ &directory);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req,
- NT_STATUS_PATH_NOT_COVERED,
- ERRSRV, ERRbadpath);
- return;
+ NT_STATUS_PATH_NOT_COVERED,
+ ERRSRV, ERRbadpath);
}
reply_nterror(req, status);
return;
- }
+ }
+
+ status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ return;
+ }
+
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+ reply_nterror(req, status);
+ return;
+ }
/* Any data in this call is an EA list. */
if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
- goto out;
+ return;
}
/*
@@ -7820,21 +7205,21 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
if (total_data != 4) {
if (total_data < 10) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
if (IVAL(pdata,0) > total_data) {
DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
IVAL(pdata,0), (unsigned int)total_data));
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
ea_list = read_ea_list(talloc_tos(), pdata + 4,
total_data - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
- goto out;
+ return;
}
}
/* If total_data == 4 Windows doesn't care what values
@@ -7842,19 +7227,19 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
* The System i QNTC IBM SMB client puts bad values here,
* so ignore them. */
- status = create_directory(conn, req, smb_dname);
+ status = create_directory(conn, req, directory);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ return;
}
-
+
/* Try and set any given EA. */
if (ea_list) {
- status = set_ea(conn, NULL, smb_dname, ea_list);
+ status = set_ea(conn, NULL, directory, ea_list);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
- goto out;
+ return;
}
}
@@ -7862,16 +7247,14 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
*pparams = (char *)SMB_REALLOC(*pparams,2);
if(*pparams == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
- goto out;
+ return;
}
params = *pparams;
SSVAL(params,0,0);
send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
-
- out:
- TALLOC_FREE(smb_dname);
+
return;
}
@@ -7924,7 +7307,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
fnf_handle = 257;
send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
-
+
return;
}
@@ -7955,7 +7338,7 @@ static void call_trans2findnotifynext(connection_struct *conn,
SSVAL(params,2,0); /* No EA errors */
send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
-
+
return;
}
@@ -7986,7 +7369,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
max_referral_level = SVAL(params,0);
if(!lp_host_msdfs()) {
- reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ reply_doserror(req, ERRDOS, ERRbadfunc);
return;
}
@@ -8028,7 +7411,7 @@ static void call_trans2ioctl(connection_struct *conn,
/* check for an invalid fid before proceeding */
if (!fsp) {
- reply_nterror(req, NT_STATUS_INVALID_HANDLE);
+ reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
@@ -8057,7 +7440,7 @@ static void call_trans2ioctl(connection_struct *conn,
}
DEBUG(2,("Unknown TRANS2_IOCTL\n"));
- reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ reply_doserror(req, ERRSRV, ERRerror);
}
/****************************************************************************
@@ -8067,7 +7450,6 @@ static void call_trans2ioctl(connection_struct *conn,
void reply_findclose(struct smb_request *req)
{
int dptr_num;
- struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBfindclose);
@@ -8081,7 +7463,7 @@ void reply_findclose(struct smb_request *req)
DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
- dptr_close(sconn, &dptr_num);
+ dptr_close(&dptr_num);
reply_outbuf(req, 0, 0);
@@ -8106,7 +7488,7 @@ void reply_findnclose(struct smb_request *req)
END_PROFILE(SMBfindnclose);
return;
}
-
+
dptr_num = SVAL(req->vwv+0, 0);
DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
@@ -8126,7 +7508,7 @@ void reply_findnclose(struct smb_request *req)
static void handle_trans2(connection_struct *conn, struct smb_request *req,
struct trans_state *state)
{
- if (get_Protocol() >= PROTOCOL_NT1) {
+ if (Protocol >= PROTOCOL_NT1) {
req->flags2 |= 0x40; /* IS_LONG_NAME */
SSVAL(req->inbuf,smb_flg2,req->flags2);
}
@@ -8283,7 +7665,7 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
default:
/* Error in request */
DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
- reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
+ reply_doserror(req, ERRSRV,ERRerror);
}
}
@@ -8335,7 +7717,7 @@ void reply_trans2(struct smb_request *req)
case TRANSACT2_SETFSINFO:
break;
default:
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ reply_doserror(req, ERRSRV, ERRaccess);
END_PROFILE(SMBtrans2);
return;
}
@@ -8526,7 +7908,7 @@ void reply_transs2(struct smb_request *req)
state->received_param += pcnt;
state->received_data += dcnt;
-
+
if ((state->received_data > state->total_data) ||
(state->received_param > state->total_param))
goto bad_param;
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 2ec50cd4d8..72837ff967 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -224,8 +224,7 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
bool change_to_user(connection_struct *conn, uint16 vuid)
{
const struct auth_serversupplied_info *server_info = NULL;
- struct smbd_server_connection *sconn = smbd_server_conn;
- user_struct *vuser = get_valid_user_struct(sconn, vuid);
+ user_struct *vuser = get_valid_user_struct(vuid);
int snum;
gid_t gid;
uid_t uid;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 0dd5bb98f7..fd7f91f361 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -5,7 +5,6 @@
Copyright (C) Tim Potter 1999
Copyright (C) Alexander Bokovoy 2002
Copyright (C) James Peach 2006
- Copyright (C) Volker Lendecke 2009
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
@@ -33,8 +32,8 @@ static_decl_vfs;
struct vfs_init_function_entry {
char *name;
+ const vfs_op_tuple *vfs_op_tuples;
struct vfs_init_function_entry *prev, *next;
- const struct vfs_fn_pointers *fns;
};
/****************************************************************************
@@ -46,7 +45,7 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
struct vfs_init_function_entry *entry = backends;
DEBUG(10, ("vfs_find_backend_entry called for %s\n", name));
-
+
while(entry) {
if (strcmp(entry->name, name)==0) return entry;
entry = entry->next;
@@ -55,8 +54,7 @@ static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name)
return NULL;
}
-NTSTATUS smb_register_vfs(int version, const char *name,
- const struct vfs_fn_pointers *fns)
+NTSTATUS smb_register_vfs(int version, const char *name, const vfs_op_tuple *vfs_op_tuples)
{
struct vfs_init_function_entry *entry = backends;
@@ -69,7 +67,7 @@ NTSTATUS smb_register_vfs(int version, const char *name,
return NT_STATUS_OBJECT_TYPE_MISMATCH;
}
- if (!name || !name[0]) {
+ if (!name || !name[0] || !vfs_op_tuples) {
DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n"));
return NT_STATUS_INVALID_PARAMETER;
}
@@ -81,7 +79,7 @@ NTSTATUS smb_register_vfs(int version, const char *name,
entry = SMB_XMALLOC_P(struct vfs_init_function_entry);
entry->name = smb_xstrdup(name);
- entry->fns = fns;
+ entry->vfs_op_tuples = vfs_op_tuples;
DLIST_ADD(backends, entry);
DEBUG(5, ("Successfully added vfs backend '%s'\n", name));
@@ -102,14 +100,23 @@ static void vfs_init_default(connection_struct *conn)
initialise custom vfs hooks
****************************************************************************/
+static inline void vfs_set_operation(struct vfs_ops * vfs, vfs_op_type which,
+ struct vfs_handle_struct * handle, void * op)
+{
+ ((struct vfs_handle_struct **)&vfs->handles)[which] = handle;
+ ((void **)(void *)&vfs->ops)[which] = op;
+}
+
bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
{
+ const vfs_op_tuple *ops;
char *module_path = NULL;
char *module_name = NULL;
char *module_param = NULL, *p;
+ int i;
vfs_handle_struct *handle;
const struct vfs_init_function_entry *entry;
-
+
if (!conn||!vfs_object||!vfs_object[0]) {
DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n"));
return False;
@@ -154,41 +161,47 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
}
/* First, try to load the module with the new module system */
- entry = vfs_find_backend_entry(module_name);
- if (!entry) {
- NTSTATUS status;
-
- DEBUG(5, ("vfs module [%s] not loaded - trying to load...\n",
- vfs_object));
-
- status = smb_probe_module("vfs", module_path);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("error probing vfs module '%s': %s\n",
- module_path, nt_errstr(status)));
+ if((entry = vfs_find_backend_entry(module_name)) ||
+ (NT_STATUS_IS_OK(smb_probe_module("vfs", module_path)) &&
+ (entry = vfs_find_backend_entry(module_name)))) {
+
+ DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
+
+ if ((ops = entry->vfs_op_tuples) == NULL) {
+ DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object));
goto fail;
- }
-
- entry = vfs_find_backend_entry(module_name);
- if (!entry) {
- DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
- goto fail;
- }
+ }
+ } else {
+ DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object));
+ goto fail;
}
- DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
-
handle = TALLOC_ZERO_P(conn, vfs_handle_struct);
if (!handle) {
DEBUG(0,("TALLOC_ZERO() failed!\n"));
goto fail;
}
+ memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops));
handle->conn = conn;
- handle->fns = entry->fns;
if (module_param) {
handle->param = talloc_strdup(conn, module_param);
}
DLIST_ADD(conn->vfs_handles, handle);
+ for(i=0; ops[i].op != NULL; i++) {
+ DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer));
+ if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) {
+ /* If this operation was already made opaque by different module, it
+ * will be overridden here.
+ */
+ DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object));
+ vfs_set_operation(&conn->vfs_opaque, ops[i].type, handle, ops[i].op);
+ }
+ /* Change current VFS disposition*/
+ DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object));
+ vfs_set_operation(&conn->vfs, ops[i].type, handle, ops[i].op);
+ }
+
SAFE_FREE(module_path);
SAFE_FREE(module_name);
return True;
@@ -291,7 +304,7 @@ bool smbd_vfs_init(connection_struct *conn)
const char **vfs_objects;
unsigned int i = 0;
int j = 0;
-
+
/* Normal share - initialise with disk access functions */
vfs_init_default(conn);
vfs_objects = lp_vfs_objects(SNUM(conn));
@@ -299,7 +312,7 @@ bool smbd_vfs_init(connection_struct *conn)
/* Override VFS functions if 'vfs object' was not specified*/
if (!vfs_objects || !vfs_objects[0])
return True;
-
+
for (i=0; vfs_objects[i] ;) {
i++;
}
@@ -314,18 +327,61 @@ bool smbd_vfs_init(connection_struct *conn)
}
/*******************************************************************
+ Check if directory exists.
+********************************************************************/
+
+bool vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *st)
+{
+ SMB_STRUCT_STAT st2;
+ bool ret;
+
+ if (!st)
+ st = &st2;
+
+ if (SMB_VFS_STAT(conn,dname,st) != 0)
+ return(False);
+
+ ret = S_ISDIR(st->st_mode);
+ if(!ret)
+ errno = ENOTDIR;
+
+ return ret;
+}
+
+/*******************************************************************
+ Check if an object exists in the vfs.
+********************************************************************/
+
+bool vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT *sbuf)
+{
+ SMB_STRUCT_STAT st;
+
+ if (!sbuf)
+ sbuf = &st;
+
+ ZERO_STRUCTP(sbuf);
+
+ if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
+ return(False);
+ return True;
+}
+
+/*******************************************************************
Check if a file exists in the vfs.
********************************************************************/
-NTSTATUS vfs_file_exist(connection_struct *conn, struct smb_filename *smb_fname)
+bool vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT *sbuf)
{
- /* Only return OK if stat was successful and S_ISREG */
- if ((SMB_VFS_STAT(conn, smb_fname) != -1) &&
- S_ISREG(smb_fname->st.st_ex_mode)) {
- return NT_STATUS_OK;
- }
+ SMB_STRUCT_STAT st;
+
+ if (!sbuf)
+ sbuf = &st;
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ ZERO_STRUCTP(sbuf);
+
+ if (SMB_VFS_STAT(conn,fname,sbuf) == -1)
+ return False;
+ return(S_ISREG(sbuf->st_mode));
}
/****************************************************************************
@@ -462,12 +518,10 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
* Actually try and commit the space on disk....
*/
- DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n",
- fsp_str_dbg(fsp), (double)len));
+ DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len ));
if (((SMB_OFF_T)len) < 0) {
- DEBUG(0,("vfs_allocate_file_space: %s negative len "
- "requested.\n", fsp_str_dbg(fsp)));
+ DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name ));
errno = EINVAL;
return -1;
}
@@ -476,15 +530,14 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
if (ret == -1)
return ret;
- if (len == (uint64_t)st.st_ex_size)
+ if (len == (uint64_t)st.st_size)
return 0;
- if (len < (uint64_t)st.st_ex_size) {
+ if (len < (uint64_t)st.st_size) {
/* Shrink - use ftruncate. */
- DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current "
- "size %.0f\n", fsp_str_dbg(fsp),
- (double)st.st_ex_size));
+ DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n",
+ fsp->fsp_name, (double)st.st_size ));
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK);
@@ -506,18 +559,15 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len)
if (!lp_strict_allocate(SNUM(fsp->conn)))
return 0;
- len -= st.st_ex_size;
+ len -= st.st_size;
len /= 1024; /* Len is now number of 1k blocks needed. */
- space_avail = get_dfree_info(conn, fsp->fsp_name->base_name, false,
- &bsize, &dfree, &dsize);
+ space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize);
if (space_avail == (uint64_t)-1) {
return -1;
}
- DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, "
- "needed blocks = %.0f, space avail = %.0f\n",
- fsp_str_dbg(fsp), (double)st.st_ex_size, (double)len,
- (double)space_avail));
+ DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n",
+ fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail ));
if (len > space_avail) {
errno = ENOSPC;
@@ -539,15 +589,14 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len)
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
- DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n",
- fsp_str_dbg(fsp), (double)len));
+ DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len));
flush_write_cache(fsp, SIZECHANGE_FLUSH);
if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) {
set_filelen_write_cache(fsp, len);
notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_ATTRIBUTES,
- fsp->fsp_name->base_name);
+ fsp->fsp_name);
}
contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN);
@@ -578,14 +627,12 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
return ret;
}
- if (len <= st.st_ex_size) {
+ if (len <= st.st_size) {
return 0;
}
- DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to "
- "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp),
- (double)st.st_ex_size, (double)len,
- (double)(len - st.st_ex_size)));
+ DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n",
+ fsp->fsp_name, (double)st.st_size, (double)len, (double)(len - st.st_size)));
contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE);
@@ -600,8 +647,8 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
}
}
- offset = st.st_ex_size;
- num_to_write = len - st.st_ex_size;
+ offset = st.st_size;
+ num_to_write = len - st.st_size;
total = 0;
while (total < num_to_write) {
@@ -609,9 +656,8 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len)
pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total);
if (pwrite_ret == -1) {
- DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file "
- "%s failed with error %s\n",
- fsp_str_dbg(fsp), strerror(errno)));
+ DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n",
+ fsp->fsp_name, strerror(errno) ));
ret = -1;
goto out;
}
@@ -659,13 +705,10 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n)
A vfs_readdir wrapper which just returns the file name.
********************************************************************/
-const char *vfs_readdirname(connection_struct *conn, void *p,
- SMB_STRUCT_STAT *sbuf, char **talloced)
+char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf)
{
SMB_STRUCT_DIRENT *ptr= NULL;
- const char *dname;
- char *translated;
- NTSTATUS status;
+ char *dname;
if (!p)
return(NULL);
@@ -676,7 +719,6 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
dname = ptr->d_name;
-
#ifdef NEXT2
if (telldir(p) < 0)
return(NULL);
@@ -687,17 +729,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
dname = dname - 2;
#endif
- status = SMB_VFS_TRANSLATE_NAME(conn, dname, vfs_translate_to_windows,
- talloc_tos(), &translated);
- if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
- *talloced = NULL;
- return dname;
- }
- *talloced = translated;
- if (!NT_STATUS_IS_OK(status)) {
- return NULL;
- }
- return translated;
+ return(dname);
}
/*******************************************************************
@@ -737,12 +769,10 @@ int vfs_ChDir(connection_struct *conn, const char *path)
char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
{
char s[PATH_MAX+1];
- char *result = NULL;
+ SMB_STRUCT_STAT st, st2;
+ char *result;
DATA_BLOB cache_value;
struct file_id key;
- struct smb_filename *smb_fname_dot = NULL;
- struct smb_filename *smb_fname_full = NULL;
- NTSTATUS status;
*s = 0;
@@ -750,14 +780,9 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto nocache;
}
- status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
- &smb_fname_dot);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
+ SET_STAT_INVALID(st);
- if (SMB_VFS_STAT(conn, smb_fname_dot) == -1) {
+ if (SMB_VFS_STAT(conn, ".",&st) == -1) {
/*
* Known to fail for root: the directory may be NFS-mounted
* and exported with root_squash (so has no root access).
@@ -767,7 +792,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto nocache;
}
- key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
+ key = vfs_file_id_from_sbuf(conn, &st);
if (!memcache_lookup(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
@@ -778,25 +803,17 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
SMB_ASSERT((cache_value.length > 0)
&& (cache_value.data[cache_value.length-1] == '\0'));
- status = create_synthetic_smb_fname(ctx, (char *)cache_value.data,
- NULL, NULL, &smb_fname_full);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto out;
- }
-
- if ((SMB_VFS_STAT(conn, smb_fname_full) == 0) &&
- (smb_fname_dot->st.st_ex_dev == smb_fname_full->st.st_ex_dev) &&
- (smb_fname_dot->st.st_ex_ino == smb_fname_full->st.st_ex_ino) &&
- (S_ISDIR(smb_fname_dot->st.st_ex_mode))) {
+ if ((SMB_VFS_STAT(conn, (char *)cache_value.data, &st2) == 0)
+ && (st.st_dev == st2.st_dev) && (st.st_ino == st2.st_ino)
+ && (S_ISDIR(st.st_mode))) {
/*
* Ok, we're done
*/
- result = talloc_strdup(ctx, smb_fname_full->base_name);
+ result = talloc_strdup(ctx, (char *)cache_value.data);
if (result == NULL) {
errno = ENOMEM;
}
- goto out;
+ return result;
}
nocache:
@@ -810,11 +827,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (!SMB_VFS_GETWD(conn,s)) {
DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
strerror(errno)));
- goto out;
+ return NULL;
}
- if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
- key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
+ if (lp_getwd_cache() && VALID_STAT(st)) {
+ key = vfs_file_id_from_sbuf(conn, &st);
memcache_add(smbd_memcache(), GETWD_CACHE,
data_blob_const(&key, sizeof(key)),
@@ -825,10 +842,6 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (result == NULL) {
errno = ENOMEM;
}
-
- out:
- TALLOC_FREE(smb_fname_dot);
- TALLOC_FREE(smb_fname_full);
return result;
}
@@ -846,9 +859,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
bool free_resolved_name = False;
#endif
char *resolved_name = NULL;
+ size_t con_path_len = strlen(conn->connectpath);
char *p = NULL;
- DEBUG(3,("check_reduced_name [%s] [%s]\n", fname, conn->connectpath));
+ DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
#ifdef REALPATH_TAKES_NULL
resolved_name = SMB_VFS_REALPATH(conn,fname,NULL);
@@ -859,10 +873,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
if (!resolved_name) {
switch (errno) {
case ENOTDIR:
- DEBUG(3,("check_reduced_name: Component not a "
- "directory in getting realpath for "
- "%s\n", fname));
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
+ return map_nt_error_from_unix(errno);
case ENOENT:
{
TALLOC_CTX *ctx = talloc_tos();
@@ -893,18 +905,8 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
resolved_name = SMB_VFS_REALPATH(conn,tmp_fname,resolved_name_buf);
#endif
if (!resolved_name) {
- NTSTATUS status = map_nt_error_from_unix(errno);
-
- if (errno == ENOENT || errno == ENOTDIR) {
- status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- DEBUG(3,("check_reduce_named: "
- "couldn't get realpath for "
- "%s (%s)\n",
- fname,
- nt_errstr(status)));
- return status;
+ DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
+ return map_nt_error_from_unix(errno);
}
tmp_fname = talloc_asprintf(ctx,
"%s/%s",
@@ -917,8 +919,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
SAFE_FREE(resolved_name);
resolved_name = SMB_STRDUP(tmp_fname);
if (!resolved_name) {
- DEBUG(0, ("check_reduced_name: malloc "
- "fail for %s\n", tmp_fname));
+ DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
return NT_STATUS_NO_MEMORY;
}
#else
@@ -928,18 +929,15 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
break;
}
default:
- DEBUG(1,("check_reduced_name: couldn't get "
- "realpath for %s\n", fname));
+ DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
return map_nt_error_from_unix(errno);
}
}
- DEBUG(10,("check_reduced_name realpath [%s] -> [%s]\n", fname,
- resolved_name));
+ DEBUG(10,("reduce_name realpath [%s] -> [%s]\n", fname, resolved_name));
if (*resolved_name != '/') {
- DEBUG(0,("check_reduced_name: realpath doesn't return "
- "absolute paths !\n"));
+ DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
if (free_resolved_name) {
SAFE_FREE(resolved_name);
}
@@ -947,29 +945,12 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
}
/* Check for widelinks allowed. */
- if (!lp_widelinks(SNUM(conn))) {
- const char *conn_rootdir;
-
- conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
- if (conn_rootdir == NULL) {
- DEBUG(2, ("check_reduced_name: Could not get "
- "conn_rootdir\n"));
- if (free_resolved_name) {
- SAFE_FREE(resolved_name);
- }
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (strncmp(conn_rootdir, resolved_name,
- strlen(conn_rootdir)) != 0) {
- DEBUG(2, ("check_reduced_name: Bad access "
- "attempt: %s is a symlink outside the "
- "share path\n", fname));
- if (free_resolved_name) {
- SAFE_FREE(resolved_name);
- }
- return NT_STATUS_ACCESS_DENIED;
- }
+ if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
+ DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path\n", fname));
+ if (free_resolved_name) {
+ SAFE_FREE(resolved_name);
+ }
+ return NT_STATUS_ACCESS_DENIED;
}
/* Check if we are allowing users to follow symlinks */
@@ -978,967 +959,21 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
#ifdef S_ISLNK
if (!lp_symlinks(SNUM(conn))) {
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
-
- status = create_synthetic_smb_fname(talloc_tos(), fname, NULL,
- NULL, &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- if (free_resolved_name) {
- SAFE_FREE(resolved_name);
- }
- return status;
- }
-
- if ( (SMB_VFS_LSTAT(conn, smb_fname) != -1) &&
- (S_ISLNK(smb_fname->st.st_ex_mode)) ) {
+ SMB_STRUCT_STAT statbuf;
+ if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
+ (S_ISLNK(statbuf.st_mode)) ) {
if (free_resolved_name) {
SAFE_FREE(resolved_name);
}
- DEBUG(3,("check_reduced_name: denied: file path name "
- "%s is a symlink\n",resolved_name));
- TALLOC_FREE(smb_fname);
+ DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
return NT_STATUS_ACCESS_DENIED;
}
- TALLOC_FREE(smb_fname);
}
#endif
- DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
- resolved_name));
+ DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
if (free_resolved_name) {
SAFE_FREE(resolved_name);
}
return NT_STATUS_OK;
}
-
-/**
- * XXX: This is temporary and there should be no callers of this once
- * smb_filename is plumbed through all path based operations.
- */
-int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
- SMB_STRUCT_STAT *psbuf)
-{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
- int ret;
-
- status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- if (lp_posix_pathnames()) {
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- } else {
- ret = SMB_VFS_STAT(conn, smb_fname);
- }
-
- if (ret != -1) {
- *psbuf = smb_fname->st;
- }
-
- TALLOC_FREE(smb_fname);
- return ret;
-}
-
-/**
- * XXX: This is temporary and there should be no callers of this once
- * smb_filename is plumbed through all path based operations.
- */
-int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
- SMB_STRUCT_STAT *psbuf)
-{
- struct smb_filename *smb_fname = NULL;
- NTSTATUS status;
- int ret;
-
- status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL,
- &smb_fname);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- return -1;
- }
-
- ret = SMB_VFS_LSTAT(conn, smb_fname);
- if (ret != -1) {
- *psbuf = smb_fname->st;
- }
-
- TALLOC_FREE(smb_fname);
- return ret;
-}
-
-/**
- * Ensure LSTAT is called for POSIX paths.
- */
-
-NTSTATUS vfs_stat_fsp(files_struct *fsp)
-{
- int ret;
-
- if(fsp->is_directory || fsp->fh->fd == -1) {
- if (fsp->posix_open) {
- ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
- } else {
- ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
- }
- if (ret == -1) {
- return map_nt_error_from_unix(errno);
- }
- } else {
- if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) {
- return map_nt_error_from_unix(errno);
- }
- }
- return NT_STATUS_OK;
-}
-
-/*
- generate a file_id from a stat structure
- */
-struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_STAT *sbuf)
-{
- return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
-}
-
-int smb_vfs_call_connect(struct vfs_handle_struct *handle,
- const char *service, const char *user)
-{
- VFS_FIND(connect_fn);
- return handle->fns->connect_fn(handle, service, user);
-}
-
-void smb_vfs_call_disconnect(struct vfs_handle_struct *handle)
-{
- VFS_FIND(disconnect);
- handle->fns->disconnect(handle);
-}
-
-uint64_t smb_vfs_call_disk_free(struct vfs_handle_struct *handle,
- const char *path, bool small_query,
- uint64_t *bsize, uint64_t *dfree,
- uint64_t *dsize)
-{
- VFS_FIND(disk_free);
- return handle->fns->disk_free(handle, path, small_query, bsize, dfree,
- dsize);
-}
-
-int smb_vfs_call_get_quota(struct vfs_handle_struct *handle,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *qt)
-{
- VFS_FIND(get_quota);
- return handle->fns->get_quota(handle, qtype, id, qt);
-}
-
-int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
- enum SMB_QUOTA_TYPE qtype, unid_t id,
- SMB_DISK_QUOTA *qt)
-{
- VFS_FIND(set_quota);
- return handle->fns->set_quota(handle, qtype, id, qt);
-}
-
-int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- SHADOW_COPY_DATA *shadow_copy_data,
- bool labels)
-{
- VFS_FIND(get_shadow_copy_data);
- return handle->fns->get_shadow_copy_data(handle, fsp, shadow_copy_data,
- labels);
-}
-int smb_vfs_call_statvfs(struct vfs_handle_struct *handle, const char *path,
- struct vfs_statvfs_struct *statbuf)
-{
- VFS_FIND(statvfs);
- return handle->fns->statvfs(handle, path, statbuf);
-}
-
-uint32_t smb_vfs_call_fs_capabilities(struct vfs_handle_struct *handle,
- enum timestamp_set_resolution *p_ts_res)
-{
- VFS_FIND(fs_capabilities);
- return handle->fns->fs_capabilities(handle, p_ts_res);
-}
-
-SMB_STRUCT_DIR *smb_vfs_call_opendir(struct vfs_handle_struct *handle,
- const char *fname, const char *mask,
- uint32 attributes)
-{
- VFS_FIND(opendir);
- return handle->fns->opendir(handle, fname, mask, attributes);
-}
-
-SMB_STRUCT_DIRENT *smb_vfs_call_readdir(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dirp,
- SMB_STRUCT_STAT *sbuf)
-{
- VFS_FIND(readdir);
- return handle->fns->readdir(handle, dirp, sbuf);
-}
-
-void smb_vfs_call_seekdir(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dirp, long offset)
-{
- VFS_FIND(seekdir);
- handle->fns->seekdir(handle, dirp, offset);
-}
-
-long smb_vfs_call_telldir(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dirp)
-{
- VFS_FIND(telldir);
- return handle->fns->telldir(handle, dirp);
-}
-
-void smb_vfs_call_rewind_dir(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dirp)
-{
- VFS_FIND(rewind_dir);
- handle->fns->rewind_dir(handle, dirp);
-}
-
-int smb_vfs_call_mkdir(struct vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- VFS_FIND(mkdir);
- return handle->fns->mkdir(handle, path, mode);
-}
-
-int smb_vfs_call_rmdir(struct vfs_handle_struct *handle, const char *path)
-{
- VFS_FIND(rmdir);
- return handle->fns->rmdir(handle, path);
-}
-
-int smb_vfs_call_closedir(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dir)
-{
- VFS_FIND(closedir);
- return handle->fns->closedir(handle, dir);
-}
-
-void smb_vfs_call_init_search_op(struct vfs_handle_struct *handle,
- SMB_STRUCT_DIR *dirp)
-{
- VFS_FIND(init_search_op);
- handle->fns->init_search_op(handle, dirp);
-}
-
-int smb_vfs_call_open(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname, struct files_struct *fsp,
- int flags, mode_t mode)
-{
- VFS_FIND(open);
- return handle->fns->open(handle, smb_fname, fsp, flags, mode);
-}
-
-NTSTATUS smb_vfs_call_create_file(struct vfs_handle_struct *handle,
- struct smb_request *req,
- uint16_t root_dir_fid,
- struct smb_filename *smb_fname,
- uint32_t access_mask,
- uint32_t share_access,
- uint32_t create_disposition,
- uint32_t create_options,
- uint32_t file_attributes,
- uint32_t oplock_request,
- uint64_t allocation_size,
- struct security_descriptor *sd,
- struct ea_list *ea_list,
- files_struct **result,
- int *pinfo)
-{
- VFS_FIND(create_file);
- return handle->fns->create_file(
- handle, req, root_dir_fid, smb_fname, access_mask,
- share_access, create_disposition, create_options,
- file_attributes, oplock_request, allocation_size, sd, ea_list,
- result, pinfo);
-}
-
-int smb_vfs_call_close_fn(struct vfs_handle_struct *handle,
- struct files_struct *fsp)
-{
- VFS_FIND(close_fn);
- return handle->fns->close_fn(handle, fsp);
-}
-
-ssize_t smb_vfs_call_vfs_read(struct vfs_handle_struct *handle,
- struct files_struct *fsp, void *data, size_t n)
-{
- VFS_FIND(vfs_read);
- return handle->fns->vfs_read(handle, fsp, data, n);
-}
-
-ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
- struct files_struct *fsp, void *data, size_t n,
- SMB_OFF_T offset)
-{
- VFS_FIND(pread);
- return handle->fns->pread(handle, fsp, data, n, offset);
-}
-
-ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
- struct files_struct *fsp, const void *data,
- size_t n)
-{
- VFS_FIND(write);
- return handle->fns->write(handle, fsp, data, n);
-}
-
-ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
- struct files_struct *fsp, const void *data,
- size_t n, SMB_OFF_T offset)
-{
- VFS_FIND(pwrite);
- return handle->fns->pwrite(handle, fsp, data, n, offset);
-}
-
-SMB_OFF_T smb_vfs_call_lseek(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_OFF_T offset,
- int whence)
-{
- VFS_FIND(lseek);
- return handle->fns->lseek(handle, fsp, offset, whence);
-}
-
-ssize_t smb_vfs_call_sendfile(struct vfs_handle_struct *handle, int tofd,
- files_struct *fromfsp, const DATA_BLOB *header,
- SMB_OFF_T offset, size_t count)
-{
- VFS_FIND(sendfile);
- return handle->fns->sendfile(handle, tofd, fromfsp, header, offset,
- count);
-}
-
-ssize_t smb_vfs_call_recvfile(struct vfs_handle_struct *handle, int fromfd,
- files_struct *tofsp, SMB_OFF_T offset,
- size_t count)
-{
- VFS_FIND(recvfile);
- return handle->fns->recvfile(handle, fromfd, tofsp, offset, count);
-}
-
-int smb_vfs_call_rename(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
-{
- VFS_FIND(rename);
- return handle->fns->rename(handle, smb_fname_src, smb_fname_dst);
-}
-
-int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
- struct files_struct *fsp)
-{
- VFS_FIND(fsync);
- return handle->fns->fsync(handle, fsp);
-}
-
-int smb_vfs_call_stat(struct vfs_handle_struct *handle,
- struct smb_filename *smb_fname)
-{
- VFS_FIND(stat);
- return handle->fns->stat(handle, smb_fname);
-}
-
-int smb_vfs_call_fstat(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_STRUCT_STAT *sbuf)
-{
- VFS_FIND(fstat);
- return handle->fns->fstat(handle, fsp, sbuf);
-}
-
-int smb_vfs_call_lstat(struct vfs_handle_struct *handle,
- struct smb_filename *smb_filename)
-{
- VFS_FIND(lstat);
- return handle->fns->lstat(handle, smb_filename);
-}
-
-uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- const SMB_STRUCT_STAT *sbuf)
-{
- VFS_FIND(get_alloc_size);
- return handle->fns->get_alloc_size(handle, fsp, sbuf);
-}
-
-int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
-{
- VFS_FIND(unlink);
- return handle->fns->unlink(handle, smb_fname);
-}
-
-int smb_vfs_call_chmod(struct vfs_handle_struct *handle, const char *path,
- mode_t mode)
-{
- VFS_FIND(chmod);
- return handle->fns->chmod(handle, path, mode);
-}
-
-int smb_vfs_call_fchmod(struct vfs_handle_struct *handle,
- struct files_struct *fsp, mode_t mode)
-{
- VFS_FIND(fchmod);
- return handle->fns->fchmod(handle, fsp, mode);
-}
-
-int smb_vfs_call_chown(struct vfs_handle_struct *handle, const char *path,
- uid_t uid, gid_t gid)
-{
- VFS_FIND(chown);
- return handle->fns->chown(handle, path, uid, gid);
-}
-
-int smb_vfs_call_fchown(struct vfs_handle_struct *handle,
- struct files_struct *fsp, uid_t uid, gid_t gid)
-{
- VFS_FIND(fchown);
- return handle->fns->fchown(handle, fsp, uid, gid);
-}
-
-int smb_vfs_call_lchown(struct vfs_handle_struct *handle, const char *path,
- uid_t uid, gid_t gid)
-{
- VFS_FIND(lchown);
- return handle->fns->lchown(handle, path, uid, gid);
-}
-
-int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
-{
- VFS_FIND(chdir);
- return handle->fns->chdir(handle, path);
-}
-
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle, char *buf)
-{
- VFS_FIND(getwd);
- return handle->fns->getwd(handle, buf);
-}
-
-int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct smb_file_time *ft)
-{
- VFS_FIND(ntimes);
- return handle->fns->ntimes(handle, smb_fname, ft);
-}
-
-int smb_vfs_call_ftruncate(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_OFF_T offset)
-{
- VFS_FIND(ftruncate);
- return handle->fns->ftruncate(handle, fsp, offset);
-}
-
-int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
- struct files_struct *fsp, uint32 share_mode,
- uint32_t access_mask)
-{
- VFS_FIND(kernel_flock);
- return handle->fns->kernel_flock(handle, fsp, share_mode,
- access_mask);
-}
-
-int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
- struct files_struct *fsp, int leasetype)
-{
- VFS_FIND(linux_setlease);
- return handle->fns->linux_setlease(handle, fsp, leasetype);
-}
-
-int smb_vfs_call_symlink(struct vfs_handle_struct *handle, const char *oldpath,
- const char *newpath)
-{
- VFS_FIND(symlink);
- return handle->fns->symlink(handle, oldpath, newpath);
-}
-
-int smb_vfs_call_vfs_readlink(struct vfs_handle_struct *handle,
- const char *path, char *buf, size_t bufsiz)
-{
- VFS_FIND(vfs_readlink);
- return handle->fns->vfs_readlink(handle, path, buf, bufsiz);
-}
-
-int smb_vfs_call_link(struct vfs_handle_struct *handle, const char *oldpath,
- const char *newpath)
-{
- VFS_FIND(link);
- return handle->fns->link(handle, oldpath, newpath);
-}
-
-int smb_vfs_call_mknod(struct vfs_handle_struct *handle, const char *path,
- mode_t mode, SMB_DEV_T dev)
-{
- VFS_FIND(mknod);
- return handle->fns->mknod(handle, path, mode, dev);
-}
-
-char *smb_vfs_call_realpath(struct vfs_handle_struct *handle,
- const char *path, char *resolved_path)
-{
- VFS_FIND(realpath);
- return handle->fns->realpath(handle, path, resolved_path);
-}
-
-NTSTATUS smb_vfs_call_notify_watch(struct vfs_handle_struct *handle,
- struct sys_notify_context *ctx,
- struct notify_entry *e,
- void (*callback)(struct sys_notify_context *ctx,
- void *private_data,
- struct notify_event *ev),
- void *private_data, void *handle_p)
-{
- VFS_FIND(notify_watch);
- return handle->fns->notify_watch(handle, ctx, e, callback,
- private_data, handle_p);
-}
-
-int smb_vfs_call_chflags(struct vfs_handle_struct *handle, const char *path,
- unsigned int flags)
-{
- VFS_FIND(chflags);
- return handle->fns->chflags(handle, path, flags);
-}
-
-struct file_id smb_vfs_call_file_id_create(struct vfs_handle_struct *handle,
- const SMB_STRUCT_STAT *sbuf)
-{
- VFS_FIND(file_id_create);
- return handle->fns->file_id_create(handle, sbuf);
-}
-
-NTSTATUS smb_vfs_call_streaminfo(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- const char *fname,
- TALLOC_CTX *mem_ctx,
- unsigned int *num_streams,
- struct stream_struct **streams)
-{
- VFS_FIND(streaminfo);
- return handle->fns->streaminfo(handle, fsp, fname, mem_ctx,
- num_streams, streams);
-}
-
-int smb_vfs_call_get_real_filename(struct vfs_handle_struct *handle,
- const char *path, const char *name,
- TALLOC_CTX *mem_ctx, char **found_name)
-{
- VFS_FIND(get_real_filename);
- return handle->fns->get_real_filename(handle, path, name, mem_ctx,
- found_name);
-}
-
-const char *smb_vfs_call_connectpath(struct vfs_handle_struct *handle,
- const char *filename)
-{
- VFS_FIND(connectpath);
- return handle->fns->connectpath(handle, filename);
-}
-
-bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- struct lock_struct *plock)
-{
- VFS_FIND(strict_lock);
- return handle->fns->strict_lock(handle, fsp, plock);
-}
-
-void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- struct lock_struct *plock)
-{
- VFS_FIND(strict_unlock);
- handle->fns->strict_unlock(handle, fsp, plock);
-}
-
-NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle,
- const char *name,
- enum vfs_translate_direction direction,
- TALLOC_CTX *mem_ctx,
- char **mapped_name)
-{
- VFS_FIND(translate_name);
- return handle->fns->translate_name(handle, name, direction, mem_ctx,
- mapped_name);
-}
-
-NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- uint32 security_info,
- struct security_descriptor **ppdesc)
-{
- VFS_FIND(fget_nt_acl);
- return handle->fns->fget_nt_acl(handle, fsp, security_info,
- ppdesc);
-}
-
-NTSTATUS smb_vfs_call_get_nt_acl(struct vfs_handle_struct *handle,
- const char *name,
- uint32 security_info,
- struct security_descriptor **ppdesc)
-{
- VFS_FIND(get_nt_acl);
- return handle->fns->get_nt_acl(handle, name, security_info, ppdesc);
-}
-
-NTSTATUS smb_vfs_call_fset_nt_acl(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- uint32 security_info_sent,
- const struct security_descriptor *psd)
-{
- VFS_FIND(fset_nt_acl);
- return handle->fns->fset_nt_acl(handle, fsp, security_info_sent, psd);
-}
-
-int smb_vfs_call_chmod_acl(struct vfs_handle_struct *handle, const char *name,
- mode_t mode)
-{
- VFS_FIND(chmod_acl);
- return handle->fns->chmod_acl(handle, name, mode);
-}
-
-int smb_vfs_call_fchmod_acl(struct vfs_handle_struct *handle,
- struct files_struct *fsp, mode_t mode)
-{
- VFS_FIND(fchmod_acl);
- return handle->fns->fchmod_acl(handle, fsp, mode);
-}
-
-int smb_vfs_call_sys_acl_get_entry(struct vfs_handle_struct *handle,
- SMB_ACL_T theacl, int entry_id,
- SMB_ACL_ENTRY_T *entry_p)
-{
- VFS_FIND(sys_acl_get_entry);
- return handle->fns->sys_acl_get_entry(handle, theacl, entry_id,
- entry_p);
-}
-
-int smb_vfs_call_sys_acl_get_tag_type(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry_d,
- SMB_ACL_TAG_T *tag_type_p)
-{
- VFS_FIND(sys_acl_get_tag_type);
- return handle->fns->sys_acl_get_tag_type(handle, entry_d, tag_type_p);
-}
-
-int smb_vfs_call_sys_acl_get_permset(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry_d,
- SMB_ACL_PERMSET_T *permset_p)
-{
- VFS_FIND(sys_acl_get_permset);
- return handle->fns->sys_acl_get_permset(handle, entry_d, permset_p);
-}
-
-void * smb_vfs_call_sys_acl_get_qualifier(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry_d)
-{
- VFS_FIND(sys_acl_get_qualifier);
- return handle->fns->sys_acl_get_qualifier(handle, entry_d);
-}
-
-SMB_ACL_T smb_vfs_call_sys_acl_get_file(struct vfs_handle_struct *handle,
- const char *path_p,
- SMB_ACL_TYPE_T type)
-{
- VFS_FIND(sys_acl_get_file);
- return handle->fns->sys_acl_get_file(handle, path_p, type);
-}
-
-SMB_ACL_T smb_vfs_call_sys_acl_get_fd(struct vfs_handle_struct *handle,
- struct files_struct *fsp)
-{
- VFS_FIND(sys_acl_get_fd);
- return handle->fns->sys_acl_get_fd(handle, fsp);
-}
-
-int smb_vfs_call_sys_acl_clear_perms(struct vfs_handle_struct *handle,
- SMB_ACL_PERMSET_T permset)
-{
- VFS_FIND(sys_acl_clear_perms);
- return handle->fns->sys_acl_clear_perms(handle, permset);
-}
-
-int smb_vfs_call_sys_acl_add_perm(struct vfs_handle_struct *handle,
- SMB_ACL_PERMSET_T permset,
- SMB_ACL_PERM_T perm)
-{
- VFS_FIND(sys_acl_add_perm);
- return handle->fns->sys_acl_add_perm(handle, permset, perm);
-}
-
-char * smb_vfs_call_sys_acl_to_text(struct vfs_handle_struct *handle,
- SMB_ACL_T theacl, ssize_t *plen)
-{
- VFS_FIND(sys_acl_to_text);
- return handle->fns->sys_acl_to_text(handle, theacl, plen);
-}
-
-SMB_ACL_T smb_vfs_call_sys_acl_init(struct vfs_handle_struct *handle,
- int count)
-{
- VFS_FIND(sys_acl_init);
- return handle->fns->sys_acl_init(handle, count);
-}
-
-int smb_vfs_call_sys_acl_create_entry(struct vfs_handle_struct *handle,
- SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry)
-{
- VFS_FIND(sys_acl_create_entry);
- return handle->fns->sys_acl_create_entry(handle, pacl, pentry);
-}
-
-int smb_vfs_call_sys_acl_set_tag_type(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry,
- SMB_ACL_TAG_T tagtype)
-{
- VFS_FIND(sys_acl_set_tag_type);
- return handle->fns->sys_acl_set_tag_type(handle, entry, tagtype);
-}
-
-int smb_vfs_call_sys_acl_set_qualifier(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry, void *qual)
-{
- VFS_FIND(sys_acl_set_qualifier);
- return handle->fns->sys_acl_set_qualifier(handle, entry, qual);
-}
-
-int smb_vfs_call_sys_acl_set_permset(struct vfs_handle_struct *handle,
- SMB_ACL_ENTRY_T entry,
- SMB_ACL_PERMSET_T permset)
-{
- VFS_FIND(sys_acl_set_permset);
- return handle->fns->sys_acl_set_permset(handle, entry, permset);
-}
-
-int smb_vfs_call_sys_acl_valid(struct vfs_handle_struct *handle,
- SMB_ACL_T theacl)
-{
- VFS_FIND(sys_acl_valid);
- return handle->fns->sys_acl_valid(handle, theacl);
-}
-
-int smb_vfs_call_sys_acl_set_file(struct vfs_handle_struct *handle,
- const char *name, SMB_ACL_TYPE_T acltype,
- SMB_ACL_T theacl)
-{
- VFS_FIND(sys_acl_set_file);
- return handle->fns->sys_acl_set_file(handle, name, acltype, theacl);
-}
-
-int smb_vfs_call_sys_acl_set_fd(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_ACL_T theacl)
-{
- VFS_FIND(sys_acl_set_fd);
- return handle->fns->sys_acl_set_fd(handle, fsp, theacl);
-}
-
-int smb_vfs_call_sys_acl_delete_def_file(struct vfs_handle_struct *handle,
- const char *path)
-{
- VFS_FIND(sys_acl_delete_def_file);
- return handle->fns->sys_acl_delete_def_file(handle, path);
-}
-
-int smb_vfs_call_sys_acl_get_perm(struct vfs_handle_struct *handle,
- SMB_ACL_PERMSET_T permset,
- SMB_ACL_PERM_T perm)
-{
- VFS_FIND(sys_acl_get_perm);
- return handle->fns->sys_acl_get_perm(handle, permset, perm);
-}
-
-int smb_vfs_call_sys_acl_free_text(struct vfs_handle_struct *handle,
- char *text)
-{
- VFS_FIND(sys_acl_free_text);
- return handle->fns->sys_acl_free_text(handle, text);
-}
-
-int smb_vfs_call_sys_acl_free_acl(struct vfs_handle_struct *handle,
- SMB_ACL_T posix_acl)
-{
- VFS_FIND(sys_acl_free_acl);
- return handle->fns->sys_acl_free_acl(handle, posix_acl);
-}
-
-int smb_vfs_call_sys_acl_free_qualifier(struct vfs_handle_struct *handle,
- void *qualifier, SMB_ACL_TAG_T tagtype)
-{
- VFS_FIND(sys_acl_free_qualifier);
- return handle->fns->sys_acl_free_qualifier(handle, qualifier, tagtype);
-}
-
-ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
- const char *path, const char *name, void *value,
- size_t size)
-{
- VFS_FIND(getxattr);
- return handle->fns->getxattr(handle, path, name, value, size);
-}
-
-ssize_t smb_vfs_call_lgetxattr(struct vfs_handle_struct *handle,
- const char *path, const char *name, void *value,
- size_t size)
-{
- VFS_FIND(lgetxattr);
- return handle->fns->lgetxattr(handle, path, name, value, size);
-}
-
-ssize_t smb_vfs_call_fgetxattr(struct vfs_handle_struct *handle,
- struct files_struct *fsp, const char *name,
- void *value, size_t size)
-{
- VFS_FIND(fgetxattr);
- return handle->fns->fgetxattr(handle, fsp, name, value, size);
-}
-
-ssize_t smb_vfs_call_listxattr(struct vfs_handle_struct *handle,
- const char *path, char *list, size_t size)
-{
- VFS_FIND(listxattr);
- return handle->fns->listxattr(handle, path, list, size);
-}
-
-ssize_t smb_vfs_call_llistxattr(struct vfs_handle_struct *handle,
- const char *path, char *list, size_t size)
-{
- VFS_FIND(llistxattr);
- return handle->fns->llistxattr(handle, path, list, size);
-}
-
-ssize_t smb_vfs_call_flistxattr(struct vfs_handle_struct *handle,
- struct files_struct *fsp, char *list,
- size_t size)
-{
- VFS_FIND(flistxattr);
- return handle->fns->flistxattr(handle, fsp, list, size);
-}
-
-int smb_vfs_call_removexattr(struct vfs_handle_struct *handle,
- const char *path, const char *name)
-{
- VFS_FIND(removexattr);
- return handle->fns->removexattr(handle, path, name);
-}
-
-int smb_vfs_call_lremovexattr(struct vfs_handle_struct *handle,
- const char *path, const char *name)
-{
- VFS_FIND(lremovexattr);
- return handle->fns->lremovexattr(handle, path, name);
-}
-
-int smb_vfs_call_fremovexattr(struct vfs_handle_struct *handle,
- struct files_struct *fsp, const char *name)
-{
- VFS_FIND(fremovexattr);
- return handle->fns->fremovexattr(handle, fsp, name);
-}
-
-int smb_vfs_call_setxattr(struct vfs_handle_struct *handle, const char *path,
- const char *name, const void *value, size_t size,
- int flags)
-{
- VFS_FIND(setxattr);
- return handle->fns->setxattr(handle, path, name, value, size, flags);
-}
-
-int smb_vfs_call_lsetxattr(struct vfs_handle_struct *handle, const char *path,
- const char *name, const void *value, size_t size,
- int flags)
-{
- VFS_FIND(lsetxattr);
- return handle->fns->lsetxattr(handle, path, name, value, size, flags);
-}
-
-int smb_vfs_call_fsetxattr(struct vfs_handle_struct *handle,
- struct files_struct *fsp, const char *name,
- const void *value, size_t size, int flags)
-{
- VFS_FIND(fsetxattr);
- return handle->fns->fsetxattr(handle, fsp, name, value, size, flags);
-}
-
-int smb_vfs_call_aio_read(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_read);
- return handle->fns->aio_read(handle, fsp, aiocb);
-}
-
-int smb_vfs_call_aio_write(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_write);
- return handle->fns->aio_write(handle, fsp, aiocb);
-}
-
-ssize_t smb_vfs_call_aio_return_fn(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_return_fn);
- return handle->fns->aio_return_fn(handle, fsp, aiocb);
-}
-
-int smb_vfs_call_aio_cancel(struct vfs_handle_struct *handle,
- struct files_struct *fsp, SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_cancel);
- return handle->fns->aio_cancel(handle, fsp, aiocb);
-}
-
-int smb_vfs_call_aio_error_fn(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_error_fn);
- return handle->fns->aio_error_fn(handle, fsp, aiocb);
-}
-
-int smb_vfs_call_aio_fsync(struct vfs_handle_struct *handle,
- struct files_struct *fsp, int op,
- SMB_STRUCT_AIOCB *aiocb)
-{
- VFS_FIND(aio_fsync);
- return handle->fns->aio_fsync(handle, fsp, op, aiocb);
-}
-
-int smb_vfs_call_aio_suspend(struct vfs_handle_struct *handle,
- struct files_struct *fsp,
- const SMB_STRUCT_AIOCB * const aiocb[], int n,
- const struct timespec *timeout)
-{
- VFS_FIND(aio_suspend);
- return handle->fns->aio_suspend(handle, fsp, aiocb, n, timeout);
-}
-
-bool smb_vfs_call_aio_force(struct vfs_handle_struct *handle,
- struct files_struct *fsp)
-{
- VFS_FIND(aio_force);
- return handle->fns->aio_force(handle, fsp);
-}
-
-bool smb_vfs_call_is_offline(struct vfs_handle_struct *handle,
- const char *path, SMB_STRUCT_STAT *sbuf)
-{
- VFS_FIND(is_offline);
- return handle->fns->is_offline(handle, path, sbuf);
-}
-
-int smb_vfs_call_set_offline(struct vfs_handle_struct *handle,
- const char *path)
-{
- VFS_FIND(set_offline);
- return handle->fns->set_offline(handle, path);
-}