mirror of
https://github.com/samba-team/samba.git
synced 2025-08-24 21:49:29 +03:00
nttrans.c: Fix change_notify. Queue processing code wasn't changing to
the correct directory before doing the stat. Doh !
uid.c: Fix for performance in security=share mode. Invalid vuid meant
that in security=share mode Samba was always doing the become_user/
undebome_user pairs for *every* smb. This code fixes it, but tridge
should review for security implications.
Jeremy.
(This used to be commit c3663379fd
)
This commit is contained in:
@ -1071,6 +1071,19 @@ void process_pending_change_notify_queue(time_t t)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!become_service(cnum,True)) {
|
||||
DEBUG(0,("process_pending_change_notify_queue: Unable to become service cnum=%d. \
|
||||
Error was %s.\n", cnum, strerror(errno) ));
|
||||
/*
|
||||
* Remove the entry and return an error to the client.
|
||||
*/
|
||||
change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess);
|
||||
ubi_slRemNext( &change_notify_queue, prev);
|
||||
cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue));
|
||||
unbecome_user();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sys_stat(fsp->name, &st) < 0) {
|
||||
DEBUG(0,("process_pending_change_notify_queue: Unable to stat directory %s. \
|
||||
Error was %s.\n", fsp->name, strerror(errno) ));
|
||||
@ -1135,27 +1148,39 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length,
|
||||
if((!fsp->open) || (!fsp->is_directory) || (cnum != fsp->cnum))
|
||||
return(ERROR(ERRDOS,ERRbadfid));
|
||||
|
||||
/*
|
||||
* Setup the current directory information in the
|
||||
* directory entry in the files_struct. We will use
|
||||
* this to check against when the timer expires.
|
||||
*/
|
||||
|
||||
if(sys_stat(fsp->name, &st) < 0) {
|
||||
DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \
|
||||
Error was %s\n", fnum, fsp->name, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(fsp->f_u.dir_ptr == NULL) {
|
||||
|
||||
/*
|
||||
* No currently stored directory info - we must
|
||||
* generate it here.
|
||||
*/
|
||||
|
||||
if((fsp->f_u.dir_ptr = (dir_status_struct *)malloc(sizeof(dir_status_struct))) == NULL) {
|
||||
DEBUG(0,("call_nt_transact_notify_change: Malloc fail !\n" ));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fsp->f_u.dir_ptr->modify_time = st.st_mtime;
|
||||
fsp->f_u.dir_ptr->status_time = st.st_ctime;
|
||||
/*
|
||||
* Setup the current directory information in the
|
||||
* directory entry in the files_struct. We will use
|
||||
* this to check against when the timer expires.
|
||||
* NB. We only do this if there is no current directory
|
||||
* information in the directory struct - as when we start
|
||||
* monitoring file size etc. this information will start
|
||||
* becoming increasingly expensive to maintain, so we won't
|
||||
* want to re-generate it for every ChangeNofity call.
|
||||
*/
|
||||
|
||||
if(sys_stat(fsp->name, &st) < 0) {
|
||||
DEBUG(0,("call_nt_transact_notify_change: Unable to stat fnum = %d, name = %s. \
|
||||
Error was %s\n", fnum, fsp->name, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fsp->f_u.dir_ptr->modify_time = st.st_mtime;
|
||||
fsp->f_u.dir_ptr->status_time = st.st_ctime;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Now queue an entry on the notify change stack. We timestamp
|
||||
@ -1183,8 +1208,8 @@ static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int length,
|
||||
|
||||
ubi_slAddTail(&change_notify_queue, cnbp);
|
||||
|
||||
DEBUG(3,("call_nt_transact_notify_change: notify change called on directory fid=%d, name = %s\n",
|
||||
fnum, fsp->name ));
|
||||
DEBUG(3,("call_nt_transact_notify_change: notify change called on directory \
|
||||
fid=%d, name = %s\n", fnum, fsp->name ));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -216,7 +216,18 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
|
||||
int snum,gid;
|
||||
int uid;
|
||||
|
||||
if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) &&
|
||||
/*
|
||||
* We need a separate check in security=share mode due to vuid
|
||||
* always being UID_FIELD_INVALID. If we don't do this then
|
||||
* in share mode security we are *always* changing uid's between
|
||||
* SMB's - this hurts performance - Badly.
|
||||
*/
|
||||
|
||||
if((lp_security() == SEC_SHARE) && (current_user.cnum == cnum) &&
|
||||
(current_user.uid == conn->uid)) {
|
||||
DEBUG(4,("Skipping become_user - already user\n"));
|
||||
return(True);
|
||||
} else if ((current_user.cnum == cnum) && (vuser != 0) && (current_user.vuid == vuid) &&
|
||||
(current_user.uid == vuser->uid)) {
|
||||
DEBUG(4,("Skipping become_user - already user\n"));
|
||||
return(True);
|
||||
|
Reference in New Issue
Block a user