summaryrefslogtreecommitdiffstats
path: root/source/smbd/reply.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/reply.c')
-rw-r--r--source/smbd/reply.c2208
1 files changed, 1408 insertions, 800 deletions
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index a881e135c08..50b31d7d681 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -1,9 +1,9 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
Main SMB reply routines
Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) Andrew Bartlett 2001
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -23,6 +23,7 @@
makes to handle specific protocols
*/
+
#include "includes.h"
/* look in server.c for some explanation of these variables */
@@ -33,14 +34,30 @@ extern char magic_char;
extern BOOL case_sensitive;
extern BOOL case_preserve;
extern BOOL short_case_preserve;
+extern userdom_struct current_user_info;
extern pstring global_myname;
+extern fstring global_myworkgroup;
extern int global_oplock_break;
+uint32 global_client_caps = 0;
unsigned int smb_echo_count = 0;
-extern BOOL global_encrypted_passwords_negotiated;
+/****************************************************************************
+report a possible attack via the password buffer overflow bug
+****************************************************************************/
+
+static void overflow_attack(int len)
+{
+ if( DEBUGLVL( 0 ) ) {
+ dbgtext( "ERROR: Invalid password length %d.\n", len );
+ dbgtext( "Your machine may be under attack by someone " );
+ dbgtext( "attempting to exploit an old bug.\n" );
+ dbgtext( "Attack was from IP = %s.\n", client_addr() );
+ }
+}
+
/****************************************************************************
- Reply to an special message.
+ reply to an special message
****************************************************************************/
int reply_special(char *inbuf,char *outbuf)
@@ -49,12 +66,11 @@ int reply_special(char *inbuf,char *outbuf)
int msg_type = CVAL(inbuf,0);
int msg_flags = CVAL(inbuf,1);
pstring name1,name2;
-
+ extern fstring remote_machine;
+ extern fstring local_machine;
int len;
char name_type = 0;
- static BOOL already_got_session = False;
-
*name1 = *name2 = 0;
memset(outbuf,'\0',smb_size);
@@ -63,11 +79,6 @@ int reply_special(char *inbuf,char *outbuf)
switch (msg_type) {
case 0x81: /* session request */
-
- if (already_got_session) {
- exit_server("multiple session request not permitted");
- }
-
SCVAL(outbuf,0,0x82);
SCVAL(outbuf,3,0);
if (name_len(inbuf+4) > 50 ||
@@ -80,45 +91,49 @@ int reply_special(char *inbuf,char *outbuf)
DEBUG(2,("netbios connect: name1=%s name2=%s\n",
name1,name2));
- name1[15] = 0;
+ fstrcpy(remote_machine,name2);
+ remote_machine[15] = 0;
+ trim_string(remote_machine," "," ");
+ strlower(remote_machine);
+ alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
- len = strlen(name2);
+ fstrcpy(local_machine,name1);
+ len = strlen(local_machine);
if (len == 16) {
- name_type = name2[15];
- name2[15] = 0;
+ name_type = local_machine[15];
+ local_machine[15] = 0;
}
-
- set_local_machine_name(name1);
- set_remote_machine_name(name2);
+ trim_string(local_machine," "," ");
+ strlower(local_machine);
+ alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
DEBUG(2,("netbios connect: local=%s remote=%s\n",
- get_local_machine_name(), get_remote_machine_name() ));
+ local_machine, remote_machine ));
if (name_type == 'R') {
/* We are being asked for a pathworks session ---
no thanks! */
- SCVAL(outbuf, 0,0x83);
+ SCVAL(outbuf, 0, 0x83);
break;
}
- /* only add the client's machine name to the list
- of possibly valid usernames if we are operating
- in share mode security */
+ /* add it as a possible user name if we
+ are in share mode security */
if (lp_security() == SEC_SHARE) {
- add_session_user(get_remote_machine_name());
+ add_session_user(remote_machine);
}
reload_services(True);
reopen_logs();
- claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
+ if (lp_status(-1))
+ claim_connection(NULL,"",0,True);
- already_got_session = True;
break;
case 0x89: /* session keepalive request
(some old clients produce this?) */
- SCVAL(outbuf,0,SMBkeepalive);
+ SCVAL(outbuf,0,0x85);
SCVAL(outbuf,3,0);
break;
@@ -128,7 +143,7 @@ int reply_special(char *inbuf,char *outbuf)
DEBUG(0,("Unexpected session response\n"));
break;
- case SMBkeepalive: /* session keepalive */
+ case 0x85: /* session keepalive */
default:
return(0);
}
@@ -139,6 +154,54 @@ int reply_special(char *inbuf,char *outbuf)
return(outsize);
}
+
+/*******************************************************************
+work out what error to give to a failed connection
+********************************************************************/
+
+static int connection_error(char *outbuf, int ecode)
+{
+ if (ecode == ERRnoipc || ecode == ERRnosuchshare)
+ return(ERROR_DOS(ERRDOS,ecode));
+
+ return(ERROR_DOS(ERRSRV,ecode));
+}
+
+/****************************************************************************
+ parse a share descriptor string
+****************************************************************************/
+
+static void parse_connect(char *p,char *service,char *user,
+ char *password,int *pwlen,char *dev)
+{
+ char *p2;
+
+ DEBUG(4,("parsing connect string %s\n",p));
+
+ p2 = strrchr(p,'\\');
+ if (p2 == NULL)
+ fstrcpy(service,p);
+ else
+ fstrcpy(service,p2+1);
+
+ p += strlen(p) + 2;
+
+ fstrcpy(password,p);
+ *pwlen = strlen(password);
+
+ p += strlen(p) + 2;
+
+ fstrcpy(dev,p);
+
+ *user = 0;
+ p = strchr(service,'%');
+ if (p != NULL)
+ {
+ *p = 0;
+ fstrcpy(user,p+1);
+ }
+}
+
/****************************************************************************
Reply to a tcon.
****************************************************************************/
@@ -146,43 +209,54 @@ int reply_special(char *inbuf,char *outbuf)
int reply_tcon(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- const char *service;
- pstring service_buf;
+ BOOL doencrypt = SMBENCRYPT();
+ pstring service;
+ pstring user;
pstring password;
pstring dev;
int outsize = 0;
uint16 vuid = SVAL(inbuf,smb_uid);
int pwlen=0;
- NTSTATUS nt_status;
- char *p;
- DATA_BLOB password_blob;
-
+ int ecode = -1;
START_PROFILE(SMBtcon);
- *service_buf = *password = *dev = 0;
+ *service = *user = *password = *dev = 0;
- p = smb_buf(inbuf)+1;
- p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
- pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
- p += pwlen;
- p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
+ parse_connect(smb_buf(inbuf)+1,service,user,password,&pwlen,dev);
- p = strrchr_m(service_buf,'\\');
- if (p) {
- service = p+1;
- } else {
- service = service_buf;
+ /*
+ * If the vuid is valid, we should be using that....
+ */
+
+ if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
+ pstrcpy(user,validated_username(vuid));
}
- password_blob = data_blob(password, pwlen+1);
+ /*
+ * Ensure the user and password names are in UNIX codepage format.
+ */
+
+ pstrcpy(user,dos_to_unix_static(user));
+ if (!doencrypt)
+ pstrcpy(password,dos_to_unix_static(password));
- conn = make_connection(service,password_blob,dev,vuid,&nt_status);
+ /*
+ * Pass the user through the NT -> unix user mapping
+ * function.
+ */
+
+ (void)map_username(user);
- data_blob_clear_free(&password_blob);
+ /*
+ * Do any UNIX username case mangling.
+ */
+ (void)Get_Pwnam( user, True);
+
+ conn = make_connection(service,user,password,pwlen,dev,vuid,&ecode);
if (!conn) {
END_PROFILE(SMBtcon);
- return ERROR_NT(nt_status);
+ return(connection_error(outbuf,ecode));
}
outsize = set_message(outbuf,2,0,True);
@@ -190,8 +264,8 @@ int reply_tcon(connection_struct *conn,
SSVAL(outbuf,smb_vwv1,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
- DEBUG(3,("tcon service=%s cnum=%d\n",
- service, conn->cnum));
+ DEBUG(3,("tcon service=%s user=%s cnum=%d\n",
+ service, user, conn->cnum));
END_PROFILE(SMBtcon);
return(outsize);
@@ -204,17 +278,18 @@ int reply_tcon(connection_struct *conn,
int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
fstring service;
- DATA_BLOB password;
+ pstring user;
+ pstring password;
pstring devicename;
- NTSTATUS nt_status;
+ BOOL doencrypt = SMBENCRYPT();
+ int ecode = -1;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
- pstring path;
- char *p, *q;
- extern BOOL global_encrypted_passwords_negotiated;
- START_PROFILE(SMBtconX);
-
- *service = *devicename = 0;
+ char *path;
+ char *p;
+ START_PROFILE(SMBtconX);
+
+ *service = *user = *password = *devicename = 0;
/* we might have to close an old one */
if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
@@ -222,67 +297,91 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
if (passlen > MAX_PASS_LEN) {
- return ERROR_DOS(ERRDOS,ERRbuftoosmall);
+ overflow_attack(passlen);
+ return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
}
- if (global_encrypted_passwords_negotiated) {
- password = data_blob(smb_buf(inbuf),passlen);
- } else {
- password = data_blob(smb_buf(inbuf),passlen+1);
- /* Ensure correct termination */
- password.data[passlen]=0;
+ memcpy(password,smb_buf(inbuf),passlen);
+ password[passlen]=0;
+ path = smb_buf(inbuf) + passlen;
+
+ if (passlen != 24) {
+ if (strequal(password," "))
+ *password = 0;
+ passlen = strlen(password);
}
- p = smb_buf(inbuf) + passlen;
- p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
-
/*
* the service name can be either: \\server\share
* or share directly like on the DELL PowerVault 705
*/
if (*path=='\\') {
- q = strchr_m(path+2,'\\');
- if (!q) {
+ p = strchr(path+2,'\\');
+ if (!p) {
END_PROFILE(SMBtconX);
return(ERROR_DOS(ERRDOS,ERRnosuchshare));
}
- fstrcpy(service,q+1);
+ fstrcpy(service,p+1);
}
else
fstrcpy(service,path);
- p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
-
+ p = strchr(service,'%');
+ if (p) {
+ *p++ = 0;
+ fstrcpy(user,p);
+ }
+ StrnCpy(devicename,path + strlen(path) + 1,6);
DEBUG(4,("Got device type %s\n",devicename));
- conn = make_connection(service,password,devicename,vuid,&nt_status);
-
- data_blob_clear_free(&password);
+ /*
+ * If the vuid is valid, we should be using that....
+ */
+
+ if (*user == '\0' && (lp_security() != SEC_SHARE) && validated_username(vuid)) {
+ pstrcpy(user,validated_username(vuid));
+ }
+
+ /*
+ * Ensure the user and password names are in UNIX codepage format.
+ */
+ pstrcpy(user,dos_to_unix_static(user));
+ if (!doencrypt)
+ pstrcpy(password,dos_to_unix_static(password));
+
+ /*
+ * Pass the user through the NT -> unix user mapping
+ * function.
+ */
+
+ (void)map_username(user);
+
+ /*
+ * Do any UNIX username case mangling.
+ */
+ (void)Get_Pwnam(user, True);
+
+ conn = make_connection(service,user,password,passlen,devicename,vuid,&ecode);
+
if (!conn) {
END_PROFILE(SMBtconX);
- return ERROR_NT(nt_status);
+ return(connection_error(outbuf,ecode));
}
if (Protocol < PROTOCOL_NT1) {
- set_message(outbuf,2,0,True);
- p = smb_buf(outbuf);
- p += srvstr_push(outbuf, p, devicename, -1,
- STR_TERMINATE|STR_ASCII);
- set_message_end(outbuf,p);
+ set_message(outbuf,2,strlen(devicename)+1,True);
+ pstrcpy(smb_buf(outbuf),devicename);
} else {
- /* NT sets the fstype of IPC$ to the null string */
- char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
+ char *fsname = lp_fstype(SNUM(conn));
- set_message(outbuf,3,0,True);
+ set_message(outbuf,3,3,True);
p = smb_buf(outbuf);
- p += srvstr_push(outbuf, p, devicename, -1,
- STR_TERMINATE|STR_ASCII);
- p += srvstr_push(outbuf, p, fsname, -1,
- STR_TERMINATE);
+ pstrcpy(p,devicename); p = skip_string(p,1); /* device name */
+ pstrcpy(p,fsname); p = skip_string(p,1); /* filesystem type e.g NTFS */
- set_message_end(outbuf,p);
+ set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
@@ -293,8 +392,8 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
- DEBUG(3,("tconX service=%s \n",
- service));
+ DEBUG(3,("tconX service=%s user=%s\n",
+ service, user));
/* set the incoming and outgoing tid to the just created one */
SSVAL(inbuf,smb_tid,conn->cnum);
@@ -304,10 +403,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return chain_reply(inbuf,outbuf,length,bufsize);
}
+
/****************************************************************************
- Reply to an unknown type.
+ reply to an unknown type
****************************************************************************/
-
int reply_unknown(char *inbuf,char *outbuf)
{
int type;
@@ -320,9 +419,8 @@ int reply_unknown(char *inbuf,char *outbuf)
}
/****************************************************************************
- Reply to an ioctl.
+ reply to an ioctl
****************************************************************************/
-
int reply_ioctl(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -336,7 +434,8 @@ int reply_ioctl(connection_struct *conn,
DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
- switch (ioctl_code) {
+ switch (ioctl_code)
+ {
case IOCTL_QUERY_JOB_INFO:
replysize = 32;
break;
@@ -351,15 +450,13 @@ int reply_ioctl(connection_struct *conn,
SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
p = smb_buf(outbuf) + 1; /* Allow for alignment */
- switch (ioctl_code) {
- case IOCTL_QUERY_JOB_INFO:
- {
- uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
- SSVAL(p,0,rap_jobid); /* Job number */
- srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
- srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
- break;
- }
+ switch (ioctl_code)
+ {
+ case IOCTL_QUERY_JOB_INFO:
+ SSVAL(p,0,fsp->print_jobid); /* Job number */
+ StrnCpy(p+2, global_myname, 15); /* Our NetBIOS name */
+ StrnCpy(p+18, lp_servicename(SNUM(conn)), 13); /* Service name */
+ break;
}
END_PROFILE(SMBioctl);
@@ -367,56 +464,707 @@ int reply_ioctl(connection_struct *conn,
}
/****************************************************************************
- Reply to a chkpth.
+ Always return an error: it's just a matter of which one...
+ ****************************************************************************/
+
+static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
+ char *smb_passwd, int smb_passlen,
+ char *smb_nt_passwd, int smb_nt_passlen)
+{
+ SAM_ACCOUNT *sam_trust_acct = NULL; /* check if trust account exists */
+ uint16 acct_ctrl;
+
+ if (lp_security() == SEC_USER) {
+ pdb_init_sam(&sam_trust_acct);
+ pdb_getsampwnam(sam_trust_acct, user);
+ } else {
+ DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
+ return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
+ }
+
+ if (sam_trust_acct == NULL) {
+ /* lkclXXXX: workstation entry doesn't exist */
+ DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
+ return(ERROR_BOTH(NT_STATUS_NO_SUCH_USER,ERRDOS,1317));
+ } else {
+ if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
+ DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
+ }
+
+ if (!smb_password_ok(sam_trust_acct, NULL, (unsigned char *)smb_passwd, (unsigned char *)smb_nt_passwd)) {
+ DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw));
+ }
+
+ acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
+ if (acct_ctrl & ACB_DOMTRUST) {
+ DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT,ERRDOS,1807));
+ }
+
+ if (acct_ctrl & ACB_SVRTRUST) {
+ DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT,ERRDOS,1809));
+ }
+
+ if (acct_ctrl & ACB_WSTRUST) {
+ DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT,ERRDOS,1808));
+ }
+ }
+
+ /* don't know what to do: indicate logon failure */
+ pdb_free_sam(sam_trust_acct);
+ return(ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRDOS,1326));
+}
+
+/****************************************************************************
+ Create a UNIX user on demand.
****************************************************************************/
-int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+int smb_create_user(char *unix_user, char *homedir)
{
- int outsize = 0;
- int mode;
- pstring name;
- BOOL ok = False;
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
- START_PROFILE(SMBchkpth);
+ pstring add_script;
+ int ret;
- srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+ pstrcpy(add_script, lp_adduser_script());
+ if (! *add_script)
+ return -1;
+ all_string_sub(add_script, "%u", unix_user, sizeof(pstring));
+ if (homedir)
+ all_string_sub(add_script, "%H", homedir, sizeof(pstring));
+ ret = smbrun(add_script,NULL);
+ DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
+ return ret;
+}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+/****************************************************************************
+ Delete a UNIX user on demand.
+****************************************************************************/
- unix_convert(name,conn,0,&bad_path,&sbuf);
+static int smb_delete_user(char *unix_user)
+{
+ pstring del_script;
+ int ret;
- mode = SVAL(inbuf,smb_vwv0);
+ /*
+ * Sanity check -- do not delete 'root' account
+ */
- if (check_name(name,conn)) {
- if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
- ok = S_ISDIR(sbuf.st_mode);
+ if (StrCaseCmp("root", unix_user) == 0) {
+ DEBUG(0,("smb_delete_user: Will not delete the [%s] user account!\n", unix_user));
+ return -1;
}
- if (!ok) {
- /* We special case this - as when a Windows machine
- is parsing a path is steps through the components
- one at a time - if a component fails it expects
- ERRbadpath, not ERRbadfile.
- */
- if(errno == ENOENT)
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ pstrcpy(del_script, lp_deluser_script());
+ if (! *del_script)
+ return -1;
+ all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
+ ret = smbrun(del_script,NULL);
+ DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+ return ret;
+}
+
+/****************************************************************************
+ Check user is in correct domain if required
+****************************************************************************/
- return(UNIXERROR(ERRDOS,ERRbadpath));
+static BOOL check_domain_match(char *user, char *domain)
+{
+ /*
+ * If we aren't serving to trusted domains, we must make sure that
+ * the validation request comes from an account in the same domain
+ * as the Samba server
+ */
+
+ if (!lp_allow_trusted_domains() &&
+ !strequal(lp_workgroup(), domain) ) {
+ DEBUG(1, ("check_domain_match: Attempt to connect as user %s from domain %s denied.\n", user, domain));
+ return False;
+ } else {
+ return True;
+ }
+}
+
+/****************************************************************************
+ Check for a valid username and password in security=server mode.
+****************************************************************************/
+
+static BOOL check_server_security(char *orig_user, char *domain, char *unix_user,
+ char *smb_apasswd, int smb_apasslen,
+ char *smb_ntpasswd, int smb_ntpasslen)
+{
+ BOOL ret = False;
+
+ if(lp_security() != SEC_SERVER)
+ return False;
+
+ if (!check_domain_match(orig_user, domain))
+ return False;
+
+ ret = server_validate(orig_user, domain,
+ smb_apasswd, smb_apasslen,
+ smb_ntpasswd, smb_ntpasslen);
+
+ if(ret) {
+ /*
+ * User validated ok against Domain controller.
+ * If the admin wants us to try and create a UNIX
+ * user on the fly, do so.
+ * Note that we can never delete users when in server
+ * level security as we never know if it was a failure
+ * due to a bad password, or the user really doesn't exist.
+ */
+
+ if(lp_adduser_script() && !smb_getpwnam(unix_user,True))
+ smb_create_user(unix_user, NULL);
}
- outsize = set_message(outbuf,0,0,True);
+ return ret;
+}
- DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+/****************************************************************************
+ Check for a valid username and password in security=domain mode.
+****************************************************************************/
- END_PROFILE(SMBchkpth);
- return(outsize);
+static BOOL check_domain_security(char *orig_user, char *domain, char *unix_user,
+ char *smb_apasswd, int smb_apasslen,
+ char *smb_ntpasswd, int smb_ntpasslen, NT_USER_TOKEN **pptoken)
+{
+ BOOL ret = False;
+ BOOL user_exists = True;
+ struct passwd *pwd = NULL;
+
+ if(lp_security() != SEC_DOMAIN)
+ return False;
+
+ if (!check_domain_match(orig_user, domain))
+ return False;
+
+ ret = domain_client_validate(orig_user, domain,
+ smb_apasswd, smb_apasslen,
+ smb_ntpasswd, smb_ntpasslen,
+ &user_exists, pptoken);
+
+ if(ret) {
+ /*
+ * User validated ok against Domain controller.
+ * If the admin wants us to try and create a UNIX
+ * user on the fly, do so.
+ */
+ if(user_exists && lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True))) {
+ smb_create_user(unix_user, NULL);
+ }
+
+ if(lp_adduser_script() && pwd) {
+ SMB_STRUCT_STAT st;
+
+ /*
+ * Also call smb_create_user if the users home directory
+ * doesn't exist. Used with winbindd to allow the script to
+ * create the home directory for a user mapped with winbindd.
+ */
+
+ if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
+ smb_create_user(unix_user, pwd->pw_dir);
+ }
+
+ } else {
+ /*
+ * User failed to validate ok against Domain controller.
+ * If the failure was "user doesn't exist" and admin
+ * wants us to try and delete that UNIX user on the fly,
+ * do so.
+ */
+ if(!user_exists && lp_deluser_script() && smb_getpwnam(unix_user,True)) {
+ smb_delete_user(unix_user);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ Reply to a session setup command.
+****************************************************************************/
+
+int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+{
+ int sess_vuid;
+ gid_t gid;
+ uid_t uid;
+ int smb_bufsize;
+ int smb_apasslen = 0;
+ pstring smb_apasswd;
+ int smb_ntpasslen = 0;
+ pstring smb_ntpasswd;
+ BOOL valid_nt_password = False;
+ BOOL valid_lm_password = False;
+ pstring user;
+ pstring orig_user;
+ BOOL guest=False;
+ static BOOL done_sesssetup = False;
+ BOOL doencrypt = SMBENCRYPT();
+ fstring domain;
+ NT_USER_TOKEN *ptok = NULL;
+
+ START_PROFILE(SMBsesssetupX);
+
+ *smb_apasswd = 0;
+ *smb_ntpasswd = 0;
+ *domain = 0;
+
+ smb_bufsize = SVAL(inbuf,smb_vwv2);
+
+ if (Protocol < PROTOCOL_NT1) {
+ smb_apasslen = SVAL(inbuf,smb_vwv7);
+ if (smb_apasslen > MAX_PASS_LEN) {
+ overflow_attack(smb_apasslen);
+ return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
+ }
+
+ memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
+ smb_apasswd[smb_apasslen] = 0;
+ pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
+ /*
+ * Incoming user is in DOS codepage format. Convert
+ * to UNIX.
+ */
+ pstrcpy(user,dos_to_unix_static(user));
+
+ if (!doencrypt && (lp_security() != SEC_SERVER)) {
+ smb_apasslen = strlen(smb_apasswd);
+ }
+ } else {
+ uint16 passlen1 = SVAL(inbuf,smb_vwv7);
+ uint16 passlen2 = SVAL(inbuf,smb_vwv8);
+ enum remote_arch_types ra_type = get_remote_arch();
+ char *p = smb_buf(inbuf);
+
+ if(global_client_caps == 0)
+ global_client_caps = IVAL(inbuf,smb_vwv11);
+
+ /* client_caps is used as final determination if client is NT or Win95.
+ This is needed to return the correct error codes in some
+ circumstances.
+ */
+
+ if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
+ if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
+ set_remote_arch( RA_WIN95);
+ }
+ }
+
+ if (passlen1 != 24 && passlen2 != 24)
+ doencrypt = False;
+
+ if (passlen1 > MAX_PASS_LEN) {
+ overflow_attack(passlen1);
+ return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
+ }
+
+ passlen1 = MIN(passlen1, MAX_PASS_LEN);
+ passlen2 = MIN(passlen2, MAX_PASS_LEN);
+
+ if(!doencrypt) {
+ /* both Win95 and WinNT stuff up the password lengths for
+ non-encrypting systems. Uggh.
+
+ if passlen1==24 its a win95 system, and its setting the
+ password length incorrectly. Luckily it still works with the
+ default code because Win95 will null terminate the password
+ anyway
+
+ if passlen1>0 and passlen2>0 then maybe its a NT box and its
+ setting passlen2 to some random value which really stuffs
+ things up. we need to fix that one. */
+
+ if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
+ passlen2 = 0;
+ }
+
+ if (lp_restrict_anonymous()) {
+ /* there seems to be no reason behind the differences in MS clients formatting
+ * various info like the domain, NativeOS, and NativeLanMan fields. Win95
+ * in particular seems to have an extra null byte between the username and the
+ * domain, or the password length calculation is wrong, which throws off the
+ * string extraction routines below. This makes the value of domain be the
+ * empty string, which fails the restrict anonymous check further down.
+ * This compensates for that, and allows browsing to work in mixed NT and
+ * win95 environments even when restrict anonymous is true. AAB
+ */
+ dump_data(100, p, 0x70);
+ DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
+ if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
+ DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
+ DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
+ DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
+ passlen1 = 1;
+ }
+ }
+
+ if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
+ /* Save the lanman2 password and the NT md4 password. */
+ smb_apasslen = passlen1;
+ memcpy(smb_apasswd,p,smb_apasslen);
+ smb_apasswd[smb_apasslen] = 0;
+ smb_ntpasslen = passlen2;
+ memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
+ smb_ntpasswd[smb_ntpasslen] = 0;
+
+ /*
+ * Ensure the plaintext passwords are in UNIX format.
+ */
+ if(!doencrypt) {
+ pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
+ pstrcpy(smb_ntpasswd,dos_to_unix_static(smb_ntpasswd));
+ }
+
+ } else {
+ /* we use the first password that they gave */
+ smb_apasslen = passlen1;
+ StrnCpy(smb_apasswd,p,smb_apasslen);
+ /*
+ * Ensure the plaintext password is in UNIX format.
+ */
+ pstrcpy(smb_apasswd,dos_to_unix_static(smb_apasswd));
+
+ /* trim the password */
+ smb_apasslen = strlen(smb_apasswd);
+
+ /* wfwg sometimes uses a space instead of a null */
+ if (strequal(smb_apasswd," ")) {
+ smb_apasslen = 0;
+ *smb_apasswd = 0;
+ }
+ }
+
+ p += passlen1 + passlen2;
+ fstrcpy(user,p);
+ p = skip_string(p,1);
+ /*
+ * Incoming user and domain are in DOS codepage format. Convert
+ * to UNIX.
+ */
+ pstrcpy(user,dos_to_unix_static(user));
+ fstrcpy(domain, dos_to_unix_static(p));
+ DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
+ domain,skip_string(p,1),skip_string(p,2)));
+ }
+
+ /* don't allow strange characters in usernames or domains */
+ alpha_strcpy(user, user, ". _-$", sizeof(user));
+ alpha_strcpy(domain, domain, ". _-", sizeof(domain));
+ if (strstr(user, "..") || strstr(domain,"..")) {
+ return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
+ }
+
+ DEBUG(3,("sesssetupX:name=[%s]\n",user));
+
+ /* If name ends in $ then I think it's asking about whether a */
+ /* computer with that name (minus the $) has access. For now */
+ /* say yes to everything ending in $. */
+
+ if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
+ END_PROFILE(SMBsesssetupX);
+ return session_trust_account(conn, inbuf, outbuf, user,
+ smb_apasswd, smb_apasslen,
+ smb_ntpasswd, smb_ntpasslen);
+ }
+
+ if (done_sesssetup && lp_restrict_anonymous()) {
+ /* tests show that even if browsing is done over already validated connections
+ * without a username and password the domain is still provided, which it
+ * wouldn't be if it was a purely anonymous connection. So, in order to
+ * restrict anonymous, we only deny connections that have no session
+ * information. If a domain has been provided, then it's not a purely
+ * anonymous connection. AAB
+ */
+ if (!*user && !*smb_apasswd && !*domain) {
+ DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
+ END_PROFILE(SMBsesssetupX);
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ }
+ }
+
+ /* If no username is sent use the guest account */
+ if (!*user) {
+ pstrcpy(user,lp_guestaccount(-1));
+ guest = True;
+ }
+
+ pstrcpy(current_user_info.smb_name,user);
+
+ reload_services(True);
+
+ /*
+ * Save the username before mapping. We will use
+ * the original username sent to us for security=server
+ * and security=domain checking.
+ */
+
+ pstrcpy( orig_user, user);
+
+ /*
+ * Always try the "DOMAIN\user" lookup first, as this is the most
+ * specific case. If this fails then try the simple "user" lookup.
+ */
+
+ {
+ pstring dom_user;
+
+ /* Work out who's who */
+
+ slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
+ domain, lp_winbind_separator(), user);
+
+ if (sys_getpwnam(dom_user) != NULL) {
+ pstrcpy(user, dom_user);
+ DEBUG(3,("Using unix username %s\n", dom_user));
+ }
+ }
+
+ /*
+ * Pass the user through the NT -> unix user mapping
+ * function.
+ */
+
+ (void)map_username(user);
+
+ /*
+ * Do any UNIX username case mangling.
+ */
+ smb_getpwnam(user, True);
+
+ add_session_user(user);
+
+ /*
+ * Check with orig_user for security=server and
+ * security=domain.
+ */
+
+ if (!guest && !check_server_security(orig_user, domain, user,
+ smb_apasswd, smb_apasslen, smb_ntpasswd, smb_ntpasslen) &&
+ !check_domain_security(orig_user, domain, user, smb_apasswd,
+ smb_apasslen, smb_ntpasswd, smb_ntpasslen, &ptok) &&
+ !check_hosts_equiv(user))
+ {
+
+ /*
+ * If we get here then the user wasn't guest and the remote
+ * authentication methods failed. Check the authentication
+ * methods on this local server.
+ *
+ * If an NT password was supplied try and validate with that
+ * first. This is superior as the passwords are mixed case
+ * 128 length unicode.
+ */
+
+ if(smb_ntpasslen)
+ {
+ if(!password_ok(user, smb_ntpasswd,smb_ntpasslen,NULL))
+ DEBUG(2,("NT Password did not match for user '%s'!\n", user));
+ else
+ valid_nt_password = True;
+ }
+
+
+ /* check the LanMan password only if necessary and if allowed
+ by lp_lanman_auth() */
+ if (!valid_nt_password && lp_lanman_auth())
+ {
+ DEBUG(2,("Defaulting to Lanman password for %s\n", user));
+ valid_lm_password = password_ok(user, smb_apasswd,smb_apasslen,NULL);
+ }
+
+
+ /* The true branch will be executed if
+ (1) the NT password failed (or was not tried), and
+ (2) LanMan authentication failed (or was disabled)
+ */
+ if (!valid_nt_password && !valid_lm_password)
+ {
+ if (lp_security() >= SEC_USER)
+ {
+ if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
+ {
+ delete_nt_token(&ptok);
+ DEBUG(1,("Rejecting user '%s': authentication failed\n", user));
+ END_PROFILE(SMBsesssetupX);
+ return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
+ }
+
+ if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER)
+ {
+ SAM_ACCOUNT *sampass = NULL;
+
+ pdb_init_sam(&sampass);
+
+ /*
+ * This is really bad form. We know that password_ok() failed,
+ * but the return value can't distinguish between a non-existent user
+ * and a bad password. So we try to look the user up again here
+ * to see if he or she exists. We must look up the user in the
+ * "smb passwd file" and not /etc/passwd so that we don't
+ * get confused when the two don't have a one-to-one correspondence.
+ * e.g. a standard UNIX account such as "operator" --jerry
+ */
+
+ if (pdb_getsampwnam(sampass, user))
+ {
+ delete_nt_token(&ptok);
+ DEBUG(1,("Rejecting user '%s': bad password\n", user));
+ END_PROFILE(SMBsesssetupX);
+ pdb_free_sam(sampass);
+ return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
+ }
+
+ pdb_free_sam(sampass);
+ }
+
+ /*
+ * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
+ * Then always map to guest account - as done below.
+ */
+ }
+
+ if (*smb_apasswd || !smb_getpwnam(user,True))
+ pstrcpy(user,lp_guestaccount(-1));
+ DEBUG(3,("Registered username %s for guest access\n",user));
+ guest = True;
+ }
+ }
+
+ if (!smb_getpwnam(user,True)) {
+ DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
+ pstrcpy(user,lp_guestaccount(-1));
+ guest = True;
+ }
+
+ if (!strequal(user,lp_guestaccount(-1)) &&
+ lp_servicenumber(user) < 0)
+ {
+ add_home_service(user,get_user_service_home_dir(user));
+ }
+
+
+ /* it's ok - setup a reply */
+ if (Protocol < PROTOCOL_NT1) {
+ set_message(outbuf,3,0,True);
+ } else {
+ char *p;
+ set_message(outbuf,3,3,True);
+ p = smb_buf(outbuf);
+ pstrcpy(p,"Unix"); p = skip_string(p,1);
+ pstrcpy(p,"Samba "); pstrcat(p,VERSION); p = skip_string(p,1);
+ pstrcpy(p,global_myworkgroup); unix_to_dos(p); p = skip_string(p,1);
+ set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
+ /* perhaps grab OS version here?? */
+ }
+
+ /* Set the correct uid in the outgoing and incoming packets
+ We will use this on future requests to determine which
+ user we should become.
+ */
+ {
+ const struct passwd *pw = smb_getpwnam(user,False);
+ if (!pw) {
+ delete_nt_token(&ptok);
+ DEBUG(1,("Username %s is invalid on this system\n",user));
+ END_PROFILE(SMBsesssetupX);
+ return ERROR_BOTH(NT_STATUS_LOGON_FAILURE,ERRSRV,ERRbadpw);
+ }
+ gid = pw->pw_gid;
+ uid = pw->pw_uid;
+ }
+
+ if (guest)
+ SSVAL(outbuf,smb_vwv2,1);
+
+ /* register the name and uid as being validated, so further connections
+ to a uid can get through without a password, on the same VC */
+
+ sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest,&ptok);
+
+ delete_nt_token(&ptok);
+
+ if (sess_vuid == -1) {
+ END_PROFILE(SMBsesssetupX);
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ }
+
+ SSVAL(outbuf,smb_uid,sess_vuid);
+ SSVAL(inbuf,smb_uid,sess_vuid);
+
+ if (!done_sesssetup)
+ max_send = MIN(max_send,smb_bufsize);
+
+ DEBUG(6,("Client requested max send size of %d\n", max_send));
+
+ done_sesssetup = True;
+
+ END_PROFILE(SMBsesssetupX);
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
+
/****************************************************************************
- Reply to a getatr.
+ reply to a chkpth
****************************************************************************/
+int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
+{
+ int outsize = 0;
+ int mode;
+ pstring name;
+ BOOL ok = False;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+ START_PROFILE(SMBchkpth);
+
+ pstrcpy(name,smb_buf(inbuf) + 1);
+
+ RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+
+ unix_convert(name,conn,0,&bad_path,&sbuf);
+
+ mode = SVAL(inbuf,smb_vwv0);
+ if (check_name(name,conn)) {
+ if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
+ ok = S_ISDIR(sbuf.st_mode);
+ }
+
+ if (!ok) {
+ /* We special case this - as when a Windows machine
+ is parsing a path is steps through the components
+ one at a time - if a component fails it expects
+ ERRbadpath, not ERRbadfile.
+ */
+ if(errno == ENOENT) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+
+ return(UNIXERROR(ERRDOS,ERRbadpath));
+ }
+
+ outsize = set_message(outbuf,0,0,True);
+
+ DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+
+ END_PROFILE(SMBchkpth);
+ return(outsize);
+}
+
+
+/****************************************************************************
+ reply to a getatr
+****************************************************************************/
int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring fname;
@@ -427,11 +1175,9 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SMB_OFF_T size=0;
time_t mtime=0;
BOOL bad_path = False;
- char *p;
START_PROFILE(SMBgetatr);
-
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
+
+ pstrcpy(fname,smb_buf(inbuf) + 1);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -489,10 +1235,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return(outsize);
}
+
/****************************************************************************
- Reply to a setatr.
+ reply to a setatr
****************************************************************************/
-
int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring fname;
@@ -502,12 +1248,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
time_t mtime;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
- char *p;
-
START_PROFILE(SMBsetatr);
-
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
+
+ pstrcpy(fname,smb_buf(inbuf) + 1);
unix_convert(fname,conn,0,&bad_path,&sbuf);
mode = SVAL(inbuf,smb_vwv0);
@@ -538,10 +1281,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return(outsize);
}
+
/****************************************************************************
- Reply to a dskattr.
+ reply to a dskattr
****************************************************************************/
-
int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
@@ -586,11 +1329,11 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
return(outsize);
}
+
/****************************************************************************
- Reply to a search.
- Can be called from SMBsearch, SMBffirst or SMBfunique.
+ reply to a search
+ Can be called from SMBsearch, SMBffirst or SMBfunique.
****************************************************************************/
-
int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring mask;
@@ -608,7 +1351,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
char *p;
BOOL ok = False;
int status_len;
- pstring path;
+ char *path;
char status[21];
int dptr_num= -1;
BOOL check_descend = False;
@@ -626,28 +1369,26 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
outsize = set_message(outbuf,1,3,True);
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
- p++;
- status_len = SVAL(p, 0);
- p += 2;
-
+ path = smb_buf(inbuf) + 1;
+ status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
+
+ RESOLVE_DFSPATH(path, conn, inbuf, outbuf);
/* dirtype &= ~aDIR; */
-
+
if (status_len == 0)
{
SMB_STRUCT_STAT sbuf;
pstring dir2;
- pstrcpy(directory,path);
- pstrcpy(dir2,path);
+ pstrcpy(directory,smb_buf(inbuf)+1);
+ pstrcpy(dir2,smb_buf(inbuf)+1);
unix_convert(directory,conn,0,&bad_path,&sbuf);
unix_format(dir2);
if (!check_name(directory,conn))
can_open = False;
- p = strrchr_m(dir2,'/');
+ p = strrchr(dir2,'/');
if (p == NULL)
{
pstrcpy(mask,dir2);
@@ -659,7 +1400,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
pstrcpy(mask,p+1);
}
- p = strrchr_m(directory,'/');
+ p = strrchr(directory,'/');
if (!p)
*directory = 0;
else
@@ -668,16 +1409,12 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (strlen(directory) == 0)
pstrcpy(directory,"./");
memset((char *)status,'\0',21);
- SCVAL(status,0,(dirtype & 0x1F));
+ SCVAL(status,0,dirtype);
}
else
{
- int status_dirtype;
- memcpy(status,p,21);
- status_dirtype = CVAL(status,0) & 0x1F;
- if (status_dirtype != (dirtype & 0x1F))
- dirtype = status_dirtype;
-
+ memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
+ dirtype = CVAL(status,0) & 0x1F;
conn->dirptr = dptr_fetch(status+12,&dptr_num);
if (!conn->dirptr)
goto SearchEmpty;
@@ -750,11 +1487,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SearchEmpty:
- if (numentries == 0 || !ok)
+ if ( (numentries == 0) || !ok)
{
- SCVAL(outbuf,smb_rcls,ERRDOS);
- SSVAL(outbuf,smb_err,ERRnofiles);
- dptr_close(&dptr_num);
+ SCVAL(outbuf,smb_rcls,ERRDOS);
+ SSVAL(outbuf,smb_err,ERRnofiles);
+ dptr_close(&dptr_num);
}
/* If we were called as SMBffirst with smb_search_id == NULL
@@ -780,7 +1517,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (Protocol >= PROTOCOL_NT1)
SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
-
+
outsize += DIR_STRUCT_SIZE*numentries;
smb_setlen(outbuf,outsize - 4);
@@ -795,34 +1532,30 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return(outsize);
}
+
/****************************************************************************
- Reply to a fclose (stop directory search).
+ reply to a fclose (stop directory search)
****************************************************************************/
-
int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
int status_len;
- pstring path;
+ char *path;
char status[21];
int dptr_num= -2;
- char *p;
-
START_PROFILE(SMBfclose);
outsize = set_message(outbuf,1,0,True);
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
- p++;
- status_len = SVAL(p,0);
- p += 2;
+ path = smb_buf(inbuf) + 1;
+ status_len = SVAL(smb_buf(inbuf),3 + strlen(path));
+
if (status_len == 0) {
END_PROFILE(SMBfclose);
return ERROR_DOS(ERRSRV,ERRsrverror);
}
- memcpy(status,p,21);
+ memcpy(status,smb_buf(inbuf) + 1 + strlen(path) + 4,21);
if(dptr_fetch(status+12,&dptr_num)) {
/* Close the dptr - we know it's gone */
@@ -837,8 +1570,9 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return(outsize);
}
+
/****************************************************************************
- Reply to an open.
+ reply to an open
****************************************************************************/
int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
@@ -859,7 +1593,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
share_mode = SVAL(inbuf,smb_vwv0);
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
+ pstrcpy(fname,smb_buf(inbuf)+1);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -899,19 +1633,19 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SSVAL(outbuf,smb_vwv6,rmode);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
END_PROFILE(SMBopen);
return(outsize);
}
+
/****************************************************************************
- Reply to an open and X.
+ reply to an open and X
****************************************************************************/
-
int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
pstring fname;
@@ -949,7 +1683,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+
+ pstrcpy(fname,smb_buf(inbuf));
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -995,7 +1730,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
*/
if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
- SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ SCVAL(outbuf,smb_flg, CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
@@ -1017,10 +1752,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return chain_reply(inbuf,outbuf,length,bufsize);
}
+
/****************************************************************************
- Reply to a SMBulogoffX.
+ reply to a SMBulogoffX
****************************************************************************/
-
int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
uint16 vuid = SVAL(inbuf,smb_uid);
@@ -1047,10 +1782,10 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
return chain_reply(inbuf,outbuf,length,bufsize);
}
+
/****************************************************************************
- Reply to a mknew or a create.
+ reply to a mknew or a create
****************************************************************************/
-
int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
pstring fname;
@@ -1068,7 +1803,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
com = SVAL(inbuf,smb_com);
createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
+ pstrcpy(fname,smb_buf(inbuf)+1);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
@@ -1120,90 +1855,87 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return(outsize);
}
+
/****************************************************************************
- Reply to a create temporary file.
+ reply to a create temporary file
****************************************************************************/
-
int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- pstring fname;
- int outsize = 0;
- int createmode;
- mode_t unixmode;
- BOOL bad_path = False;
- files_struct *fsp;
- int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
- int tmpfd;
- SMB_STRUCT_STAT sbuf;
- char *p, *s;
+ pstring fname;
+ int outsize = 0;
+ int createmode;
+ mode_t unixmode;
+ BOOL bad_path = False;
+ files_struct *fsp;
+ int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+ int tmpfd;
+ SMB_STRUCT_STAT sbuf;
+ char *p, *s;
- START_PROFILE(SMBctemp);
+ START_PROFILE(SMBctemp);
- createmode = SVAL(inbuf,smb_vwv0);
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
- pstrcat(fname,"\\TMXXXXXX");
+ createmode = SVAL(inbuf,smb_vwv0);
+ pstrcpy(fname,smb_buf(inbuf)+1);
+ pstrcat(fname,"\\TMXXXXXX");
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
-
- unixmode = unix_mode(conn,createmode,fname);
-
- tmpfd = smb_mkstemp(fname);
- if (tmpfd == -1) {
- END_PROFILE(SMBctemp);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ unix_convert(fname,conn,0,&bad_path,&sbuf);
- vfs_stat(conn,fname,&sbuf);
+ unixmode = unix_mode(conn,createmode,fname);
- /* Open file in dos compatibility share mode. */
- /* We should fail if file does not exist. */
- fsp = open_file_shared(conn,fname,&sbuf,
- SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
- unixmode, oplock_request, NULL, NULL);
+ tmpfd = smb_mkstemp(fname);
+ if (tmpfd == -1) {
+ END_PROFILE(SMBctemp);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- /* close fd from smb_mkstemp() */
- close(tmpfd);
+ vfs_stat(conn,fname,&sbuf);
- if (!fsp) {
- set_bad_path_error(errno, bad_path);
- END_PROFILE(SMBctemp);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ /* Open file in dos compatibility share mode. */
+ /* We should fail if file does not exist. */
+ fsp = open_file_shared(conn,fname,&sbuf,
+ SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
+ FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
+ unixmode, oplock_request, NULL, NULL);
+ /* close fd from smb_mkstemp() */
+ close(tmpfd);
- outsize = set_message(outbuf,1,0,True);
- SSVAL(outbuf,smb_vwv0,fsp->fnum);
+ if (!fsp) {
+ set_bad_path_error(errno, bad_path);
+ END_PROFILE(SMBctemp);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- /* the returned filename is relative to the directory */
- s = strrchr_m(fname, '/');
- if (!s) {
- s = fname;
- } else {
- s++;
- }
+ /* the returned filename is relative to the directory */
+ s = strrchr(fname, '/');
+ if (!s)
+ s = fname;
+ else
+ s++;
- p = smb_buf(outbuf);
- SSVALS(p, 0, -1); /* what is this? not in spec */
- SSVAL(p, 2, strlen(s));
- p += 4;
- p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
- outsize = set_message_end(outbuf, p);
+ outsize = set_message(outbuf,1,4+ strlen(fname),True);
+ SSVAL(outbuf,smb_vwv0,fsp->fnum);
- if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
- }
+ p = smb_buf(outbuf);
+ SSVALS(p, 0, -1); /* what is this? not in spec */
+ SSVAL(p, 2, strlen(s));
+ p += 4;
+ pstrcpy(p,s);
+
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
- SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
- DEBUG( 2, ( "created temp file %s\n", fname ) );
- DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
- fname, fsp->fd, createmode, (int)unixmode ) );
+ DEBUG( 2, ( "created temp file %s\n", fname ) );
+ DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
+ fname, fsp->fd, createmode, (int)unixmode ) );
- END_PROFILE(SMBctemp);
- return(outsize);
+ END_PROFILE(SMBctemp);
+ return(outsize);
}
/*******************************************************************
@@ -1256,7 +1988,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
if (!CAN_WRITE(conn))
return NT_STATUS_MEDIA_WRITE_PROTECTED;
- if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
+ if (conn->vfs_ops.lstat(conn,dos_to_unix_static(fname),&sbuf) != 0)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
fmode = dos_mode(conn,fname,&sbuf);
@@ -1266,6 +1998,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
if (fmode & aRONLY)
return NT_STATUS_CANNOT_DELETE;
}
+
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
return NT_STATUS_CANNOT_DELETE;
@@ -1304,12 +2037,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
BOOL bad_path = False;
BOOL rc = True;
SMB_STRUCT_STAT sbuf;
-
+
*directory = *mask = 0;
-
+
rc = unix_convert(name,conn,0,&bad_path,&sbuf);
-
- p = strrchr_m(name,'/');
+
+ p = strrchr(name,'/');
if (!p) {
pstrcpy(directory,".");
pstrcpy(mask,name);
@@ -1318,7 +2051,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
pstrcpy(directory,name);
pstrcpy(mask,p+1);
}
-
+
/*
* We should only check the mangled cache
* here if unix_convert failed. This means
@@ -1327,59 +2060,60 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
* for a possible mangle. This patch from
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
-
+
if (!rc && mangle_is_mangled(mask))
mangle_check_cache( mask );
-
+
has_wild = ms_has_wild(mask);
-
+
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
error = can_delete(directory,conn,dirtype);
- if (!NT_STATUS_IS_OK(error)) return error;
+ if (!NT_STATUS_IS_OK(error))
+ return error;
- if (vfs_unlink(conn,directory) == 0) {
+ if (vfs_unlink(conn,directory) == 0)
count++;
- }
} else {
void *dirptr = NULL;
char *dname;
-
- if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
-
+ if (check_name(directory,conn))
+ dirptr = OpenDir(conn, directory, True);
+
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
- the pattern matches against the long name, otherwise the short name
- We don't implement this yet XXXX
+ the pattern matches against the long name, otherwise the short name
+ We don't implement this yet XXXX
*/
-
+
if (dirptr) {
error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-
+
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
while ((dname = ReadDirName(dirptr))) {
pstring fname;
pstrcpy(fname,dname);
-
- if(!mask_match(fname, mask, case_sensitive)) continue;
-
+
+ if(!mask_match(fname, mask, case_sensitive))
+ continue;
+
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
error = can_delete(fname,conn,dirtype);
- if (!NT_STATUS_IS_OK(error)) continue;
- if (vfs_unlink(conn,fname) == 0) count++;
+ if (!NT_STATUS_IS_OK(error))
+ continue;
+ if (vfs_unlink(conn,fname) == 0)
+ count++;
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
CloseDir(dirptr);
}
}
-
- if (count == 0 && NT_STATUS_IS_OK(error)) {
+
+ if (count == 0 && NT_STATUS_IS_OK(error))
error = map_nt_error_from_unix(errno);
- }
-
+
return error;
}
@@ -1387,32 +2121,34 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
Reply to a unlink
****************************************************************************/
-int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
- int dum_buffsize)
+int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
pstring name;
int dirtype;
NTSTATUS status;
+
START_PROFILE(SMBunlink);
-
+
dirtype = SVAL(inbuf,smb_vwv0);
-
- srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
-
+
+ pstrcpy(name,smb_buf(inbuf) + 1);
+
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
-
+
DEBUG(3,("reply_unlink : %s\n",name));
-
+
status = unlink_internals(conn, dirtype, name);
- if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
+ if (!NT_STATUS_IS_OK(status))
+ return ERROR_NT(status);
/*
* Win2k needs a changenotify request response before it will
* update after a rename..
*/
+
process_pending_change_notify_queue((time_t)0);
-
+
outsize = set_message(outbuf,0,0,True);
END_PROFILE(SMBunlink);
@@ -1432,59 +2168,6 @@ void fail_readraw(void)
}
/****************************************************************************
- Use sendfile in readbraw.
-****************************************************************************/
-
-void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
- ssize_t mincount, char *outbuf)
-{
- ssize_t ret=0;
-
-#if defined(WITH_SENDFILE)
- /*
- * We can only use sendfile on a non-chained packet and on a file
- * that is exclusively oplocked. reply_readbraw has already checked the length.
- */
-
- if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
- EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
- DATA_BLOB header;
-
- _smb_setlen(outbuf,nread);
- header.data = outbuf;
- header.length = 4;
- header.free = NULL;
-
- if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
- /*
- * Special hack for broken Linux with no 64 bit clean sendfile. If we
- * return ENOSYS then pretend we just got a normal read.
- */
- if (errno == ENOSYS)
- goto normal_read;
-
- DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
- fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readbraw sendfile failed");
- }
-
- }
-
- normal_read:
-#endif
-
- if (nread > 0) {
- ret = read_file(fsp,outbuf+4,startpos,nread);
- if (ret < mincount)
- ret = 0;
- }
-
- _smb_setlen(outbuf,ret);
- if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
- fail_readraw();
-}
-
-/****************************************************************************
Reply to a readbraw (core+ protocol).
****************************************************************************/
@@ -1494,6 +2177,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
size_t nread = 0;
SMB_OFF_T startpos;
char *header = outbuf;
+ ssize_t ret=0;
files_struct *fsp;
START_PROFILE(SMBreadbraw);
@@ -1580,9 +2264,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
if (size < sizeneeded) {
SMB_STRUCT_STAT st;
if (vfs_fstat(fsp,fsp->fd,&st) == 0)
- size = st.st_size;
- if (!fsp->can_write)
- fsp->size = size;
+ fsp->size = size = st.st_size;
}
if (startpos >= size)
@@ -1597,288 +2279,217 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
(int)maxcount, (int)mincount, (int)nread ) );
- send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
+ if (nread > 0) {
+ ret = read_file(fsp,header+4,startpos,nread);
+ if (ret < mincount)
+ ret = 0;
+ }
+
+ _smb_setlen(header,ret);
+ if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
+ fail_readraw();
DEBUG(5,("readbraw finished\n"));
END_PROFILE(SMBreadbraw);
return -1;
}
+
/****************************************************************************
- Reply to a lockread (core+ protocol).
+ reply to a lockread (core+ protocol)
****************************************************************************/
-
int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
{
- ssize_t nread = -1;
- char *data;
- int outsize = 0;
- SMB_OFF_T startpos;
- size_t numtoread;
+ ssize_t nread = -1;
+ char *data;
+ int outsize = 0;
+ SMB_OFF_T startpos;
+ size_t numtoread;
NTSTATUS status;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBlockread);
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBlockread);
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- release_level_2_oplocks_on_change(fsp);
+ release_level_2_oplocks_on_change(fsp);
- numtoread = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
+ numtoread = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
- outsize = set_message(outbuf,5,3,True);
- numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
- data = smb_buf(outbuf) + 3;
-
- /*
- * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
- * protocol request that predates the read/write lock concept.
- * Thus instead of asking for a read lock here we need to ask
- * for a write lock. JRA.
- */
-
+ outsize = set_message(outbuf,5,3,True);
+ numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+ data = smb_buf(outbuf) + 3;
+
+ /*
+ * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
+ * protocol request that predates the read/write lock concept.
+ * Thus instead of asking for a read lock here we need to ask
+ * for a write lock. JRA.
+ */
+
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
if (NT_STATUS_V(status)) {
- if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length, -1, 0)) {
- END_PROFILE(SMBlockread);
- return -1;
- }
- }
+ if (lp_blocking_locks(SNUM(conn))) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length, -1, 0))
END_PROFILE(SMBlockread);
+ return -1;
+ }
+ END_PROFILE(SMBlockread);
return ERROR_NT(status);
- }
+ }
- nread = read_file(fsp,data,startpos,numtoread);
+ nread = read_file(fsp,data,startpos,numtoread);
- if (nread < 0) {
- END_PROFILE(SMBlockread);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- outsize += nread;
- SSVAL(outbuf,smb_vwv0,nread);
- SSVAL(outbuf,smb_vwv5,nread+3);
- SSVAL(smb_buf(outbuf),1,nread);
-
- DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
- fsp->fnum, (int)numtoread, (int)nread));
+ if (nread < 0) {
+ END_PROFILE(SMBlockread);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- END_PROFILE(SMBlockread);
- return(outsize);
+ outsize += nread;
+ SSVAL(outbuf,smb_vwv0,nread);
+ SSVAL(outbuf,smb_vwv5,nread+3);
+ SSVAL(smb_buf(outbuf),1,nread);
+
+ DEBUG( 3, ( "lockread fnum=%d num=%d nread=%d\n",
+ fsp->fnum, (int)numtoread, (int)nread ) );
+
+ END_PROFILE(SMBlockread);
+ return(outsize);
}
+
/****************************************************************************
- Reply to a read.
+ reply to a read
****************************************************************************/
int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- size_t numtoread;
- ssize_t nread = 0;
- char *data;
- SMB_OFF_T startpos;
- int outsize = 0;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBread);
-
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
-
- numtoread = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
-
- outsize = set_message(outbuf,5,3,True);
- numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
- data = smb_buf(outbuf) + 3;
-
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
- END_PROFILE(SMBread);
- return ERROR_DOS(ERRDOS,ERRlock);
- }
+ size_t numtoread;
+ ssize_t nread = 0;
+ char *data;
+ SMB_OFF_T startpos;
+ int outsize = 0;
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBread);
- if (numtoread > 0)
- nread = read_file(fsp,data,startpos,numtoread);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- if (nread < 0) {
- END_PROFILE(SMBread);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ numtoread = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
- outsize += nread;
- SSVAL(outbuf,smb_vwv0,nread);
- SSVAL(outbuf,smb_vwv5,nread+3);
- SCVAL(smb_buf(outbuf),0,1);
- SSVAL(smb_buf(outbuf),1,nread);
+ outsize = set_message(outbuf,5,3,True);
+ numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+ data = smb_buf(outbuf) + 3;
- DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
- fsp->fnum, (int)numtoread, (int)nread ) );
-
- END_PROFILE(SMBread);
- return(outsize);
-}
-
-/****************************************************************************
- Reply to a read and X - possibly using sendfile.
-****************************************************************************/
-
-int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
- files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
-{
- ssize_t nread = -1;
- char *data = smb_buf(outbuf);
-
-#if defined(WITH_SENDFILE)
- /*
- * We can only use sendfile on a non-chained packet and on a file
- * that is exclusively oplocked.
- */
-
- if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
- lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
- SMB_STRUCT_STAT sbuf;
- DATA_BLOB header;
-
- if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
- return(UNIXERROR(ERRDOS,ERRnoaccess));
-
- if (startpos > sbuf.st_size)
- goto normal_read;
-
- if (smb_maxcnt > (sbuf.st_size - startpos))
- smb_maxcnt = (sbuf.st_size - startpos);
-
- if (smb_maxcnt == 0)
- goto normal_read;
-
- /*
- * Set up the packet header before send. We
- * assume here the sendfile will work (get the
- * correct amount of data).
- */
-
- SSVAL(outbuf,smb_vwv5,smb_maxcnt);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
- SCVAL(outbuf,smb_vwv0,0xFF);
- set_message(outbuf,12,smb_maxcnt,False);
- header.data = outbuf;
- header.length = data - outbuf;
- header.free = NULL;
-
- if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
- /*
- * Special hack for broken Linux with no 64 bit clean sendfile. If we
- * return ENOSYS then pretend we just got a normal read.
- */
- if (errno == ENOSYS)
- goto normal_read;
-
- DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
- fsp->fsp_name, strerror(errno) ));
- exit_server("send_file_readX sendfile failed");
- }
-
- DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
- return -1;
- }
-
- normal_read:
-
-#endif
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ END_PROFILE(SMBread);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
- nread = read_file(fsp,data,startpos,smb_maxcnt);
+ if (numtoread > 0)
+ nread = read_file(fsp,data,startpos,numtoread);
- if (nread < 0) {
- END_PROFILE(SMBreadX);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- SSVAL(outbuf,smb_vwv5,nread);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(smb_buf(outbuf),-2,nread);
+ if (nread < 0) {
+ END_PROFILE(SMBread);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ outsize += nread;
+ SSVAL(outbuf,smb_vwv0,nread);
+ SSVAL(outbuf,smb_vwv5,nread+3);
+ SCVAL(smb_buf(outbuf),0,1);
+ SSVAL(smb_buf(outbuf),1,nread);
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
+ fsp->fnum, (int)numtoread, (int)nread ) );
- return nread;
+ END_PROFILE(SMBread);
+ return(outsize);
}
+
/****************************************************************************
- Reply to a read and X.
+ reply to a read and X
****************************************************************************/
-
int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
- files_struct *fsp = file_fsp(inbuf,smb_vwv2);
- SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
- ssize_t nread = -1;
- size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
-#if 0
- size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
-#endif
-
- START_PROFILE(SMBreadX);
+ files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+ SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
+ size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+ size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
+ ssize_t nread = -1;
+ char *data;
+ START_PROFILE(SMBreadX);
- /* If it's an IPC, pass off the pipe handler. */
- if (IS_IPC(conn)) {
- END_PROFILE(SMBreadX);
- return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
- }
+ /* If it's an IPC, pass off the pipe handler. */
+ if (IS_IPC(conn)) {
+ END_PROFILE(SMBreadX);
+ return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
+ }
- CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ CHECK_FSP(fsp,conn);
+ CHECK_READ(fsp);
- set_message(outbuf,12,0,True);
+ set_message(outbuf,12,0,True);
+ data = smb_buf(outbuf);
- if(CVAL(inbuf,smb_wct) == 12) {
+ if(CVAL(inbuf,smb_wct) == 12) {
#ifdef LARGE_SMB_OFF_T
- /*
- * This is a large offset (64 bit) read.
- */
- startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
+ /*
+ * This is a large offset (64 bit) read.
+ */
+ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
#else /* !LARGE_SMB_OFF_T */
- /*
- * Ensure we haven't been sent a >32 bit offset.
- */
+ /*
+ * Ensure we haven't been sent a >32 bit offset.
+ */
- if(IVAL(inbuf,smb_vwv10) != 0) {
- DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
+ if(IVAL(inbuf,smb_vwv10) != 0) {
+ DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
- END_PROFILE(SMBreadX);
- return ERROR_DOS(ERRDOS,ERRbadaccess);
- }
+ END_PROFILE(SMBreadX);
+ return ERROR_DOS(ERRDOS,ERRbadaccess);
+ }
#endif /* LARGE_SMB_OFF_T */
- }
-
- if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
- END_PROFILE(SMBreadX);
- return ERROR_DOS(ERRDOS,ERRlock);
- }
+ }
- nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
- if (nread != -1)
- nread = chain_reply(inbuf,outbuf,length,bufsize);
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ END_PROFILE(SMBreadX);
+ return ERROR_DOS(ERRDOS,ERRlock);
+ }
+ nread = read_file(fsp,data,startpos,smb_maxcnt);
+
+ if (nread < 0) {
+ END_PROFILE(SMBreadX);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ SSVAL(outbuf,smb_vwv5,nread);
+ SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(smb_buf(outbuf),-2,nread);
+
+ DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
- END_PROFILE(SMBreadX);
- return nread;
+ END_PROFILE(SMBreadX);
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
/****************************************************************************
- Reply to a writebraw (core+ or LANMAN1.0 protocol).
+ reply to a writebraw (core+ or LANMAN1.0 protocol)
****************************************************************************/
int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -1993,15 +2604,12 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
/* we won't return a status if write through is not selected - this follows what WfWg does */
END_PROFILE(SMBwritebraw);
if (!write_through && total_written==tcount) {
-
-#if RABBIT_PELLET_FIX
/*
* Fix for "rabbit pellet" mode, trigger an early TCP ack by
* sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
*/
if (!send_keepalive(smbd_server_fd()))
exit_server("reply_writebraw: send of keepalive failed");
-#endif
return(-1);
}
@@ -2009,68 +2617,68 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
/****************************************************************************
- Reply to a writeunlock (core+).
+ reply to a writeunlock (core+)
****************************************************************************/
-int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
- int size, int dum_buffsize)
+int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- ssize_t nwritten = -1;
- size_t numtowrite;
- SMB_OFF_T startpos;
- char *data;
+ ssize_t nwritten = -1;
+ size_t numtowrite;
+ SMB_OFF_T startpos;
+ char *data;
NTSTATUS status;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- int outsize = 0;
- START_PROFILE(SMBwriteunlock);
-
- CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ int outsize = 0;
+ START_PROFILE(SMBwriteunlock);
- numtowrite = SVAL(inbuf,smb_vwv1);
- startpos = IVAL(inbuf,smb_vwv2);
- data = smb_buf(inbuf) + 3;
+ CHECK_FSP(fsp,conn);
+ CHECK_WRITE(fsp);
+
+ numtowrite = SVAL(inbuf,smb_vwv1);
+ startpos = IVAL(inbuf,smb_vwv2);
+ data = smb_buf(inbuf) + 3;
if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
WRITE_LOCK,False)) {
- END_PROFILE(SMBwriteunlock);
+ END_PROFILE(SMBwriteunlock);
return ERROR_DOS(ERRDOS,ERRlock);
- }
+ }
- /* The special X/Open SMB protocol handling of
- zero length writes is *NOT* done for
- this call */
- if(numtowrite == 0)
- nwritten = 0;
- else
- nwritten = write_file(fsp,data,startpos,numtowrite);
+ /* The special X/Open SMB protocol handling of
+ zero length writes is *NOT* done for
+ this call */
+ if(numtowrite == 0)
+ nwritten = 0;
+ else
+ nwritten = write_file(fsp,data,startpos,numtowrite);
- if (lp_syncalways(SNUM(conn)))
- sync_file(conn,fsp);
+ if (lp_syncalways(SNUM(conn)))
+ sync_file(conn,fsp);
- if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
- END_PROFILE(SMBwriteunlock);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
+ END_PROFILE(SMBwriteunlock);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
(SMB_BIG_UINT)startpos);
if (NT_STATUS_V(status)) {
- END_PROFILE(SMBwriteunlock);
+ END_PROFILE(SMBwriteunlock);
return ERROR_NT(status);
- }
-
- outsize = set_message(outbuf,1,0,True);
-
- SSVAL(outbuf,smb_vwv0,nwritten);
-
- DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten));
-
- END_PROFILE(SMBwriteunlock);
- return outsize;
+ }
+
+ outsize = set_message(outbuf,1,0,True);
+
+ SSVAL(outbuf,smb_vwv0,nwritten);
+
+ DEBUG( 3, ( "writeunlock fnum=%d num=%d wrote=%d\n",
+ fsp->fnum, (int)numtowrite, (int)nwritten ) );
+
+ END_PROFILE(SMBwriteunlock);
+ return(outsize);
}
+
/****************************************************************************
Reply to a write.
****************************************************************************/
@@ -2149,10 +2757,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
return(outsize);
}
+
/****************************************************************************
- Reply to a write and X.
+ reply to a write and X
****************************************************************************/
-
int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
@@ -2249,8 +2857,9 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
return chain_reply(inbuf,outbuf,length,bufsize);
}
+
/****************************************************************************
- Reply to a lseek.
+ reply to a lseek
****************************************************************************/
int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -2341,22 +2950,21 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
START_PROFILE(SMBflush);
CHECK_FSP(fsp,conn);
-
+
if (!fsp) {
file_sync_all(conn);
} else {
sync_file(conn,fsp);
}
-
+
DEBUG(3,("flush\n"));
END_PROFILE(SMBflush);
return(outsize);
}
/****************************************************************************
- Reply to a exit.
+ reply to a exit
****************************************************************************/
-
int reply_exit(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -2370,16 +2978,15 @@ int reply_exit(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
Reply to a close - has to deal with closing a directory opened by NT SMB's.
****************************************************************************/
-
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
int outsize = 0;
time_t mtime;
- int32 eclass = 0, err = 0;
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
@@ -2445,18 +3052,13 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
- /* We have a cached error */
- if(eclass || err) {
- END_PROFILE(SMBclose);
- return ERROR_DOS(eclass,err);
- }
-
END_PROFILE(SMBclose);
return(outsize);
}
+
/****************************************************************************
- Reply to a writeclose (Core+ protocol).
+ reply to a writeclose (Core+ protocol)
****************************************************************************/
int reply_writeclose(connection_struct *conn,
@@ -2513,10 +3115,10 @@ int reply_writeclose(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
- Reply to a lock.
+ reply to a lock
****************************************************************************/
-
int reply_lock(connection_struct *conn,
char *inbuf,char *outbuf, int length, int dum_buffsize)
{
@@ -2538,18 +3140,18 @@ int reply_lock(connection_struct *conn,
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
if (NT_STATUS_V(status)) {
- if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
- /*
- * A blocking lock was requested. Package up
- * this smb into a queued request and push it
- * onto the blocking lock queue.
- */
- if(push_blocking_lock_request(inbuf, length, -1, 0)) {
- END_PROFILE(SMBlock);
- return -1;
- }
- }
- END_PROFILE(SMBlock);
+ if (lp_blocking_locks(SNUM(conn))) {
+ /*
+ * A blocking lock was requested. Package up
+ * this smb into a queued request and push it
+ * onto the blocking lock queue.
+ */
+ if(push_blocking_lock_request(inbuf, length, -1, 0)) {
+ END_PROFILE(SMBlock);
+ return -1;
+ }
+ }
+ END_PROFILE(SMBlock);
return ERROR_NT(status);
}
@@ -2557,41 +3159,40 @@ int reply_lock(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
- Reply to a unlock.
+ reply to a unlock
****************************************************************************/
-
-int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
- int dum_buffsize)
+int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- int outsize = set_message(outbuf,0,0,True);
- SMB_BIG_UINT count,offset;
+ int outsize = set_message(outbuf,0,0,True);
+ SMB_BIG_UINT count,offset;
NTSTATUS status;
- files_struct *fsp = file_fsp(inbuf,smb_vwv0);
- START_PROFILE(SMBunlock);
+ files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+ START_PROFILE(SMBunlock);
+
+ CHECK_FSP(fsp,conn);
+
+ count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
+ offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
- CHECK_FSP(fsp,conn);
-
- count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
- offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
-
status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
if (NT_STATUS_V(status)) {
- END_PROFILE(SMBunlock);
+ END_PROFILE(SMBunlock);
return ERROR_NT(status);
- }
+ }
- DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count ) );
-
- END_PROFILE(SMBunlock);
- return(outsize);
+ DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
+ fsp->fd, fsp->fnum, (double)offset, (double)count ) );
+
+ END_PROFILE(SMBunlock);
+ return(outsize);
}
+
/****************************************************************************
- Reply to a tdis.
+ reply to a tdis
****************************************************************************/
-
int reply_tdis(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -2615,10 +3216,11 @@ int reply_tdis(connection_struct *conn,
return outsize;
}
+
+
/****************************************************************************
- Reply to a echo.
+ reply to a echo
****************************************************************************/
-
int reply_echo(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -2656,10 +3258,10 @@ int reply_echo(connection_struct *conn,
return -1;
}
+
/****************************************************************************
- Reply to a printopen.
+ reply to a printopen
****************************************************************************/
-
int reply_printopen(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -2690,8 +3292,9 @@ int reply_printopen(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
- Reply to a printclose.
+ reply to a printclose
****************************************************************************/
int reply_printclose(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
@@ -2723,10 +3326,10 @@ int reply_printclose(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
- Reply to a printqueue.
+ reply to a printqueue
****************************************************************************/
-
int reply_printqueue(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
@@ -2773,7 +3376,7 @@ int reply_printqueue(connection_struct *conn,
SSVAL(p,5, queue[i].job);
SIVAL(p,7,queue[i].size);
SCVAL(p,11,0);
- srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
+ StrnCpy(p+12,queue[i].fs_user,16);
p += 28;
}
@@ -2794,10 +3397,10 @@ int reply_printqueue(connection_struct *conn,
return(outsize);
}
+
/****************************************************************************
- Reply to a printwrite.
+ reply to a printwrite
****************************************************************************/
-
int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int numtowrite;
@@ -2828,29 +3431,29 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
return(outsize);
}
+
/****************************************************************************
The guts of the mkdir command, split out so it may be called by the NT SMB
code.
****************************************************************************/
-
NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
{
BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
int ret= -1;
-
+
unix_convert(directory,conn,0,&bad_path,&sbuf);
-
+
if (check_name(directory, conn))
ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
-
+
if (ret == -1) {
NTSTATUS nterr = set_bad_path_error(errno, bad_path);
if (!NT_STATUS_IS_OK(nterr))
return nterr;
return map_nt_error_from_unix(errno);
}
-
+
return NT_STATUS_OK;
}
@@ -2865,7 +3468,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
START_PROFILE(SMBmkdir);
- srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
+ pstrcpy(directory,smb_buf(inbuf) + 1);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
@@ -2913,7 +3516,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
pstrcat(fullname, "/");
pstrcat(fullname, dname);
- if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
+ if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0) {
ret = True;
break;
}
@@ -2932,6 +3535,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
break;
}
}
+
CloseDir(dirptr);
return ret;
}
@@ -2966,7 +3570,6 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
break;
}
}
-
if(all_veto_files) {
SeekDir(dirptr,dirpos);
while ((dname = ReadDirName(dirptr))) {
@@ -2981,12 +3584,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
errno = ENOMEM;
break;
}
-
pstrcpy(fullname, directory);
pstrcat(fullname, "/");
pstrcat(fullname, dname);
- if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
+ if(conn->vfs_ops.lstat(conn,dos_to_unix_static(fullname), &st) != 0)
break;
if(st.st_mode & S_IFDIR) {
if(lp_recursive_veto_delete(SNUM(conn))) {
@@ -3008,7 +3610,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
errno = ENOTEMPTY;
}
}
-
+
if (!ok)
DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
@@ -3028,7 +3630,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBrmdir);
- srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
+ pstrcpy(directory,smb_buf(inbuf) + 1);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
@@ -3055,31 +3657,31 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return(outsize);
}
+
/*******************************************************************
- Resolve wildcards in a filename rename.
+resolve wildcards in a filename rename
********************************************************************/
-
static BOOL resolve_wildcards(char *name1,char *name2)
{
fstring root1,root2;
fstring ext1,ext2;
char *p,*p2;
- name1 = strrchr_m(name1,'/');
- name2 = strrchr_m(name2,'/');
+ name1 = strrchr(name1,'/');
+ name2 = strrchr(name2,'/');
if (!name1 || !name2) return(False);
fstrcpy(root1,name1);
fstrcpy(root2,name2);
- p = strrchr_m(root1,'.');
+ p = strrchr(root1,'.');
if (p) {
*p = 0;
fstrcpy(ext1,p+1);
} else {
fstrcpy(ext1,"");
}
- p = strrchr_m(root2,'.');
+ p = strrchr(root2,'.');
if (p) {
*p = 0;
fstrcpy(ext2,p+1);
@@ -3153,7 +3755,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
* as this is checked in resolve_wildcards().
*/
- p = strrchr_m(name,'/');
+ p = strrchr(name,'/');
if (!p) {
pstrcpy(directory,".");
pstrcpy(mask,name);
@@ -3179,6 +3781,9 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
has_wild = ms_has_wild(mask);
if (!has_wild) {
+ pstring zdirectory;
+ pstring znewname;
+
/*
* No wildcards - just process the one file.
*/
@@ -3189,7 +3794,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
pstrcat(directory,mask);
/* Ensure newname contains a '/' also */
- if(strrchr_m(newname,'/') == 0) {
+ if(strrchr(newname,'/') == 0) {
pstring tmpstr;
pstrcpy(tmpstr, "./");
@@ -3198,7 +3803,7 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO
}
DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
-directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
+directory = %s, newname = %s, newname_last_component = %s, mangle_is_8_3 = %d\n",
case_sensitive, case_preserve, short_case_preserve, directory,
newname, newname_last_component, is_short_name));
@@ -3223,7 +3828,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
* Note that we guarantee that newname contains a '/'
* character above.
*/
- p = strrchr_m(newname,'/');
+ p = strrchr(newname,'/');
pstrcpy(newname_modified_last_component,p+1);
if(strcsequal(newname_modified_last_component,
@@ -3235,9 +3840,10 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
pstrcpy(p+1, newname_last_component);
}
}
-
+
+
resolve_wildcards(directory,newname);
-
+
/*
* The source object must exist.
*/
@@ -3252,7 +3858,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
* directory existed or not.
*/
- p = strrchr_m(directory, '/');
+ p = strrchr(directory, '/');
if (!p)
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
*p = '\0';
@@ -3262,7 +3868,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
}
error = map_nt_error_from_unix(errno);
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ get_nt_error_msg(error), directory,newname));
return error;
}
@@ -3271,16 +3877,19 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
if (!NT_STATUS_IS_OK(error)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ get_nt_error_msg(error), directory,newname));
return error;
}
+ pstrcpy(zdirectory, dos_to_unix_static(directory));
+ pstrcpy(znewname, dos_to_unix_static(newname));
+
/*
* If the src and dest names are identical - including case,
* don't do the rename, just return success.
*/
- if (strcsequal(directory, newname)) {
+ if (strcsequal(zdirectory, znewname)) {
DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
return NT_STATUS_OK;
}
@@ -3291,7 +3900,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
+ if(conn->vfs_ops.rename(conn,zdirectory, znewname) == 0) {
DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
directory,newname));
return NT_STATUS_OK;
@@ -3303,10 +3912,11 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
error = map_nt_error_from_unix(errno);
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(error), directory,newname));
+ get_nt_error_msg(error), directory,newname));
return error;
} else {
+
/*
* Wildcards - process each file that matches.
*/
@@ -3335,12 +3945,12 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
if (!vfs_object_exist(conn, fname, &sbuf1)) {
error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
- DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
+ DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
continue;
}
error = can_rename(fname,conn,&sbuf1);
if (!NT_STATUS_IS_OK(error)) {
- DEBUG(6,("rename %s refused\n", fname));
+ DEBUG(6,("rename %s failed. Error %s\n", fname, get_nt_error_msg(error)));
continue;
}
pstrcpy(destname,newname);
@@ -3352,20 +3962,21 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
}
if (!replace_if_exists &&
- vfs_file_exist(conn,destname, NULL)) {
+ vfs_object_exist(conn,destname, NULL)) {
DEBUG(6,("file_exist %s\n", destname));
error = NT_STATUS_OBJECT_NAME_COLLISION;
continue;
}
- if (!conn->vfs_ops.rename(conn,fname,destname))
+ if (!conn->vfs_ops.rename(conn,dos_to_unix_static(fname),
+ dos_to_unix_static(destname)))
count++;
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
}
CloseDir(dirptr);
}
}
-
+
if (count == 0 && NT_STATUS_IS_OK(error)) {
error = map_nt_error_from_unix(errno);
}
@@ -3377,27 +3988,22 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
Reply to a mv.
****************************************************************************/
-int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
- int dum_buffsize)
+int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
pstring name;
pstring newname;
- char *p;
NTSTATUS status;
-
START_PROFILE(SMBmv);
- p = smb_buf(inbuf) + 1;
- p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
- p++;
- p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
-
+ pstrcpy(name,smb_buf(inbuf) + 1);
+ pstrcpy(newname,smb_buf(inbuf) + 3 + strlen(name));
+
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
-
+
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
-
+
status = rename_internals(conn, name, newname, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
@@ -3406,7 +4012,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/*
* Win2k needs a changenotify request response before it will
* update after a rename..
- */
+ */
process_pending_change_notify_queue((time_t)0);
outsize = set_message(outbuf,0,0,True);
@@ -3431,7 +4037,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
pstrcpy(dest,dest1);
if (target_is_directory) {
- char *p = strrchr_m(src,'/');
+ char *p = strrchr(src,'/');
if (p)
p++;
else
@@ -3493,10 +4099,11 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
return(ret == (SMB_OFF_T)src_sbuf.st_size);
}
-/****************************************************************************
- Reply to a file copy.
-****************************************************************************/
+
+/****************************************************************************
+ reply to a file copy.
+ ****************************************************************************/
int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
@@ -3521,9 +4128,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*directory = *mask = 0;
- p = smb_buf(inbuf);
- p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
+ pstrcpy(name,smb_buf(inbuf));
+ pstrcpy(newname,smb_buf(inbuf) + 1 + strlen(name));
DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
@@ -3559,7 +4165,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_DOS(ERRSRV,ERRerror);
}
- p = strrchr_m(name,'/');
+ p = strrchr(name,'/');
if (!p) {
pstrcpy(directory,"./");
pstrcpy(mask,name);
@@ -3579,7 +4185,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*/
if (!rc && mangle_is_mangled(mask))
- mangle_check_cache( mask );
+ mangle_check_cache( mask );
has_wild = ms_has_wild(mask);
@@ -3659,9 +4265,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
/****************************************************************************
- Reply to a setdir.
+ reply to a setdir
****************************************************************************/
-
int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int snum;
@@ -3675,8 +4280,9 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
END_PROFILE(pathworks_setdir);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
-
- srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
+
+ pstrcpy(newdir,smb_buf(inbuf) + 1);
+ strlower(newdir);
if (strlen(newdir) == 0) {
ok = True;
@@ -3835,7 +4441,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma
}
/****************************************************************************
- Reply to a lockingX request.
+ reply to a lockingX request
****************************************************************************/
int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -3855,9 +4461,9 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
NTSTATUS status;
START_PROFILE(SMBlockingX);
-
+
CHECK_FSP(fsp,conn);
-
+
data = smb_buf(inbuf);
if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
@@ -3866,21 +4472,21 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
compatible! (tridge) */
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
-
+
/* Check if this is an oplock break on a file
- we have granted an oplock on.
+ we have granted an oplock on.
*/
if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
/* Client can insist on breaking to none. */
BOOL break_to_none = (oplocklevel == 0);
-
+
DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
- (unsigned int)oplocklevel, fsp->fnum ));
+ (unsigned int)oplocklevel, fsp->fnum ));
/*
* Make sure we have granted an exclusive or batch oplock on this file.
*/
-
+
if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
@@ -3897,16 +4503,16 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
if (remove_oplock(fsp, break_to_none) == False) {
DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
- fsp->fsp_name ));
+ fsp->fsp_name ));
}
-
+
/* if this is a pure oplock break request then don't send a reply */
if (num_locks == 0 && num_ulocks == 0) {
/* Sanity check - ensure a pure oplock break is not a
- chained request. */
+ chained request. */
if(CVAL(inbuf,smb_vwv0) != 0xff)
DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
- (unsigned int)CVAL(inbuf,smb_vwv0) ));
+ (unsigned int)CVAL(inbuf,smb_vwv0) ));
END_PROFILE(SMBlockingX);
return -1;
}
@@ -3916,16 +4522,16 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
* We do this check *after* we have checked this is not a oplock break
* response message. JRA.
*/
-
+
release_level_2_oplocks_on_change(fsp);
-
+
/* Data now points at the beginning of the list
- of smb_unlkrng structs */
+ of smb_unlkrng structs */
for(i = 0; i < (int)num_ulocks; i++) {
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
-
+
/*
* There is no error code marked "stupid client bug".... :-).
*/
@@ -3935,8 +4541,8 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
}
DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
- (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
-
+ (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
+
status = do_unlock(fsp,conn,lock_pid,count,offset);
if (NT_STATUS_V(status)) {
END_PROFILE(SMBlockingX);
@@ -3947,18 +4553,18 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
/* Setup the timeout in seconds. */
lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
-
+
/* Now do any requested locks */
data += ((large_file_format ? 20 : 10)*num_ulocks);
-
+
/* Data now points at the beginning of the list
- of smb_lkrng structs */
-
+ of smb_lkrng structs */
+
for(i = 0; i < (int)num_locks; i++) {
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
-
+
/*
* There is no error code marked "stupid client bug".... :-).
*/
@@ -3966,15 +4572,16 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
END_PROFILE(SMBlockingX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
-
+
DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
- (double)offset, (double)count, (unsigned int)lock_pid,
- fsp->fsp_name, (int)lock_timeout ));
-
+ (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name,
+ (int)lock_timeout ));
+
status = do_lock_spin(fsp,conn,lock_pid, count,offset,
- ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
+ ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
+
if (NT_STATUS_V(status)) {
- if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+ if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
/*
* A blocking lock was requested. Package up
* this smb into a queued request and push it
@@ -3988,10 +4595,10 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
break;
}
}
-
+
/* If any of the above locks failed, then we must unlock
- all of the previous locks (X/Open spec). */
- if (i != num_locks && num_locks != 0) {
+ all of the previous locks (X/Open spec). */
+ if(i != num_locks && num_locks != 0) {
/*
* Ensure we don't do a remove on the lock that just failed,
* as under POSIX rules, if we have a lock already there, we
@@ -4001,7 +4608,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
-
+
/*
* There is no error code marked "stupid client bug".... :-).
*/
@@ -4009,7 +4616,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
END_PROFILE(SMBlockingX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
-
+
do_unlock(fsp,conn,lock_pid,count,offset);
}
END_PROFILE(SMBlockingX);
@@ -4017,16 +4624,18 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
}
set_message(outbuf,2,0,True);
-
+
DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
-
+ fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
+
END_PROFILE(SMBlockingX);
return chain_reply(inbuf,outbuf,length,bufsize);
}
+/* Back from the dead for OS/2..... JRA. */
+
/****************************************************************************
- Reply to a SMBreadbmpx (read block multiplex) request.
+ Reply to a SMBreadbmpx (read block multiplex) request
****************************************************************************/
int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -4053,6 +4662,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
CHECK_FSP(fsp,conn);
CHECK_READ(fsp);
+ CHECK_ERROR(fsp);
startpos = IVAL(inbuf,smb_vwv1);
maxcount = SVAL(inbuf,smb_vwv3);
@@ -4067,14 +4677,14 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
tcount = maxcount;
total_read = 0;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK, False)) {
END_PROFILE(SMBreadBmpx);
return ERROR_DOS(ERRDOS,ERRlock);
}
do {
size_t N = MIN(max_per_packet,tcount-total_read);
-
+
nread = read_file(fsp,data,startpos,N);
if (nread <= 0)
@@ -4122,7 +4732,6 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
* Convert the DOS times into unix times. Ignore create
* time as UNIX can't set this.
*/
-
unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
@@ -4219,6 +4828,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
wbms = fsp->wbmpx_ptr; /* Use an existing struct */
else
wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
+
if(!wbms) {
DEBUG(0,("Out of memory in reply_readmpx\n"));
END_PROFILE(SMBwriteBmpx);
@@ -4237,11 +4847,11 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
SCVAL(outbuf,smb_com,SMBwriteBmpx);
outsize = set_message(outbuf,1,0,True);
-
+
SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
- fsp->fnum, (int)numtowrite, (int)nwritten ) );
+ fsp->fnum, (int)numtowrite, (int)nwritten ) );
if (write_through && tcount==nwritten) {
/* We need to send both a primary and a secondary response */
@@ -4316,8 +4926,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
if (nwritten < (ssize_t)numtowrite) {
if(write_through) {
/* We are returning an error - we can delete the aux struct */
- if (wbms)
- free((char *)wbms);
+ SAFE_FREE(wbms);
fsp->wbmpx_ptr = NULL;
END_PROFILE(SMBwriteBs);
return(ERROR_DOS(ERRHRD,ERRdiskfull));
@@ -4336,7 +4945,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
send_response = True;
}
- free((char *)wbms);
+ SAFE_FREE(wbms);
fsp->wbmpx_ptr = NULL;
}
@@ -4368,7 +4977,8 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
return ERROR_DOS(ERRDOS,ERRbadfid);
}
- /* Do an fstat on this file */
+ /* Do an stat on this file */
+
if(fsp_stat(fsp, &sbuf)) {
END_PROFILE(SMBgetattrE);
return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -4376,8 +4986,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
mode = dos_mode(conn,fsp->fsp_name,&sbuf);
- /*
- * Convert the times into dos times. Set create
+ /* Convert the times into dos times. Set create
* date to be last modify date as UNIX doesn't save
* this.
*/
@@ -4385,7 +4994,6 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
-
if (mode & aDIR) {
SIVAL(outbuf,smb_vwv6,0);
SIVAL(outbuf,smb_vwv8,0);