summaryrefslogtreecommitdiff
path: root/source3/smbd/nttrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/nttrans.c')
-rw-r--r--source3/smbd/nttrans.c220
1 files changed, 135 insertions, 85 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 9b6cfe1621..4e857c183c 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -424,10 +424,6 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
files_struct *fsp;
char *p = NULL;
- /* If it's a request for a directory open, fail it. */
- if(flags & OPEN_DIRECTORY)
- return(ERROR(ERRDOS,ERRnoaccess));
-
/*
* We need to construct the open_and_X ofun value from the
* NT values, as that's what our code is structured to accept.
@@ -459,7 +455,7 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
} else {
/*
- * Ordinary file.
+ * Ordinary file or directory.
*/
/*
@@ -495,66 +491,95 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
- /*
- * NB. We have a potential bug here. If we cause an oplock
- * break to ourselves, then we could end up processing filename
- * related SMB requests whilst we await the oplock break
- * response. As we may have changed the filename case
- * semantics to be POSIX-like, this could mean a filename
- * request could fail when it should succeed. This is a
- * rare condition, but eventually we must arrange to restore
- * the correct case semantics before issuing an oplock break
- * request to our client. JRA.
+ /*
+ * If it's a request for a directory open, deal with it separately.
*/
- open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
- oplock_request,&rmode,&smb_action);
+ if(flags & OPEN_DIRECTORY) {
+ oplock_request = 0;
- restore_case_semantics(file_attributes);
+ open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action);
+
+ restore_case_semantics(file_attributes);
+
+ if(!fsp->open) {
+ fsp->reserved = False;
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+ } else {
+
+ /*
+ * Ordinary file case.
+ */
- if (!fsp->open) {
/*
- * We cheat here. The only case we care about is a directory
- * rename, where the NT client will attempt to open the source
- * directory for DELETE access. Note that when the NT client
- * does this it does *not* set the directory bit in the
- * request packet. This is translated into a read/write open
- * request. POSIX states that any open for write request on a directory
- * will generate an EISDIR error, so we can catch this here and open
- * a pseudo handle that is flagged as a directory. JRA.
+ * NB. We have a potential bug here. If we cause an oplock
+ * break to ourselves, then we could end up processing filename
+ * related SMB requests whilst we await the oplock break
+ * response. As we may have changed the filename case
+ * semantics to be POSIX-like, this could mean a filename
+ * request could fail when it should succeed. This is a
+ * rare condition, but eventually we must arrange to restore
+ * the correct case semantics before issuing an oplock break
+ * request to our client. JRA.
*/
- if(errno == EISDIR) {
- oplock_request = 0;
- open_directory(fnum, cnum, fname, &smb_action);
+ open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
+ oplock_request,&rmode,&smb_action);
+
+ if (!fsp->open) {
+ /*
+ * We cheat here. The only case we care about is a directory
+ * rename, where the NT client will attempt to open the source
+ * directory for DELETE access. Note that when the NT client
+ * does this it does *not* set the directory bit in the
+ * request packet. This is translated into a read/write open
+ * request. POSIX states that any open for write request on a directory
+ * will generate an EISDIR error, so we can catch this here and open
+ * a pseudo handle that is flagged as a directory. JRA.
+ */
+
+ if(errno == EISDIR) {
+ oplock_request = 0;
+
+ open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action);
+
+ if(!fsp->open) {
+ fsp->reserved = False;
+ restore_case_semantics(file_attributes);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+ } else {
+ if((errno == ENOENT) && bad_path) {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
- if(!fsp->open) {
fsp->reserved = False;
+
+ restore_case_semantics(file_attributes);
+
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- } else {
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
- }
-
- fsp->reserved = False;
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- }
+ }
+ }
if(fsp->is_directory) {
- if(stat(fsp->name, &sbuf) != 0) {
+ if(sys_stat(fsp->name, &sbuf) != 0) {
close_directory(fnum);
+ restore_case_semantics(file_attributes);
return(ERROR(ERRDOS,ERRnoaccess));
}
} else {
- if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+ if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) {
close_file(fnum,False);
+ restore_case_semantics(file_attributes);
return(ERROR(ERRDOS,ERRnoaccess));
}
}
+ restore_case_semantics(file_attributes);
+
file_len = sbuf.st_size;
fmode = dos_mode(cnum,fname,&sbuf);
if(fmode == 0)
@@ -668,10 +693,6 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length,
files_struct *fsp;
char *p = NULL;
- /* If it's a request for a directory open, fail it. */
- if(flags & OPEN_DIRECTORY)
- return(ERROR(ERRDOS,ERRnoaccess));
-
/*
* We need to construct the open_and_X ofun value from the
* NT values, as that's what our code is structured to accept.
@@ -733,56 +754,85 @@ static int call_nt_transact_create(char *inbuf, char *outbuf, int length,
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
- open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
- oplock_request,&rmode,&smb_action);
+ /*
+ * If it's a request for a directory open, deal with it separately.
+ */
- fsp = &Files[fnum];
-
- if (!fsp->open) {
- if((errno == ENOENT) && bad_path) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
+ if(flags & OPEN_DIRECTORY) {
+
+ oplock_request = 0;
+
+ /*
+ * We will get a create directory here if the Win32
+ * app specified a security descriptor in the
+ * CreateDirectory() call.
+ */
+
+ open_directory(fnum, cnum, fname, smb_ofun, unixmode, &smb_action);
+
+ if(!fsp->open) {
+ fsp->reserved = False;
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- Files[fnum].reserved = False;
+ } else {
- restore_case_semantics(file_attributes);
+ /*
+ * Ordinary file case.
+ */
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
- close_file(fnum,False);
+ open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
+ oplock_request,&rmode,&smb_action);
- restore_case_semantics(file_attributes);
+ fsp = &Files[fnum];
+
+ if (!fsp->open) {
+ if((errno == ENOENT) && bad_path) {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ Files[fnum].reserved = False;
- return(ERROR(ERRDOS,ERRnoaccess));
- }
+ restore_case_semantics(file_attributes);
+
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- restore_case_semantics(file_attributes);
+ if (fstat(fsp->f_u.fd_ptr->fd,&sbuf) != 0) {
+ close_file(fnum,False);
- file_len = sbuf.st_size;
- fmode = dos_mode(cnum,fname,&sbuf);
- if(fmode == 0)
- fmode = FILE_ATTRIBUTE_NORMAL;
- mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
- close_file(fnum,False);
- return(ERROR(ERRDOS,ERRnoaccess));
- }
+ restore_case_semantics(file_attributes);
+
+ return(ERROR(ERRDOS,ERRnoaccess));
+ }
- /*
- * If the caller set the extended oplock request bit
- * and we granted one (by whatever means) - set the
- * correct bit for extended oplock reply.
- */
+ file_len = sbuf.st_size;
+ fmode = dos_mode(cnum,fname,&sbuf);
+ if(fmode == 0)
+ fmode = FILE_ATTRIBUTE_NORMAL;
+ mtime = sbuf.st_mtime;
+
+ if (fmode & aDIR) {
+ close_file(fnum,False);
+ restore_case_semantics(file_attributes);
+ return(ERROR(ERRDOS,ERRnoaccess));
+ }
+
+ /*
+ * If the caller set the extended oplock request bit
+ * and we granted one (by whatever means) - set the
+ * correct bit for extended oplock reply.
+ */
- if (oplock_request && lp_fake_oplocks(SNUM(cnum)))
- smb_action |= EXTENDED_OPLOCK_GRANTED;
+ if (oplock_request && lp_fake_oplocks(SNUM(cnum)))
+ smb_action |= EXTENDED_OPLOCK_GRANTED;
- if(oplock_request && fsp->granted_oplock)
- smb_action |= EXTENDED_OPLOCK_GRANTED;
+ if(oplock_request && fsp->granted_oplock)
+ smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
}
+ restore_case_semantics(file_attributes);
+
/* Realloc the size of parameters and data we will return */
params = *ppparams = Realloc(*ppparams, 69);
if(params == NULL)
@@ -972,7 +1022,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize)
DEBUG(2,("%s: reply_nttrans: queueing message NT_TRANSACT_CREATE \
due to being in oplock break state.\n", timestring() ));
- push_smb_message( inbuf, length);
+ push_oplock_pending_smb_message( inbuf, length);
return -1;
}