diff options
author | cvs2svn Import User <samba-bugs@samba.org> | 1997-10-15 01:38:14 +0000 |
---|---|---|
committer | cvs2svn Import User <samba-bugs@samba.org> | 1997-10-15 01:38:14 +0000 |
commit | dc1f10efa87576a0289fa71aaeed015a3675b029 (patch) | |
tree | fca7a02192adb888fe6b4d239c5d1fa32d0a08ca /source/smbd | |
parent | 332f78bbc945c327069e9c9e29c7137c8cbd5c02 (diff) | |
parent | a173a1495c50b5ad1f6b47710cf4b4a7a2226b46 (diff) | |
download | samba-dc1f10efa87576a0289fa71aaeed015a3675b029.tar.gz |
This commit was manufactured by cvs2svn to create tagsamba-1.9.17p3
'release-1-9-17p3'.
Diffstat (limited to 'source/smbd')
-rw-r--r-- | source/smbd/dir.c | 6 | ||||
-rw-r--r-- | source/smbd/ipc.c | 19 | ||||
-rw-r--r-- | source/smbd/mangle.c | 207 | ||||
-rw-r--r-- | source/smbd/password.c | 62 | ||||
-rw-r--r-- | source/smbd/pipes.c | 6 | ||||
-rw-r--r-- | source/smbd/predict.c | 39 | ||||
-rw-r--r-- | source/smbd/quotas.c | 27 | ||||
-rw-r--r-- | source/smbd/reply.c | 300 | ||||
-rw-r--r-- | source/smbd/server.c | 1206 | ||||
-rw-r--r-- | source/smbd/trans2.c | 37 | ||||
-rw-r--r-- | source/smbd/uid.c | 84 |
11 files changed, 682 insertions, 1311 deletions
diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 316b58818fd..567bc14424e 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -470,12 +470,12 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) continue; - pstrcpy(fname,filename); + strcpy(fname,filename); *path = 0; - pstrcpy(path,Connections[cnum].dirpath); + strcpy(path,Connections[cnum].dirpath); if(needslash) strcat(path,"/"); - pstrcpy(pathreal,path); + strcpy(pathreal,path); strcat(path,fname); strcat(pathreal,dname); if (sys_stat(pathreal,&sbuf) != 0) diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index b9355c4ec07..1d7ee375d3f 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -440,7 +440,7 @@ static void PackDriverData(struct pack_desc* desc) } static int check_printq_info(struct pack_desc* desc, - int uLevel, char *id1, char *id2) + int uLevel, char *id1, const char* id2) { desc->subformat = NULL; switch( uLevel ) { @@ -1074,7 +1074,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data, *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); - SSVAL(*rparam,0,NERR_Success); + SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA)); SSVAL(*rparam,2,0); SSVAL(*rparam,4,counted); SSVAL(*rparam,6,counted+missed); @@ -1601,13 +1601,14 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, name[l] = 0; DEBUG(3,("Setting print name to %s\n",name)); + + become_root(1); for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].open && Files[i].print_file) { pstring wd; GetWd(wd); - unbecome_user(); if (!become_user(Files[i].cnum,vuid) || !become_service(Files[i].cnum,True)) @@ -1617,6 +1618,8 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data, string_set(&Files[i].name,name); break; } + + unbecome_root(1); } desc.errcode=NERR_Success; @@ -2219,7 +2222,6 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, int uLevel; struct pack_desc desc; char* name; - char* logon_script; uLevel = SVAL(p,0); name = p + 2; @@ -2262,14 +2264,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data, PACKS(&desc,"z",mypath); /* computer */ } PACKS(&desc,"z",myworkgroup);/* domain */ - -/* JHT - By calling lp_logon_script() and standard_sub() we have */ -/* made sure all macros are fully substituted and available */ - logon_script = lp_logon_script(); - standard_sub( cnum, logon_script ); - PACKS(&desc,"z", logon_script); /* script path */ -/* End of JHT mods */ - + PACKS(&desc,"z",lp_logon_script()); /* script path */ PACKI(&desc,"D",0x00000000); /* reserved */ } diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c index b0a45ffb47c..66e8233df28 100644 --- a/source/smbd/mangle.c +++ b/source/smbd/mangle.c @@ -123,34 +123,30 @@ BOOL is_8_3(char *fname, BOOL check_case) { char *p = fname; - if(lp_client_code_page() == KANJI_CODEPAGE) - { - dot_pos = 0; - while (*p) +#ifdef KANJI + dot_pos = 0; + while (*p) { - if (is_shift_jis (*p)) - p += 2; - else if (is_kana (*p)) - p ++; - else - { - if (*p == '.' && !dot_pos) - dot_pos = (char *) p; - if (!isdoschar(*p)) - return(False); - p++; - } - } - } - else - { - while (*p) + if (is_shift_jis (*p)) { + p += 2; + } else if (is_kana (*p)) { + p ++; + } else { + if (*p == '.' && !dot_pos) + dot_pos = (char *) p; + if (!isdoschar(*p)) + return(False); + p++; + } + } +#else + while (*p) { - if (!isdoschar(*p)) - return(False); - p++; + if (!isdoschar(*p)) + return(False); + p++; } - } +#endif /* KANJI */ } /* no dot and less than 9 means OK */ @@ -502,90 +498,84 @@ void mangle_name_83(char *s) DEBUG(5,("Mangling name %s to ",s)); if (p) - { - if (p == s) - strcpy(extension,"___"); - else + { + if (p == s) + strcpy(extension,"___"); + else { *p++ = 0; while (*p && extlen < 3) - { - if(lp_client_code_page() == KANJI_CODEPAGE) - { - if (is_shift_jis (*p)) - { - if (extlen < 2) - { - extension[extlen++] = p[0]; - extension[extlen++] = p[1]; - } - else - { - extension[extlen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } - else if (is_kana (*p)) - { - extension[extlen++] = p[0]; - p++; - } - else - { - if (isdoschar (*p) && *p != '.') - extension[extlen++] = p[0]; - p++; - } - } - else - { - if (isdoschar(*p) && *p != '.') - extension[extlen++] = *p; - p++; - } - } + { +#ifdef KANJI + if (is_shift_jis (*p)) + { + if (extlen < 2) + { + extension[extlen++] = p[0]; + extension[extlen++] = p[1]; + } + else + { + extension[extlen++] = base36 (((unsigned char) *p) % 36); + } + p += 2; + } + else if (is_kana (*p)) + { + extension[extlen++] = p[0]; + p++; + } + else + { + if (isdoschar (*p) && *p != '.') + extension[extlen++] = p[0]; + p++; + } +#else + if (isdoschar(*p) && *p != '.') + extension[extlen++] = *p; + p++; +#endif /* KANJI */ + } extension[extlen] = 0; + } } - } p = s; while (*p && baselen < 5) - { - if(lp_client_code_page() == KANJI_CODEPAGE) { +#ifdef KANJI if (is_shift_jis (*p)) - { - if (baselen < 4) - { - base[baselen++] = p[0]; - base[baselen++] = p[1]; - } - else - { + { + if (baselen < 4) + { + base[baselen++] = p[0]; + base[baselen++] = p[1]; + } + else + { base[baselen++] = base36 (((unsigned char) *p) % 36); - } - p += 2; - } + } + p += 2; + } else if (is_kana (*p)) - { - base[baselen++] = p[0]; - p++; - } + { + base[baselen++] = p[0]; + p++; + } else - { - if (isdoschar (*p) && *p != '.') - base[baselen++] = p[0]; - p++; - } - } - else - { + { + if (isdoschar (*p) && *p != '.') + base[baselen++] = p[0]; + p++; + } +#else if (isdoschar(*p) && *p != '.') - base[baselen++] = *p; + base[baselen++] = *p; p++; +#endif /* KANJI */ } - } base[baselen] = 0; csum = csum % (36*36); @@ -611,9 +601,8 @@ static BOOL illegal_name(char *name) static BOOL initialised=False; unsigned char *s; - if (!initialised) - { - char *ill = "*\\/?<>|\":{}"; + if (!initialised) { + char *ill = "*\\/?<>|\":"; initialised = True; bzero((char *)illegal,256); @@ -621,23 +610,21 @@ static BOOL illegal_name(char *name) illegal[*s] = True; } - if(lp_client_code_page() == KANJI_CODEPAGE) - { - for (s = (unsigned char *)name; *s;) { - if (is_shift_jis (*s)) { - s += 2; - } else if (illegal[*s]) { - return(True); - } else { - s++; - } +#ifdef KANJI + for (s = (unsigned char *)name; *s;) { + if (is_shift_jis (*s)) { + s += 2; + } else if (illegal[*s]) { + return(True); + } else { + s++; } } - else - { - for (s = (unsigned char *)name;*s;s++) - if (illegal[*s]) return(True); - } +#else + for (s = (unsigned char *)name;*s;s++) + if (illegal[*s]) return(True); +#endif + return(False); } diff --git a/source/smbd/password.c b/source/smbd/password.c index f4d94791cf3..6d84a5ff61c 100644 --- a/source/smbd/password.c +++ b/source/smbd/password.c @@ -36,6 +36,7 @@ static char this_user[100]=""; static char this_salt[100]=""; static char this_crypted[100]=""; +#ifdef SMB_PASSWD /* Data to do lanman1/2 password challenge. */ static unsigned char saved_challenge[8]; static BOOL challenge_sent=False; @@ -45,24 +46,17 @@ Get the next challenge value - no repeats. ********************************************************************/ void generate_next_challenge(char *challenge) { - unsigned char buf[16]; - static int counter = 0; - struct timeval tval; - int v1,v2; - - /* get a sort-of random number */ - GetTimeOfDay(&tval); - v1 = (counter++) + getpid() + tval.tv_sec; - v2 = (counter++) * getpid() + tval.tv_usec; - SIVAL(challenge,0,v1); - SIVAL(challenge,4,v2); - - /* mash it up with md4 */ - mdfour(buf, (unsigned char *)challenge, 8); - - memcpy(saved_challenge, buf, 8); - memcpy(challenge,buf,8); - challenge_sent = True; + static int counter = 0; + struct timeval tval; + int v1,v2; + GetTimeOfDay(&tval); + v1 = (counter++) + getpid() + tval.tv_sec; + v2 = (counter++) * getpid() + tval.tv_usec; + SIVAL(challenge,0,v1); + SIVAL(challenge,4,v2); + E1((uchar *)challenge,(uchar *)"SAMBA",(uchar *)saved_challenge); + memcpy(challenge,saved_challenge,8); + challenge_sent = True; } /******************************************************************* @@ -84,6 +78,7 @@ BOOL last_challenge(char *challenge) memcpy(challenge,saved_challenge,8); return(True); } +#endif /* this holds info on user ids that are already validated for this VC */ static user_struct *validated_users = NULL; @@ -406,7 +401,7 @@ static char *PAM_password; * echo off means password. */ static int PAM_conv (int num_msg, - struct pam_message **msg, + const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { int count = 0, replies = 0; @@ -817,6 +812,7 @@ Hence we make a direct return to avoid a second chance!!! #endif } +#ifdef SMB_PASSWD /**************************************************************************** core of smb password checking routine. ****************************************************************************/ @@ -858,6 +854,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha #endif return (memcmp(p24, password, 24) == 0); } +#endif /**************************************************************************** check if a username/password is OK @@ -867,16 +864,21 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) pstring pass2; int level = lp_passwordlevel(); struct passwd *pass; +#ifdef SMB_PASSWD char challenge[8]; struct smb_passwd *smb_pass; BOOL challenge_done = False; +#endif if (password) password[pwlen] = 0; +#ifdef SMB_PASSWD if (pwlen == 24) challenge_done = last_challenge(challenge); +#endif #if DEBUG_PASSWORD +#ifdef SMB_PASSWD if (challenge_done) { int i; @@ -884,9 +886,10 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) for( i = 0; i < 24; i++) DEBUG(100,("%0x ", (unsigned char)password[i])); DEBUG(100,("]\n")); - } else { - DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); } + else +#endif + DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); #endif if (!password) @@ -903,6 +906,8 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) else pass = Get_Pwnam(user,True); +#ifdef SMB_PASSWD + DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); if((pwlen == 24) && challenge_done) @@ -959,6 +964,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) DEBUG(3,("Error smb_password_check failed\n")); } +#endif DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); @@ -1520,7 +1526,7 @@ BOOL server_cryptkey(char *buf) struct in_addr dest_ip; int port = SMB_PORT; BOOL ret; - + if(secserver_inbuf == NULL) { secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); if(secserver_inbuf == NULL) { @@ -1590,12 +1596,12 @@ BOOL server_cryptkey(char *buf) and the remote machine name. */ { - char buf2[32]; /* create name as PIDname */ - sprintf(buf2,"%d", getpid()); - strncpy(&buf2[strlen(buf2)], remote_machine, 31 - strlen(buf2)); - buf2[31] = '\0'; - DEBUG(1,("negprot w/password server as %s\n",buf2)); - name_mangle(buf2,p,' '); + char buf[32]; /* create name as PIDname */ + sprintf(buf,"%d", getpid()); + strncpy(&buf[strlen(buf)], remote_machine, 31 - strlen(buf)); + buf[31] = '\0'; + DEBUG(1,("negprot w/password server as %s\n",buf)); + name_mangle(buf,p,' '); len += name_len(p); } diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c index a465e911459..2cc6eea506f 100644 --- a/source/smbd/pipes.c +++ b/source/smbd/pipes.c @@ -127,7 +127,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr); open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - 0, &rmode,&smb_action); + &rmode,&smb_action); if (!Files[fnum].open) { @@ -141,7 +141,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -149,7 +149,7 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } diff --git a/source/smbd/predict.c b/source/smbd/predict.c index 691d8fbb4e0..7d6b2498f5a 100644 --- a/source/smbd/predict.c +++ b/source/smbd/predict.c @@ -53,24 +53,37 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num) offset >= rp_offset && possible>0 && smb_last_time-rp_time < rp_timeout) - { - ret = possible; - if (buf) - memcpy(buf,rp_buffer + (offset-rp_offset),possible); - else - *ptr = rp_buffer + (offset-rp_offset); - DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); - } + { + ret = possible; + if (buf) + memcpy(buf,rp_buffer + (offset-rp_offset),possible); + else + *ptr = rp_buffer + (offset-rp_offset); + DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num)); + } if (ret == num) { predict_skip = True; } else { - predict_skip = False; + struct stat rp_stat; + + /* Find the end of the file - ensure we don't + read predict beyond it. */ + if(fstat(fd,&rp_stat) < 0) + { + DEBUG(0,("read-prediction failed on fstat. Error was %s\n", strerror(errno))); + predict_skip = True; + } + else + { + predict_skip = False; - /* prepare the next prediction */ - rp_predict_fd = fd; - rp_predict_offset = offset + num; - rp_predict_length = num; + /* prepare the next prediction */ + rp_predict_fd = fd; + /* Make sure we don't seek beyond the end of the file. */ + rp_predict_offset = MIN((offset + num),rp_stat.st_size); + rp_predict_length = num; + } } if (ret < 0) ret = 0; diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index d4f746c9e36..2d238dfaf17 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -416,10 +416,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } return (True); } + #else #ifdef __FreeBSD__ #include <ufs/ufs/quota.h> +#include <machine/param.h> #elif AIX /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */ #include <jfs/quota.h> @@ -463,7 +465,25 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) } #else /* USE_SETRES */ #if defined(__FreeBSD__) - r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D); + { + /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ + uid_t user_id; + gid_t egrp_id; + + /* Need to be root to get quotas in FreeBSD */ + user_id = getuid(); + egrp_id = getegid(); + setuid(0); + seteuid(0); + r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); + + /* As FreeBSD has group quotas, if getting the user + quota fails, try getting the group instead. */ + if (r) + r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); + setuid(user_id); + seteuid(euser_id); + } #elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ @@ -474,7 +494,12 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize) #endif /* USE_SETRES */ /* Use softlimit to determine disk space, except when it has been exceeded */ +#if defined(__FreeBSD__) + *bsize = DEV_BSIZE; +#else /* !__FreeBSD__ */ *bsize = 1024; +#endif /*!__FreeBSD__ */ + if (r) { if (errno == EDQUOT) diff --git a/source/smbd/reply.c b/source/smbd/reply.c index a8f674183c5..ffa80aac870 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -42,7 +42,6 @@ extern BOOL short_case_preserve; extern pstring sesssetup_user; extern fstring myworkgroup; extern int Client; -extern int global_oplock_break; /* this macro should always be used to extract an fnum (smb_fid) from a packet to ensure chaining works correctly */ @@ -66,18 +65,18 @@ static void overflow_attack(int len) ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) { - int outsize = 4; - int msg_type = CVAL(inbuf,0); - int msg_flags = CVAL(inbuf,1); - pstring name1,name2; - extern fstring remote_machine; - extern fstring local_machine; - char *p; - - *name1 = *name2 = 0; - - smb_setlen(outbuf,0); - + int outsize = 4; + int msg_type = CVAL(inbuf,0); + int msg_flags = CVAL(inbuf,1); + pstring name1,name2; + extern fstring remote_machine; + extern fstring local_machine; + char *p; + + *name1 = *name2 = 0; + + smb_setlen(outbuf,0); + switch (msg_type) { case 0x81: /* session request */ CVAL(outbuf,0) = 0x82; @@ -122,15 +121,15 @@ int reply_special(char *inbuf,char *outbuf) DEBUG(0,("Unexpected session response\n")); break; - case 0x85: /* session keepalive */ - default: - return(0); - } - + case 0x85: /* session keepalive */ + default: + return(0); + } + DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n", timestring(),msg_type,msg_flags)); - - return(outsize); + + return(outsize); } @@ -252,7 +251,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize) if ((SVAL(inbuf,smb_vwv2) & 0x1) != 0) close_cnum(SVAL(inbuf,smb_tid),vuid); - if (passlen > MAX_PASSWORD_LENGTH) { + if (passlen > MAX_PASS_LEN) { overflow_attack(passlen); } @@ -388,7 +387,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (Protocol < PROTOCOL_NT1) { smb_apasslen = SVAL(inbuf,smb_vwv7); - if (smb_apasslen > MAX_PASSWORD_LENGTH) + if (smb_apasslen > MAX_PASS_LEN) { overflow_attack(smb_apasslen); } @@ -423,12 +422,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (passlen1 != 24 && passlen2 != 24) doencrypt = False; - if (passlen1 > MAX_PASSWORD_LENGTH) { + if (passlen1 > MAX_PASS_LEN) { overflow_attack(passlen1); } - passlen1 = MIN(passlen1, MAX_PASSWORD_LENGTH); - passlen2 = MIN(passlen2, MAX_PASSWORD_LENGTH); + passlen1 = MIN(passlen1, MAX_PASS_LEN); + passlen2 = MIN(passlen2, MAX_PASS_LEN); if(doencrypt) { /* Save the lanman2 password and the NT md4 password. */ @@ -599,7 +598,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize) if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); - DEBUG(6,("Client requested max send size of %d\n", max_send)); + DEBUG(5,(" Client requested max send size of %d\n", max_send)); done_sesssetup = True; @@ -640,15 +639,6 @@ int reply_chkpth(char *inbuf,char *outbuf) unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - - /* Ugly - NT specific hack - but needed (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } - return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1111,8 +1101,6 @@ int reply_open(char *inbuf,char *outbuf) int rmode=0; struct stat sbuf; BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); cnum = SVAL(inbuf,smb_tid); @@ -1137,12 +1125,9 @@ int reply_open(char *inbuf,char *outbuf) unixmode = unix_mode(cnum,aARCH); - open_file_shared(fnum,cnum,fname,share_mode,3,unixmode, - oplock_request,&rmode,NULL); - - fsp = &Files[fnum]; + open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL); - if (!fsp->open) + if (!Files[fnum].open) { if((errno == ENOENT) && bad_path) { @@ -1152,8 +1137,8 @@ int reply_open(char *inbuf,char *outbuf) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1163,7 +1148,7 @@ int reply_open(char *inbuf,char *outbuf) if (fmode & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fname)); - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1174,12 +1159,10 @@ int reply_open(char *inbuf,char *outbuf) SIVAL(outbuf,smb_vwv4,size); SSVAL(outbuf,smb_vwv6,rmode); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + if (lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); } - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; return(outsize); } @@ -1194,7 +1177,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) int fnum = -1; int smb_mode = SVAL(inbuf,smb_vwv3); int smb_attr = SVAL(inbuf,smb_vwv5); - BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf); + BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1); #if 0 int open_flags = SVAL(inbuf,smb_vwv2); int smb_sattr = SVAL(inbuf,smb_vwv4); @@ -1206,7 +1189,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) struct stat sbuf; int smb_action = 0; BOOL bad_path = False; - files_struct *fsp; /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(cnum)) @@ -1234,11 +1216,9 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) unixmode = unix_mode(cnum,smb_attr | aARCH); open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode, - oplock_request, &rmode,&smb_action); + &rmode,&smb_action); - fsp = &Files[fnum]; - - if (!fsp->open) + if (!Files[fnum].open) { if((errno == ENOENT) && bad_path) { @@ -1248,8 +1228,8 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) return(UNIXERROR(ERRDOS,ERRnoaccess)); } - if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -1257,18 +1237,12 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize) fmode = dos_mode(cnum,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - } - - if(fsp->granted_oplock) { - smb_action |= EXTENDED_OPLOCK_GRANTED; - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + smb_action |= (1<<15); } set_message(outbuf,15,0,True); @@ -1303,7 +1277,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize) int i; for (i=0;i<MAX_OPEN_FILES;i++) if (Files[i].uid == vuser->uid && Files[i].open) { - close_file(i); + close_file(i, 0); } } @@ -1330,8 +1304,6 @@ int reply_mknew(char *inbuf,char *outbuf) mode_t unixmode; int ofun = 0; BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); com = SVAL(inbuf,smb_com); cnum = SVAL(inbuf,smb_tid); @@ -1373,12 +1345,9 @@ int reply_mknew(char *inbuf,char *outbuf) } /* Open file in dos compatibility share mode. */ - open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, - oplock_request, NULL, NULL); + open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL); - fsp = &Files[fnum]; - - if (!fsp->open) + if (!Files[fnum].open) { if((errno == ENOENT) && bad_path) { @@ -1391,13 +1360,10 @@ int reply_mknew(char *inbuf,char *outbuf) outsize = set_message(outbuf,1,0,True); SSVAL(outbuf,smb_vwv0,fnum); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + if (lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); } - - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - + DEBUG(2,("new file %s\n",fname)); DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); @@ -1418,8 +1384,6 @@ int reply_ctemp(char *inbuf,char *outbuf) int createmode; mode_t unixmode; BOOL bad_path = False; - files_struct *fsp; - int oplock_request = CORE_OPLOCK_REQUEST(inbuf); cnum = SVAL(inbuf,smb_tid); createmode = SVAL(inbuf,smb_vwv0); @@ -1447,12 +1411,9 @@ int reply_ctemp(char *inbuf,char *outbuf) /* Open file in dos compatibility share mode. */ /* We should fail if file exists. */ - open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, - oplock_request, NULL, NULL); + open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL); - fsp = &Files[fnum]; - - if (!fsp->open) + if (!Files[fnum].open) { if((errno == ENOENT) && bad_path) { @@ -1467,13 +1428,10 @@ int reply_ctemp(char *inbuf,char *outbuf) CVAL(smb_buf(outbuf),0) = 4; strcpy(smb_buf(outbuf) + 1,fname2); - if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; + if (lp_fake_oplocks(SNUM(cnum))) { + CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5)); } - if(fsp->granted_oplock) - CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED; - DEBUG(2,("created temp file %s\n",fname2)); DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode)); @@ -1621,22 +1579,6 @@ int reply_readbraw(char *inbuf, char *outbuf) int fd; char *fname; -#ifdef USE_OPLOCKS - /* - * Special check if an oplock break has been issued - * and the readraw request croses on the wire, we must - * return a zero length response here. - */ - - if(global_oplock_break) - { - _smb_setlen(header,0); - transfer_file(0,Client,0,header,4,0); - DEBUG(5,("readbraw - oplock break finished\n")); - return -1; - } -#endif - cnum = SVAL(inbuf,smb_tid); fnum = GETFNUM(inbuf,smb_vwv0); @@ -2248,7 +2190,7 @@ int reply_close(char *inbuf,char *outbuf) /* try and set the date */ set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum, 1); /* We have a cached error */ if(eclass || err) @@ -2295,7 +2237,7 @@ int reply_writeclose(char *inbuf,char *outbuf) set_filetime(Files[fnum].name,mtime); - close_file(fnum); + close_file(fnum, 1); DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n", timestring(),fnum,cnum,numtowrite,nwritten, @@ -2492,8 +2434,7 @@ int reply_printopen(char *inbuf,char *outbuf) return(ERROR(ERRDOS,ERRnoaccess)); /* Open for exclusive use, write only. */ - open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), - 0, NULL, NULL); + open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL); if (!Files[fnum].open) return(UNIXERROR(ERRDOS,ERRnoaccess)); @@ -2527,7 +2468,7 @@ int reply_printclose(char *inbuf,char *outbuf) if (!CAN_PRINT(cnum)) return(ERROR(ERRDOS,ERRnoaccess)); - close_file(fnum); + close_file(fnum, 1); DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum)); @@ -2695,66 +2636,6 @@ int reply_mkdir(char *inbuf,char *outbuf) return(outsize); } -/**************************************************************************** -Static function used by reply_rmdir to delete an entire directory -tree recursively. -****************************************************************************/ -static BOOL recursive_rmdir(char *directory) -{ - char *dname = NULL; - BOOL ret = False; - void *dirptr = OpenDir(-1, directory, False); - - if(dirptr == NULL) - return True; - - while((dname = ReadDirName(dirptr))) - { - pstring fullname; - struct stat st; - - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) - continue; - - /* Construct the full name. */ - if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) - { - errno = ENOMEM; - ret = True; - break; - } - strcpy(fullname, directory); - strcat(fullname, "/"); - strcat(fullname, dname); - - if(sys_lstat(fullname, &st) != 0) - { - ret = True; - break; - } - - if(st.st_mode & S_IFDIR) - { - if(recursive_rmdir(fullname)!=0) - { - ret = True; - break; - } - if(sys_rmdir(fullname) != 0) - { - ret = True; - break; - } - } - else if(sys_unlink(fullname) != 0) - { - ret = True; - break; - } - } - CloseDir(dirptr); - return ret; -} /**************************************************************************** reply to a rmdir @@ -2823,15 +2704,10 @@ int reply_rmdir(char *inbuf,char *outbuf) if(sys_lstat(fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) - { - if(lp_recursive_veto_delete(SNUM(cnum))) { - if(recursive_rmdir(fullname) != 0) + if(sys_rmdir(fullname) != 0) break; } - if(sys_rmdir(fullname) != 0) - break; - } else if(sys_unlink(fullname) != 0) break; } @@ -3155,7 +3031,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum1 = find_free_file(); if (fnum1<0) return(False); open_file_shared(fnum1,cnum,src,(DENY_NONE<<4), - 1,0,0,&Access,&action); + 1,0,&Access,&action); if (!Files[fnum1].open) return(False); @@ -3164,14 +3040,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, fnum2 = find_free_file(); if (fnum2<0) { - close_file(fnum1); + close_file(fnum1, 0); return(False); } open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1, - ofun,st.st_mode,0,&Access,&action); + ofun,st.st_mode,&Access,&action); if (!Files[fnum2].open) { - close_file(fnum1); + close_file(fnum1, 0); return(False); } @@ -3182,8 +3058,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun, if (st.st_size) ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0); - close_file(fnum1); - close_file(fnum2); + close_file(fnum1, 0); + close_file(fnum2, 0); return(ret == st.st_size); } @@ -3370,10 +3246,7 @@ int reply_setdir(char *inbuf,char *outbuf) int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) { int fnum = GETFNUM(inbuf,smb_vwv2); - unsigned char locktype = CVAL(inbuf,smb_vwv3); -#if 0 - unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1); -#endif /* USE_OPLOCKS */ + uint16 locktype = SVAL(inbuf,smb_vwv3); uint16 num_ulocks = SVAL(inbuf,smb_vwv6); uint16 num_locks = SVAL(inbuf,smb_vwv7); uint32 count, offset; @@ -3390,50 +3263,6 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize) CHECK_ERROR(fnum); data = smb_buf(inbuf); - -#ifdef USE_OPLOCKS - /* Check if this is an oplock break on a file - we have granted an oplock on. - */ - if((locktype == LOCKING_ANDX_OPLOCK_RELEASE) && - (num_ulocks == 0) && (num_locks == 0) && - (CVAL(inbuf,smb_vwv0) == 0xFF)) - { - share_lock_token token; - files_struct *fsp = &Files[fnum]; - uint32 dev = fsp->fd_ptr->dev; - uint32 inode = fsp->fd_ptr->inode; - - DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n", - fnum)); - /* - * Make sure we have granted an oplock on this file. - */ - if(!fsp->granted_oplock) - { - DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file.\n", fnum)); - return ERROR(ERRDOS,ERRlock); - } - - /* Remove the oplock flag from the sharemode. */ - lock_share_entry(fsp->cnum, dev, inode, &token); - if(remove_share_oplock( fnum, token)==False) - { - DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \ -dev = %x, inode = %x\n", fnum, dev, inode)); - unlock_share_entry(fsp->cnum, dev, inode, token); - return -1; - } - unlock_share_entry(fsp->cnum, dev, inode, token); - - /* Clear the granted flag and return. */ - - fsp->granted_oplock = False; - return -1; - } -#endif /* USE_OPLOCKS */ - /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { @@ -3468,7 +3297,7 @@ dev = %x, inode = %x\n", fnum, dev, inode)); set_message(outbuf,2,0,True); DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n", - timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks)); + timestring(),fnum,cnum,locktype,num_locks,num_ulocks)); chain_fnum = fnum; @@ -3821,3 +3650,8 @@ int reply_getattrE(char *inbuf,char *outbuf) return(outsize); } + + + + + diff --git a/source/smbd/server.c b/source/smbd/server.c index b250572a1f4..3bfd5bbbf40 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -84,16 +84,6 @@ int chain_fnum = -1; /* number of open connections */ static int num_connections_open = 0; -#ifdef USE_OPLOCKS -/* Oplock ipc UDP socket. */ -int oplock_sock = -1; -uint16 oplock_port = 0; -/* Current number of oplocks we have outstanding. */ -int32 global_oplocks_open = 0; -#endif /* USE_OPLOCKS */ - -BOOL global_oplock_break = False; - extern fstring remote_machine; pstring OriginalDir; @@ -189,7 +179,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) int result = 0; extern struct current_user current_user; - DEBUG(8,("dos_mode: %d %s\n", cnum, path)); + DEBUG(5,("dos_mode: %d %s\n", cnum, path)); if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) { if (!((sbuf->st_mode & S_IWOTH) || @@ -241,15 +231,15 @@ int dos_mode(int cnum,char *path,struct stat *sbuf) result |= aHIDDEN; } - DEBUG(8,("dos_mode returning ")); + DEBUG(5,("dos_mode returning ")); - if (result & aHIDDEN) DEBUG(8, ("h")); - if (result & aRONLY ) DEBUG(8, ("r")); - if (result & aSYSTEM) DEBUG(8, ("s")); - if (result & aDIR ) DEBUG(8, ("d")); - if (result & aARCH ) DEBUG(8, ("a")); + if (result & aHIDDEN) DEBUG(5, ("h")); + if (result & aRONLY ) DEBUG(5, ("r")); + if (result & aSYSTEM) DEBUG(5, ("s")); + if (result & aDIR ) DEBUG(5, ("d")); + if (result & aARCH ) DEBUG(5, ("a")); - DEBUG(8,("\n")); + DEBUG(5,("\n")); return(result); } @@ -713,7 +703,15 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize) dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -803,7 +801,15 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024; dfree_retval : dfreeq_retval ; /* maybe dfree and dfreeq are calculated using different bsizes so convert dfree from bsize into bsizeq */ - *dfree = ((*dfree) * (*bsize)) / (bsizeq); + /* avoid overflows due to multiplication, so do not: + *dfree = ((*dfree) * (*bsize)) / (bsizeq); + bsize and bsizeq are powers of 2 so its better to + to divide them getting a multiplication or division factor + for dfree. Rene Nieuwenhuizen (07-10-1997) */ + if (*bsize >= bsizeq) + *dfree = *dfree * (*bsize / bsizeq); + else + *dfree = *dfree / (bsizeq / *bsize); *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; *bsize = bsizeq; *dsize = dsizeq; @@ -886,7 +892,8 @@ static void check_for_pipe(char *fname) /**************************************************************************** fd support routines - attempt to do a sys_open ****************************************************************************/ -static int fd_attempt_open(char *fname, int flags, int mode) + +int fd_attempt_open(char *fname, int flags, int mode) { int fd = sys_open(fname,flags,mode); @@ -938,7 +945,7 @@ static int fd_attempt_open(char *fname, int flags, int mode) fd support routines - attempt to find an already open file by dev and inode - increments the ref_count of the returned file_fd_struct *. ****************************************************************************/ -static file_fd_struct *fd_get_already_open(struct stat *sbuf) +file_fd_struct *fd_get_already_open(struct stat *sbuf) { int i; file_fd_struct *fd_ptr; @@ -965,7 +972,7 @@ static file_fd_struct *fd_get_already_open(struct stat *sbuf) fd support routines - attempt to find a empty slot in the FileFd array. Increments the ref_count of the returned entry. ****************************************************************************/ -static file_fd_struct *fd_get_new() +file_fd_struct *fd_get_new() { int i; file_fd_struct *fd_ptr; @@ -998,7 +1005,8 @@ n")); fd support routines - attempt to re-open an already open fd as O_RDWR. Save the already open fd (we cannot close due to POSIX file locking braindamage. ****************************************************************************/ -static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) + +void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) { int fd = sys_open( fname, O_RDWR, mode); @@ -1018,7 +1026,7 @@ static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr) fd support routines - attempt to close the file referenced by this fd. Decrements the ref_count and returns it. ****************************************************************************/ -static int fd_attempt_close(file_fd_struct *fd_ptr) +int fd_attempt_close(file_fd_struct *fd_ptr) { DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n", fd_ptr - &FileFd[0], @@ -1054,11 +1062,9 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct pstring fname; struct stat statbuf; file_fd_struct *fd_ptr; - files_struct *fsp = &Files[fnum]; - fsp->open = False; - fsp->fd_ptr = 0; - fsp->granted_oplock = False; + Files[fnum].open = False; + Files[fnum].fd_ptr = 0; errno = EPERM; pstrcpy(fname,fname1); @@ -1196,7 +1202,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct if (sys_disk_free(dname,&dum1,&dum2,&dum3) < lp_minprintspace(SNUM(cnum))) { fd_attempt_close(fd_ptr); - fsp->fd_ptr = 0; + Files[fnum].fd_ptr = 0; if(fd_ptr->ref_count == 0) sys_unlink(fname); errno = ENOSPC; @@ -1232,26 +1238,25 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct fd_ptr->dev = (uint32)sbuf->st_dev; fd_ptr->inode = (uint32)sbuf->st_ino; - fsp->fd_ptr = fd_ptr; + Files[fnum].fd_ptr = fd_ptr; Connections[cnum].num_files_open++; - fsp->mode = sbuf->st_mode; - GetTimeOfDay(&fsp->open_time); - fsp->uid = current_user.id; - fsp->size = 0; - fsp->pos = -1; - fsp->open = True; - fsp->mmap_ptr = NULL; - fsp->mmap_size = 0; - fsp->can_lock = True; - fsp->can_read = ((flags & O_WRONLY)==0); - fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); - fsp->share_mode = 0; - fsp->print_file = Connections[cnum].printer; - fsp->modified = False; - fsp->granted_oplock = False; - fsp->cnum = cnum; - string_set(&fsp->name,dos_to_unix(fname,False)); - fsp->wbmpx_ptr = NULL; + Files[fnum].mode = sbuf->st_mode; + GetTimeOfDay(&Files[fnum].open_time); + Files[fnum].uid = current_user.id; + Files[fnum].size = 0; + Files[fnum].pos = -1; + Files[fnum].open = True; + Files[fnum].mmap_ptr = NULL; + Files[fnum].mmap_size = 0; + Files[fnum].can_lock = True; + Files[fnum].can_read = ((flags & O_WRONLY)==0); + Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + Files[fnum].share_mode = 0; + Files[fnum].print_file = Connections[cnum].printer; + Files[fnum].modified = False; + Files[fnum].cnum = cnum; + string_set(&Files[fnum].name,dos_to_unix(fname,False)); + Files[fnum].wbmpx_ptr = NULL; /* * If the printer is marked as postscript output a leading @@ -1260,8 +1265,8 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct * This has a similar effect as CtrlD=0 in WIN.INI file. * tim@fsg.com 09/06/94 */ - if (fsp->print_file && POSTSCRIPT(cnum) && - fsp->can_write) + if (Files[fnum].print_file && POSTSCRIPT(cnum) && + Files[fnum].can_write) { DEBUG(3,("Writing postscript line\n")); write_file(fnum,"%!\n",3); @@ -1269,23 +1274,23 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n", timestring(),Connections[cnum].user,fname, - BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write), + BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write), Connections[cnum].num_files_open,fnum)); } #if USE_MMAP /* mmap it if read-only */ - if (!fsp->can_write) + if (!Files[fnum].can_write) { - fsp->mmap_size = file_size(fname); - fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size, - PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0); + Files[fnum].mmap_size = file_size(fname); + Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size, + PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0); - if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) + if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr) { DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno))); - fsp->mmap_ptr = NULL; + Files[fnum].mmap_ptr = NULL; } } #endif @@ -1343,8 +1348,13 @@ static void check_magic(int fnum,int cnum) /**************************************************************************** close a file - possibly invalidating the read prediction + +If normal_close is 1 then this came from a normal SMBclose (or equivalent) +operation otherwise it came as the result of some other operation such as +the closing of the connection. In the latter case printing and +magic scripts are not run ****************************************************************************/ -void close_file(int fnum) +void close_file(int fnum, int normal_close) { files_struct *fs_p = &Files[fnum]; int cnum = fs_p->cnum; @@ -1356,17 +1366,17 @@ void close_file(int fnum) fs_p->open = False; Connections[cnum].num_files_open--; if(fs_p->wbmpx_ptr) - { - free((char *)fs_p->wbmpx_ptr); - fs_p->wbmpx_ptr = NULL; - } + { + free((char *)fs_p->wbmpx_ptr); + fs_p->wbmpx_ptr = NULL; + } #if USE_MMAP if(fs_p->mmap_ptr) - { - munmap(fs_p->mmap_ptr,fs_p->mmap_size); - fs_p->mmap_ptr = NULL; - } + { + munmap(fs_p->mmap_ptr,fs_p->mmap_size); + fs_p->mmap_ptr = NULL; + } #endif if (lp_share_modes(SNUM(cnum))) @@ -1381,11 +1391,12 @@ void close_file(int fnum) unlock_share_entry( cnum, dev, inode, token); /* NT uses smbclose to start a print - weird */ - if (fs_p->print_file) + if (normal_close && fs_p->print_file) print_file(fnum); /* check for magic scripts */ - check_magic(fnum,cnum); + if (normal_close) + check_magic(fnum,cnum); DEBUG(2,("%s %s closed file %s (numopen=%d)\n", timestring(),Connections[cnum].user,fs_p->name, @@ -1403,8 +1414,7 @@ static int access_table(int new_deny,int old_deny,int old_mode, if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL); if (new_deny == DENY_DOS || old_deny == DENY_DOS) { - int pid = getpid(); - if (old_deny == new_deny && share_pid == pid) + if (old_deny == new_deny && share_pid == getpid()) return(AALL); if (old_mode == 0) return(AREAD); @@ -1458,76 +1468,23 @@ BOOL check_file_sharing(int cnum,char *fname) struct stat sbuf; share_lock_token token; int pid = getpid(); - uint32 dev, inode; if(!lp_share_modes(SNUM(cnum))) return True; if (stat(fname,&sbuf) == -1) return(True); - dev = (uint32)sbuf.st_dev; - inode = (uint32)sbuf.st_ino; - - lock_share_entry(cnum, dev, inode, &token); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token); + num_share_modes = get_share_modes(cnum, token, + (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares); - /* - * Check if the share modes will give us access. - */ - - if(num_share_modes != 0) + for( i = 0; i < num_share_modes; i++) { - BOOL broke_oplock; - - do - { - - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - min_share_mode_entry *share_entry = &old_shares[i]; - -#ifdef USE_OPLOCKS - /* - * Break oplocks before checking share modes. See comment in - * open_file_shared for details. - * Check if someone has an oplock on this file. If so we must - * break it before continuing. - */ - if(share_entry->op_type & BATCH_OPLOCK) - { - - DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - return False; - } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; - } -#endif /* USE_OPLOCKS */ - - /* someone else has a share lock on it, check to see - if we can too */ - if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid)) - goto free_and_exit; + if (old_shares[i].share_mode != DENY_DOS) + goto free_and_exit; - } /* end for */ - - if(broke_oplock) - { - free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); - } - } while(broke_oplock); + if(old_shares[i].pid != pid) + goto free_and_exit; } /* XXXX exactly what share mode combinations should be allowed for @@ -1538,7 +1495,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); free_and_exit: - unlock_share_entry(cnum, dev, inode, token); + unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token); if(old_shares != NULL) free((char *)old_shares); return(ret); @@ -1559,7 +1516,7 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, if (*share_locked && lp_share_modes(SNUM(cnum))) unlock_share_entry( cnum, Files[fnum].fd_ptr->dev, Files[fnum].fd_ptr->inode, token); - close_file(fnum); + close_file(fnum, 0); /* Share mode no longer locked. */ *share_locked = False; errno = EACCES; @@ -1571,52 +1528,12 @@ static void truncate_unless_locked(int fnum, int cnum, share_lock_token token, } } -/**************************************************************************** -check if we can open a file with a share mode -****************************************************************************/ -int check_share_mode( min_share_mode_entry *share, int deny_mode, char *fname, - BOOL fcbopen, int *flags) -{ - int old_open_mode = share->share_mode &0xF; - int old_deny_mode = (share->share_mode >>4)&7; - - if (old_deny_mode > 4 || old_open_mode > 2) - { - DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", - deny_mode,old_deny_mode,old_open_mode,fname)); - return False; - } - - { - int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, - share->pid,fname); - - if ((access_allowed == AFAIL) || - (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) || - (access_allowed == AREAD && *flags == O_WRONLY) || - (access_allowed == AWRITE && *flags == O_RDONLY)) - { - DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", - deny_mode,old_deny_mode,old_open_mode, - share->pid,fname, access_allowed)); - return False; - } - - if (access_allowed == AREAD) - *flags = O_RDONLY; - - if (access_allowed == AWRITE) - *flags = O_WRONLY; - - } - return True; -} /**************************************************************************** open a file with a share mode ****************************************************************************/ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, - int mode,int oplock_request, int *Access,int *action) + int mode,int *Access,int *action) { files_struct *fs_p = &Files[fnum]; int flags=0; @@ -1629,7 +1546,6 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, share_lock_token token; uint32 dev = 0; uint32 inode = 0; - int num_share_modes = 0; fs_p->open = False; fs_p->fd_ptr = 0; @@ -1701,88 +1617,69 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun, if (lp_share_modes(SNUM(cnum))) { + int num_shares = 0; int i; min_share_mode_entry *old_shares = 0; + if (file_existed) { dev = (uint32)sbuf.st_dev; inode = (uint32)sbuf.st_ino; lock_share_entry(cnum, dev, inode, &token); share_locked = True; - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + num_shares = get_share_modes(cnum, token, dev, inode, &old_shares); } - /* - * Check if the share modes will give us access. - */ - - if(share_locked && (num_share_modes != 0)) + for(i = 0; i < num_shares; i++) { - BOOL broke_oplock; + /* someone else has a share lock on it, check to see + if we can too */ + int old_open_mode = old_shares[i].share_mode &0xF; + int old_deny_mode = (old_shares[i].share_mode >>4)&7; - do + if (old_deny_mode > 4 || old_open_mode > 2) { + DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n", + deny_mode,old_deny_mode,old_open_mode,fname)); + free((char *)old_shares); + if(share_locked) + unlock_share_entry(cnum, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; + } - broke_oplock = False; - for(i = 0; i < num_share_modes; i++) - { - min_share_mode_entry *share_entry = &old_shares[i]; - -#ifdef USE_OPLOCKS - /* - * By observation of NetBench, oplocks are broken *before* share - * modes are checked. This allows a file to be closed by the client - * if the share mode would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so we must break - * it before continuing. - */ - if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) - { - - DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode)); - - /* Oplock break.... */ - unlock_share_entry(cnum, dev, inode, token); - if(request_oplock_break(share_entry, dev, inode) == False) - { - free((char *)old_shares); - DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \ -dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - lock_share_entry(cnum, dev, inode, &token); - broke_oplock = True; - break; - } -#endif /* USE_OPLOCKS */ - - /* someone else has a share lock on it, check to see - if we can too */ - if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False) - { - free((char *)old_shares); - unlock_share_entry(cnum, dev, inode, token); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - return; - } - - } /* end for */ + { + int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode, + old_shares[i].pid,fname); - if(broke_oplock) + if ((access_allowed == AFAIL) || + (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) || + (access_allowed == AREAD && flags == O_WRONLY) || + (access_allowed == AWRITE && flags == O_RDONLY)) { + DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n", + deny_mode,old_deny_mode,old_open_mode, + old_shares[i].pid,fname, + access_allowed)); free((char *)old_shares); - num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares); + if(share_locked) + unlock_share_entry(cnum, dev, inode, token); + errno = EACCES; + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRbadshare; + return; } - } while(broke_oplock); + + if (access_allowed == AREAD) + flags = O_RDONLY; + + if (access_allowed == AWRITE) + flags = O_WRONLY; + } } - if(old_shares != 0) free((char *)old_shares); } @@ -1839,35 +1736,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode)); file (which expects the share_mode_entry to be there). */ if (lp_share_modes(SNUM(cnum))) - { - uint16 port = 0; -#ifdef USE_OPLOCKS - /* JRA. Currently this only services Exlcusive and batch - oplocks (no other opens on this file). This needs to - be extended to level II oplocks (multiple reader - oplocks). */ - - if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum))) - { - fs_p->granted_oplock = True; - global_oplocks_open++; - port = oplock_port; - - DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \ -dev = %x, inode = %x\n", oplock_request, fname, dev, inode)); - - } - else - { - port = 0; - oplock_request = 0; - } -#else /* USE_OPLOCKS */ - oplock_request = 0; - port = 0; -#endif /* USE_OPLOCKS */ - set_share_mode(token, fnum, port, oplock_request); - } + set_share_mode(token, fnum); if ((flags2&O_TRUNC) && file_existed) truncate_unless_locked(fnum,cnum,token,&share_locked); @@ -2116,7 +1985,11 @@ struct {EPERM,ERRDOS,ERRnoaccess}, {EACCES,ERRDOS,ERRnoaccess}, {ENOENT,ERRDOS,ERRbadfile}, +#if 0 /* Go back to old method for now. */ + {ENOTDIR,ERRDOS,ERRbaddirectory}, +#else {ENOTDIR,ERRDOS,ERRbadpath}, +#endif {EIO,ERRHRD,ERRgeneral}, {EBADF,ERRSRV,ERRsrverror}, {EINVAL,ERRSRV,ERRsrverror}, @@ -2137,6 +2010,23 @@ struct {0,0,0} }; +#if 0 /* Go back to old method for now. */ +/* Mapping for old clients. */ + +struct +{ + int new_smb_error; + int old_smb_error; + int protocol_level; + enum remote_arch_types valid_ra_type; +} old_client_errmap[] = +{ + {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT}, + {0,0,0} +}; + +#endif /* Go back to old method for now. */ + /**************************************************************************** create an error packet from errno ****************************************************************************/ @@ -2167,6 +2057,32 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int } } +#if 0 /* Go back to old method for now. */ + + /* Make sure we don't return error codes that old + clients don't understand. */ + + /* JRA - unfortunately, WinNT needs some error codes + for apps to work correctly, Win95 will break if + these error codes are returned. But they both + negotiate the *same* protocol. So we need to use + the revolting 'remote_arch' enum to tie break. + + There must be a better way of doing this... + */ + + for(i = 0; old_client_errmap[i].new_smb_error != 0; i++) + { + if(((Protocol < old_client_errmap[i].protocol_level) || + (old_client_errmap[i].valid_ra_type != get_remote_arch())) && + (old_client_errmap[i].new_smb_error == ecode)) + { + ecode = old_client_errmap[i].old_smb_error; + break; + } + } +#endif /* Go back to old method for now. */ + return(error_packet(inbuf,outbuf,eclass,ecode,line)); } @@ -2373,516 +2289,6 @@ static BOOL open_sockets(BOOL is_daemon,int port) return True; } -/**************************************************************************** - process an smb from the client - split out from the process() code so - it can be used by the oplock break code. -****************************************************************************/ - -static void process_smb(char *inbuf, char *outbuf) -{ - extern int Client; - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (!check_access(-1)) { - /* send a negative session response "not listining on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG(1,("%s Connection denied from %s\n", - timestring(),client_addr())); - send_smb(Client,(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); - DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); - -#ifdef WITH_VTP - if(trans_num == 1 && VT_Check(inbuf)) - { - VT_Process(); - return; - } -#endif - - if (msg_type == 0) - show_msg(inbuf); - - nread = construct_reply(inbuf,outbuf,nread,max_send); - - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - send_smb(Client,outbuf); - } - trans_num++; -} - -#ifdef USE_OPLOCKS -/**************************************************************************** - open the oplock IPC socket communication -****************************************************************************/ -static BOOL open_oplock_ipc() -{ - struct sockaddr_in sock_name; - int name_len = sizeof(sock_name); - - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK)); - if (oplock_sock == -1) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno))); - oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &name_len)<0) - { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - oplock_port = 0; - return False; - } - oplock_port = ntohs(sock_name.sin_port); - - return True; -} - -/**************************************************************************** - process an oplock break message. -****************************************************************************/ -static BOOL process_local_message(int oplock_sock, char *buffer, int buf_size) -{ - int32 msg_len; - int16 from_port; - char *msg_start; - - msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET); - from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET); - - msg_start = &buffer[UDP_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* Switch on message command - currently OPLOCK_BREAK_CMD is the - only valid request. */ - - switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET)) - { - case OPLOCK_BREAK_CMD: - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) - { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \ -should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN)); - return False; - } - { - uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET); - uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET); - uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET); - struct timeval tval; - struct sockaddr_in toaddr; - - tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET); - tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET); - - DEBUG(5,("process_local_message: oplock break request from \ -pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode)); - - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just return success in this case. - */ - - if(global_oplocks_open != 0) - { - if(oplock_break(dev, inode, &tval) == False) - { - DEBUG(0,("process_local_message: oplock break failed - \ -not returning udp message.\n")); - return False; - } - } - else - { - DEBUG(3,("process_local_message: oplock break requested with no outstanding \ -oplocks. Returning success.\n")); - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY); - - bzero((char *)&toaddr,sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) - { - DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n", - remotepid, strerror(errno))); - return False; - } - - DEBUG(5,("process_local_message: oplock break reply sent to \ -pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, - from_port, dev, inode)); - - } - break; - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - return True; -} - -/**************************************************************************** - Process an oplock break directly. -****************************************************************************/ -BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval) -{ - extern int Client; - static char *inbuf = NULL; - static char *outbuf = NULL; - files_struct *fsp = NULL; - int fnum; - time_t start_time; - BOOL shutdown_server = False; - - DEBUG(5,("oplock_break: called for dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", dev, inode, global_oplocks_open)); - - if(inbuf == NULL) - { - inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(inbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; - } - outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); - if(outbuf == NULL) { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - free(inbuf); - inbuf = NULL; - return False; - } - } - - /* We need to search the file open table for the - entry containing this dev and inode, and ensure - we have an oplock on it. */ - for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++) - { - if(OPEN_FNUM(fnum)) - { - fsp = &Files[fnum]; - if((fsp->fd_ptr->dev == dev) && (fsp->fd_ptr->inode == inode) && - (fsp->open_time.tv_sec == tval->tv_sec) && - (fsp->open_time.tv_usec == tval->tv_usec)) - break; - } - } - - if(fsp == NULL) - { - /* The file could have been closed in the meantime - return success. */ - DEBUG(3,("oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \ -allowing break to succeed.\n", dev, inode, fnum)); - return True; - } - - /* Ensure we have an oplock on the file */ - - /* There is a potential race condition in that an oplock could - have been broken due to another udp request, and yet there are - still oplock break messages being sent in the udp message - queue for this file. So return true if we don't have an oplock, - as we may have just freed it. - */ - - if(!fsp->granted_oplock) - { - DEBUG(3,("oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. \ -Allowing break to succeed regardless.\n", fsp->name, fnum, dev, inode)); - return True; - } - - /* Now comes the horrid part. We must send an oplock break to the client, - and then process incoming messages until we get a close or oplock release. - */ - - /* Prepare the SMBlockingX message. */ - bzero(outbuf,smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - /* Change this when we have level II oplocks. */ - SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE); - - send_smb(Client, outbuf); - - global_oplock_break = True; - - /* Process incoming messages. */ - - /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - seconds we should just die.... */ - - start_time = time(NULL); - - while(OPEN_FNUM(fnum) && fsp->granted_oplock) - { - if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False) - { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) - DEBUG(0,("oplock_break: end of file from client\n")); - - if (smb_read_error == READ_ERROR) - DEBUG(0,("oplock_break: receive_smb error (%s)\n", - strerror(errno))); - - if (smb_read_error == READ_TIMEOUT) - DEBUG(0,("oplock_break: receive_smb timed out after %d seconds.\n", - OPLOCK_BREAK_TIMEOUT)); - - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); - shutdown_server = True; - break; - } - process_smb(inbuf, outbuf); - - /* We only need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * Die if we go over the time limit. - */ - - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) - { - DEBUG(0,("oplock_break: no break received from client within \ -%d seconds.\n", OPLOCK_BREAK_TIMEOUT)); - DEBUG(0,("oplock_break failed for file %s (fnum = %d, dev = %x, \ -inode = %x).\n", fsp->name, fnum, dev, inode)); - shutdown_server = True; - break; - } - } - - /* - * If the client did not respond we must die. - */ - - if(shutdown_server) - { - DEBUG(0,("oplock_break: client failure in break - shutting down this smbd.\n")); - close_sockets(); - close(oplock_sock); - exit_server("oplock break failure"); - } - - if(OPEN_FNUM(fnum)) - { - /* The lockingX reply will have removed the oplock flag - from the sharemode. */ - /* Paranoia.... */ - fsp->granted_oplock = False; - } - - global_oplocks_open--; - - /* Santity check - remove this later. JRA */ - if(global_oplocks_open < 0) - { - DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n", - global_oplocks_open)); - abort(); - } - - DEBUG(5,("oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \ -global_oplocks_open = %d\n", fnum, dev, inode, global_oplocks_open)); - - return True; -} - -/**************************************************************************** -Send an oplock break message to another smbd process. If the oplock is held -by the local smbd then call the oplock break function directly. -****************************************************************************/ - -BOOL request_oplock_break(min_share_mode_entry *share_entry, - uint32 dev, uint32 inode) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - int pid = getpid(); - - if(pid == share_entry->pid) - { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != oplock_port) - { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", pid, share_entry->op_port, oplock_port)); - return False; - } - - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); - - /* Call oplock break direct. */ - return oplock_break(dev, inode, &share_entry->time); - } - - /* We need to send a OPLOCK_BREAK_CMD message to the - port in the share mode entry. */ - - SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD); - SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid); - SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev); - SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode); - SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec); - SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec); - - /* set the address and port */ - bzero((char *)&addr_out,sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - DEBUG(3,("request_oplock_break: sending a oplock break message to pid %d on port %d \ -for dev = %x, inode = %x\n", share_entry->pid, share_entry->op_port, dev, inode)); - - if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) - { - DEBUG(0,("request_oplock_break: failed when sending a oplock break message \ -to pid %d on port %d for dev = %x, inode = %x. Error was %s\n", - share_entry->pid, share_entry->op_port, dev, inode, - strerror(errno))); - return False; - } - - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in OPLOCK_BREAK_TIMEOUT seconds. - * While we get messages that aren't ours, loop. - */ - - while(1) - { - char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - int32 reply_msg_len; - int16 reply_from_port; - char *reply_msg_start; - - if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply), - OPLOCK_BREAK_TIMEOUT * 1000) == False) - { - if(smb_read_error == READ_TIMEOUT) - DEBUG(0,("request_oplock_break: no response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x\n", share_entry->pid, - share_entry->op_port, dev, inode)); - else - DEBUG(0,("request_oplock_break: error in response received to oplock break request to \ -pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", share_entry->pid, - share_entry->op_port, dev, inode, strerror(errno))); - return False; - } - - /* - * If the response we got was not an answer to our message, but - * was a completely different request, push it onto the pending - * udp message stack so that we can deal with it in the main loop. - * It may be another oplock break request to us. - */ - - /* - * Local note from JRA. There exists the possibility of a denial - * of service attack here by allowing non-root processes running - * on a local machine sending many of these pending messages to - * a smbd port. Currently I'm not sure how to restrict the messages - * I will queue (although I could add a limit to the queue) to - * those received by root processes only. There should be a - * way to make this bulletproof.... - */ - - reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET); - reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET); - - reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN]; - - if(reply_msg_len != OPLOCK_BREAK_MSG_LEN) - { - /* Ignore it. */ - DEBUG(0,("request_oplock_break: invalid message length received. Ignoring\n")); - continue; - } - - if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) || - (reply_from_port != share_entry->op_port) || - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], - &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0)) - { - DEBUG(3,("request_oplock_break: received other message whilst awaiting \ -oplock break response from pid %d on port %d for dev = %x, inode = %x.\n", - share_entry->pid, share_entry->op_port, dev, inode)); - if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False) - return False; - } - - break; - } - - DEBUG(3,("request_oplock_break: broke oplock.\n")); - - return True; -} - -#endif /* USE_OPLOCKS */ /**************************************************************************** check if a snum is in use @@ -3440,15 +2846,19 @@ int reply_lanman1(char *outbuf) set_message(outbuf,13,doencrypt?8:0,True); SSVAL(outbuf,smb_vwv1,secword); +#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) generate_next_challenge(smb_buf(outbuf)); +#endif Protocol = PROTOCOL_LANMAN1; if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ @@ -3487,9 +2897,11 @@ int reply_lanman2(char *outbuf) set_message(outbuf,13,doencrypt?8:0,True); SSVAL(outbuf,smb_vwv1,secword); +#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) generate_next_challenge(smb_buf(outbuf)); +#endif SIVAL(outbuf,smb_vwv6,getpid()); @@ -3497,7 +2909,9 @@ int reply_lanman2(char *outbuf) if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif } CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */ @@ -3567,6 +2981,7 @@ int reply_nt1(char *outbuf) #endif CVAL(outbuf,smb_vwv1) = secword; +#ifdef SMB_PASSWD /* Create a token value and add it to the outgoing packet. */ if (doencrypt) { @@ -3575,12 +2990,15 @@ int reply_nt1(char *outbuf) /* Tell the nt machine how long the challenge is. */ SSVALS(outbuf,smb_vwv16+1,challenge_len); } +#endif Protocol = PROTOCOL_NT1; if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) { DEBUG(3,("using password server validation\n")); +#ifdef SMB_PASSWD if (doencrypt) set_challenge(smb_buf(outbuf)); +#endif } SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */ @@ -3791,7 +3209,7 @@ static void close_open_files(int cnum) int i; for (i=0;i<MAX_OPEN_FILES;i++) if( Files[i].cnum == cnum && Files[i].open) { - close_file(i); + close_file(i, 0); } } @@ -3804,6 +3222,10 @@ void close_cnum(int cnum, uint16 vuid) { DirCacheFlush(SNUM(cnum)); + close_open_files(cnum); + dptr_closecnum(cnum); + + /* after this we are running as root, so be careful! */ unbecome_user(); if (!OPEN_CNUM(cnum)) @@ -3824,9 +3246,6 @@ void close_cnum(int cnum, uint16 vuid) if (lp_status(SNUM(cnum))) yield_connection(cnum,"STATUS.",MAXSTATUS); - close_open_files(cnum); - dptr_closecnum(cnum); - /* execute any "postexec = " line */ if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid)) { @@ -4556,11 +3975,14 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) return(outsize); } + /**************************************************************************** process commands from the client ****************************************************************************/ static void process(void) { + static int trans_num = 0; + int nread; extern int Client; InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -4583,36 +4005,32 @@ static void process(void) #endif while (True) - { - int deadtime = lp_deadtime()*60; - int counter; - int last_keepalive=0; - int service_load_counter = 0; -#ifdef USE_OPLOCKS - BOOL got_smb = False; -#endif /* USE_OPLOCKS */ - - if (deadtime <= 0) - deadtime = DEFAULT_SMBD_TIMEOUT; - - if (lp_readprediction()) - do_read_prediction(); - - errno = 0; - - for (counter=SMBD_SELECT_LOOP; -#ifdef USE_OPLOCKS - !receive_message_or_smb(Client,oplock_sock, - InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb); -#else /* USE_OPLOCKS */ - !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); -#endif /* USE_OPLOCKS */ - counter += SMBD_SELECT_LOOP) { - int i; - time_t t; - BOOL allidle = True; - extern int keepalive; + int32 len; + int msg_type; + int msg_flags; + int type; + int deadtime = lp_deadtime()*60; + int counter; + int last_keepalive=0; + int service_load_counter = 0; + + if (deadtime <= 0) + deadtime = DEFAULT_SMBD_TIMEOUT; + + if (lp_readprediction()) + do_read_prediction(); + + errno = 0; + + for (counter=SMBD_SELECT_LOOP; + !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000); + counter += SMBD_SELECT_LOOP) + { + int i; + time_t t; + BOOL allidle = True; + extern int keepalive; if (counter > 365 * 3600) /* big number of seconds. */ { @@ -4620,84 +4038,126 @@ static void process(void) service_load_counter = 0; } - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return; - } + if (smb_read_error == READ_EOF) { + DEBUG(3,("end of file from client\n")); + return; + } - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return; - } + if (smb_read_error == READ_ERROR) { + DEBUG(3,("receive_smb error (%s) exiting\n", + strerror(errno))); + return; + } - t = time(NULL); + t = time(NULL); - /* become root again if waiting */ - unbecome_user(); + /* become root again if waiting */ + unbecome_user(); - /* check for smb.conf reload */ - if (counter >= service_load_counter + SMBD_RELOAD_CHECK) + /* check for smb.conf reload */ + if (counter >= service_load_counter + SMBD_RELOAD_CHECK) { service_load_counter = counter; /* reload services, if files have changed. */ - reload_services(True); + reload_services(True); } - /* automatic timeout if all connections are closed */ - if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) - { - DEBUG(2,("%s Closing idle connection\n",timestring())); - return; - } + /* automatic timeout if all connections are closed */ + if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) { + DEBUG(2,("%s Closing idle connection\n",timestring())); + return; + } - if (keepalive && (counter-last_keepalive)>keepalive) - { - extern int password_client; - if (!send_keepalive(Client)) - { - DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); - return; - } - /* also send a keepalive to the password server if its still - connected */ - if (password_client != -1) - send_keepalive(password_client); - last_keepalive = counter; + if (keepalive && (counter-last_keepalive)>keepalive) { + extern int password_client; + if (!send_keepalive(Client)) { + DEBUG(2,("%s Keepalive failed - exiting\n",timestring())); + return; + } + /* also send a keepalive to the password server if its still + connected */ + if (password_client != -1) + send_keepalive(password_client); + last_keepalive = counter; + } + + /* check for connection timeouts */ + for (i=0;i<MAX_CONNECTIONS;i++) + if (Connections[i].open) + { + /* close dirptrs on connections that are idle */ + if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT) + dptr_idlecnum(i); + + if (Connections[i].num_files_open > 0 || + (t-Connections[i].lastused)<deadtime) + allidle = False; + } + + if (allidle && num_connections_open>0) { + DEBUG(2,("%s Closing idle connection 2\n",timestring())); + return; + } + } + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (!check_access(-1)) { + /* send a negative session response "not listining + on calling name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG(1,("%s Connection denied from %s\n", + timestring(),client_addr())); + send_smb(Client,(char *)buf); + exit_server("connection denied"); + } } - /* check for connection timeouts */ - for (i=0;i<MAX_CONNECTIONS;i++) - if (Connections[i].open) - { - /* close dirptrs on connections that are idle */ - if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT) - dptr_idlecnum(i); - if (Connections[i].num_files_open > 0 || - (t-Connections[i].lastused)<deadtime) - allidle = False; - } + msg_type = CVAL(InBuffer,0); + msg_flags = CVAL(InBuffer,1); + type = CVAL(InBuffer,smb_com); - if (allidle && num_connections_open>0) - { - DEBUG(2,("%s Closing idle connection 2\n",timestring())); + len = smb_len(InBuffer); + + DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len)); + + nread = len + 4; + + DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread)); + +#ifdef WITH_VTP + if(trans_num == 1 && VT_Check(InBuffer)) { + VT_Process(); return; } - } +#endif -#ifdef USE_OPLOCKS - if(got_smb) -#endif /* USE_OPLOCKS */ - process_smb(InBuffer, OutBuffer); -#ifdef USE_OPLOCKS - else - process_local_message(oplock_sock, InBuffer, BUFFER_SIZE); -#endif /* USE_OPLOCKS */ - } + + if (msg_type == 0) + show_msg(InBuffer); + + nread = construct_reply(InBuffer,OutBuffer,nread,max_send); + + if(nread > 0) { + if (CVAL(OutBuffer,0) == 0) + show_msg(OutBuffer); + + if (nread != smb_len(OutBuffer) + 4) + { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, + smb_len(OutBuffer))); + } + else + send_smb(Client,OutBuffer); + } + trans_num++; + } } @@ -4976,12 +4436,6 @@ static void usage(char *pname) DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir())); } -#ifdef USE_OPLOCKS - /* Setup the oplock IPC socket. */ - if(!open_oplock_ipc()) - exit(1); -#endif /* USE_OPLOCKS */ - process(); close_sockets(); diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index 7f46604cce9..f7351b99e5a 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -166,7 +166,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, char *params = *pparams; int16 open_mode = SVAL(params, 2); int16 open_attr = SVAL(params,6); - BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); + BOOL oplock_request = BITSETW(params,1); #if 0 BOOL return_additional_info = BITSETW(params,0); int16 open_sattr = SVAL(params, 4); @@ -213,7 +213,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode, - oplock_request, &rmode,&smb_action); + &rmode,&smb_action); if (!Files[fnum].open) { @@ -226,7 +226,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, } if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -235,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { - close_file(fnum); + close_file(fnum, 0); return(ERROR(ERRDOS,ERRnoaccess)); } @@ -252,7 +252,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum, SSVAL(params,12,rmode); if (oplock_request && lp_fake_oplocks(SNUM(cnum))) { - smb_action |= EXTENDED_OPLOCK_GRANTED; + smb_action |= (1<<15); } SSVAL(params,18,smb_action); @@ -319,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l reskey = TellDir(Connections[cnum].dirptr); - DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", + DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n", Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr))); if (!dname) @@ -607,15 +607,6 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - - /* Ugly - NT specific hack - but needed (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } - return(ERROR(ERRDOS,ERRbadpath)); } @@ -650,14 +641,6 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum unix_ERR_class = ERRDOS; unix_ERR_code = ERRbadpath; } - - /* Ugly - NT specific hack - but needed (JRA) */ - if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && - (get_remote_arch() == RA_WINNT)) - { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbaddirectory; - } return (UNIXERROR(ERRDOS,ERRbadpath)); } return(ERROR(ERRDOS,ERRbadpath)); @@ -1364,14 +1347,6 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length, tvs.modtime=MAX(interpret_long_date(pdata+16), interpret_long_date(pdata+24)); -#if 0 /* Needs more testing... */ - /* Test from Luke to prevent Win95 from - setting incorrect values here. - */ - if (tvs.actime < tvs.modtime) - return(ERROR(ERRDOS,ERRnoaccess)); -#endif /* Needs more testing... */ - /* attributes */ mode = IVAL(pdata,32); break; diff --git a/source/smbd/uid.c b/source/smbd/uid.c index cdc4e474c61..fe2cb5a652d 100644 --- a/source/smbd/uid.c +++ b/source/smbd/uid.c @@ -258,6 +258,8 @@ BOOL become_user(int cnum, uint16 vuid) if (current_user.ngroups > 0) if (setgroups(current_user.ngroups,current_user.groups)<0) DEBUG(0,("setgroups call failed!\n")); + } else { + current_user.ngroups = 0; } #endif @@ -318,7 +320,8 @@ BOOL unbecome_user(void ) current_user.uid = initial_uid; current_user.gid = initial_gid; - + current_user.ngroups = 0; + if (ChDir(OriginalDir) != 0) DEBUG(0,("%s chdir(%s) failed in unbecome_user\n", timestring(),OriginalDir)); @@ -476,3 +479,82 @@ int smbrun(char *cmd,char *outfile,BOOL shared) #endif return 1; } + + + +static struct current_user current_user_saved; +static int become_root_depth; +static pstring become_root_dir; + +/**************************************************************************** +This is used when we need to do a privilaged operation (such as mucking +with share mode files) and temporarily need root access to do it. This +call should always be paired with an unbecome_root() call immediately +after the operation + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void become_root(int save_dir) +{ + if (become_root_depth) { + DEBUG(0,("ERROR: become root depth is non zero\n")); + } + if (save_dir) + GetWd(become_root_dir); + + current_user_saved = current_user; + become_root_depth = 1; + + become_gid(0); + become_uid(0); +} + +/**************************************************************************** +When the privilaged operation is over call this + +Set save_dir if you also need to save/restore the CWD +****************************************************************************/ +void unbecome_root(int restore_dir) +{ + if (become_root_depth != 1) { + DEBUG(0,("ERROR: unbecome root depth is %d\n", + become_root_depth)); + } + + /* we might have done a become_user() while running as root, + if we have then become root again in order to become + non root! */ + if (current_user.uid != 0) { + become_uid(0); + } + + /* restore our gid first */ + if (!become_gid(current_user_saved.gid)) { + DEBUG(0,("ERROR: Failed to restore gid\n")); + exit_server("Failed to restore gid"); + } + +#ifndef NO_SETGROUPS + if (current_user_saved.ngroups > 0) { + if (setgroups(current_user_saved.ngroups, + current_user_saved.groups)<0) + DEBUG(0,("ERROR: setgroups call failed!\n")); + } +#endif + + /* now restore our uid */ + if (!become_uid(current_user_saved.uid)) { + DEBUG(0,("ERROR: Failed to restore uid\n")); + exit_server("Failed to restore uid"); + } + + if (restore_dir) + ChDir(become_root_dir); + + current_user = current_user_saved; + + become_root_depth = 0; +} + + + |