summaryrefslogtreecommitdiff
path: root/source4/smbd
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2004-02-03 05:47:36 +0000
committerStefan Metzmacher <metze@samba.org>2004-02-03 05:47:36 +0000
commit26ecaa32266e0c8699f280dd190811c310f2939c (patch)
treef33117f0ace3da6141e932f97cfcc51ef53233ab /source4/smbd
parentb2f097ad38e3216946dcc45f749198d337fc117e (diff)
downloadsamba-26ecaa32266e0c8699f280dd190811c310f2939c.tar.gz
samba-26ecaa32266e0c8699f280dd190811c310f2939c.tar.bz2
samba-26ecaa32266e0c8699f280dd190811c310f2939c.zip
- move all SMB server stuff to smb_server/*
and create the SMB server subsystem - remove unused XML and MYSQL configure tests metze (This used to be commit 956d212c83d8ebd8e31ec109f17dc2105ca72c30)
Diffstat (limited to 'source4/smbd')
-rw-r--r--source4/smbd/conn.c158
-rw-r--r--source4/smbd/connection.c223
-rw-r--r--source4/smbd/negprot.c526
-rw-r--r--source4/smbd/nttrans.c273
-rw-r--r--source4/smbd/password.c492
-rw-r--r--source4/smbd/process.c748
-rw-r--r--source4/smbd/reply.c2380
-rw-r--r--source4/smbd/request.c602
-rw-r--r--source4/smbd/search.c229
-rw-r--r--source4/smbd/service.c339
-rw-r--r--source4/smbd/session.c42
-rw-r--r--source4/smbd/sesssetup.c149
-rw-r--r--source4/smbd/tcon.c3
-rw-r--r--source4/smbd/trans2.c1411
14 files changed, 0 insertions, 7575 deletions
diff --git a/source4/smbd/conn.c b/source4/smbd/conn.c
deleted file mode 100644
index 0498b3cb5d..0000000000
--- a/source4/smbd/conn.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Manage connections_struct structures
- Copyright (C) Andrew Tridgell 1998
- Copyright (C) Alexander Bokovoy 2002
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/* set these to define the limits of the server. NOTE These are on a
- per-client basis. Thus any one machine can't connect to more than
- MAX_CONNECTIONS services, but any number of machines may connect at
- one time. */
-#define MAX_CONNECTIONS 128
-
-/****************************************************************************
-init the conn structures
-****************************************************************************/
-void conn_init(struct server_context *smb)
-{
- smb->tree.bmap = bitmap_allocate(MAX_CONNECTIONS);
-}
-
-/****************************************************************************
-check if a snum is in use
-****************************************************************************/
-BOOL conn_snum_used(struct server_context *smb, int snum)
-{
- struct tcon_context *conn;
- for (conn=smb->tree.connections;conn;conn=conn->next) {
- if (conn->service == snum) {
- return(True);
- }
- }
- return(False);
-}
-
-
-/****************************************************************************
-find a conn given a cnum
-****************************************************************************/
-struct tcon_context *conn_find(struct server_context *smb, unsigned cnum)
-{
- int count=0;
- struct tcon_context *conn;
-
- for (conn=smb->tree.connections;conn;conn=conn->next,count++) {
- if (conn->cnum == cnum) {
- if (count > 10) {
- DLIST_PROMOTE(smb->tree.connections, conn);
- }
- return conn;
- }
- }
-
- return NULL;
-}
-
-
-/****************************************************************************
- find first available connection slot, starting from a random position.
-The randomisation stops problems with the server dieing and clients
-thinking the server is still available.
-****************************************************************************/
-struct tcon_context *conn_new(struct server_context *smb)
-{
- TALLOC_CTX *mem_ctx;
- struct tcon_context *conn;
- int i;
-
- i = bitmap_find(smb->tree.bmap, 1);
-
- if (i == -1) {
- DEBUG(1,("ERROR! Out of connection structures\n"));
- return NULL;
- }
-
- mem_ctx = talloc_init("tcon_context[%d]", i);
-
- conn = (struct tcon_context *)talloc(mem_ctx, sizeof(*conn));
- if (!conn) return NULL;
-
- ZERO_STRUCTP(conn);
-
- conn->mem_ctx = mem_ctx;
- conn->cnum = i;
- conn->smb = smb;
-
- bitmap_set(smb->tree.bmap, i);
-
- smb->tree.num_open++;
-
- DLIST_ADD(smb->tree.connections, conn);
-
- return conn;
-}
-
-/****************************************************************************
-close all conn structures
-****************************************************************************/
-void conn_close_all(struct server_context *smb)
-{
- struct tcon_context *conn, *next;
- for (conn=smb->tree.connections;conn;conn=next) {
- next=conn->next;
- close_cnum(conn);
- }
-}
-
-
-#if REWRITE_REMOVED
-/****************************************************************************
-clear a vuid out of the validity cache, and as the 'owner' of a connection.
-****************************************************************************/
-void conn_clear_vuid_cache(struct server_context *smb, uint16 vuid)
-{
- struct tcon_context *conn;
- unsigned int i;
-
- for (conn=smb->tree.connections;conn;conn=conn->next) {
- for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
- if (conn->vuid_cache.list[i] == vuid) {
- conn->vuid_cache.list[i] = UID_FIELD_INVALID;
- }
- }
- }
-}
-#endif
-
-/****************************************************************************
- Free a conn structure.
-****************************************************************************/
-
-void conn_free(struct server_context *smb, struct tcon_context *conn)
-{
- DLIST_REMOVE(smb->tree.connections, conn);
-
- bitmap_clear(smb->tree.bmap, conn->cnum);
- smb->tree.num_open--;
-
- ZERO_STRUCTP(conn);
- SAFE_FREE(conn);
-}
-
diff --git a/source4/smbd/connection.c b/source4/smbd/connection.c
deleted file mode 100644
index 35f5138956..0000000000
--- a/source4/smbd/connection.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- connection claim routines
- Copyright (C) Andrew Tridgell 1998
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-static TDB_CONTEXT *tdb;
-
-
-static void make_conn_key(struct tcon_context *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey)
-{
- ZERO_STRUCTP(pkey);
- pkey->pid = getpid();
- pkey->cnum = conn?conn->cnum:-1;
- fstrcpy(pkey->name, name);
-
- pkbuf->dptr = (char *)pkey;
- pkbuf->dsize = sizeof(*pkey);
-}
-
-/****************************************************************************
- Delete a connection record.
-****************************************************************************/
-
-BOOL yield_connection(struct tcon_context *conn, const char *name)
-{
- struct connections_key key;
- TDB_DATA kbuf;
-
- if (!tdb)
- return False;
-
- DEBUG(3,("Yielding connection to %s\n",name));
-
- make_conn_key(conn, name, &kbuf, &key);
-
- if (tdb_delete(tdb, kbuf) != 0) {
- int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0;
- DEBUG(dbg_lvl,("yield_connection: tdb_delete for name %s failed with error %s.\n",
- name, tdb_errorstr(tdb) ));
- return (False);
- }
-
- return(True);
-}
-
-struct count_stat {
- pid_t mypid;
- int curr_connections;
- char *name;
- BOOL Clear;
-};
-
-/****************************************************************************
- Count the entries belonging to a service in the connection db.
-****************************************************************************/
-
-static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp)
-{
- struct connections_data crec;
- struct count_stat *cs = (struct count_stat *)udp;
-
- if (dbuf.dsize != sizeof(crec))
- return 0;
-
- memcpy(&crec, dbuf.dptr, sizeof(crec));
-
- if (crec.cnum == -1)
- return 0;
-
- /* If the pid was not found delete the entry from connections.tdb */
-
- if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) {
- DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n",
- (unsigned int)crec.pid, crec.cnum, crec.name));
- if (tdb_delete(the_tdb, kbuf) != 0)
- DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) ));
- return 0;
- }
-
- if (strequal(crec.name, cs->name))
- cs->curr_connections++;
-
- return 0;
-}
-
-/****************************************************************************
- Claim an entry in the connections database.
-****************************************************************************/
-
-BOOL claim_connection(struct tcon_context *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
-{
- struct connections_key key;
- struct connections_data crec;
- TDB_DATA kbuf, dbuf;
-
- if (!tdb)
- tdb = tdb_open_log(lock_path(conn->mem_ctx, "connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
- O_RDWR | O_CREAT, 0644);
-
- if (!tdb)
- return False;
-
- /*
- * Enforce the max connections parameter.
- */
-
- if (max_connections > 0) {
- struct count_stat cs;
-
- cs.mypid = getpid();
- cs.curr_connections = 0;
- cs.name = lp_servicename(SNUM(conn));
- cs.Clear = Clear;
-
- /*
- * This has a race condition, but locking the chain before hand is worse
- * as it leads to deadlock.
- */
-
- if (tdb_traverse(tdb, count_fn, &cs) == -1) {
- DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
- tdb_errorstr(tdb) ));
- return False;
- }
-
- if (cs.curr_connections >= max_connections) {
- DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
- max_connections, name ));
- return False;
- }
- }
-
- DEBUG(5,("claiming %s %d\n",name,max_connections));
-
- make_conn_key(conn, name, &kbuf, &key);
-
- /* fill in the crec */
- ZERO_STRUCT(crec);
- crec.magic = 0x280267;
- crec.pid = getpid();
- crec.cnum = conn?conn->cnum:-1;
- if (conn) {
- crec.uid = -1;
- crec.gid = -1;
- StrnCpy(crec.name,
- lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
- }
- crec.start = time(NULL);
- crec.bcast_msg_flags = msg_flags;
-
- StrnCpy(crec.machine,sub_get_remote_machine(),sizeof(crec.machine)-1);
- StrnCpy(crec.addr,conn?conn->smb->socket.client_addr:"NONE",sizeof(crec.addr)-1);
-
- dbuf.dptr = (char *)&crec;
- dbuf.dsize = sizeof(crec);
-
- if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
- DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
- tdb_errorstr(tdb) ));
- return False;
- }
-
- return True;
-}
-
-BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
-{
- struct connections_key key;
- struct connections_data *pcrec;
- TDB_DATA kbuf, dbuf;
-
- if (!tdb)
- return False;
-
- DEBUG(10,("register_message_flags: %s flags 0x%x\n",
- doreg ? "adding" : "removing",
- (unsigned int)msg_flags ));
-
- make_conn_key(NULL, "", &kbuf, &key);
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr) {
- DEBUG(0,("register_message_flags: tdb_fetch failed\n"));
- return False;
- }
-
- pcrec = (struct connections_data *)dbuf.dptr;
- pcrec->bcast_msg_flags = msg_flags;
- if (doreg)
- pcrec->bcast_msg_flags |= msg_flags;
- else
- pcrec->bcast_msg_flags &= ~msg_flags;
-
- if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
- DEBUG(0,("register_message_flags: tdb_store failed with error %s.\n",
- tdb_errorstr(tdb) ));
- SAFE_FREE(dbuf.dptr);
- return False;
- }
-
- DEBUG(10,("register_message_flags: new flags 0x%x\n",
- (unsigned int)pcrec->bcast_msg_flags ));
-
- SAFE_FREE(dbuf.dptr);
- return True;
-}
diff --git a/source4/smbd/negprot.c b/source4/smbd/negprot.c
deleted file mode 100644
index caf3ce33b9..0000000000
--- a/source4/smbd/negprot.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- negprot reply code
- Copyright (C) Andrew Tridgell 1992-1998
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/* initialise the auth_context for this server and return the cryptkey */
-static void get_challenge(struct server_context *smb, char buff[8])
-{
- NTSTATUS nt_status;
- const uint8 *cryptkey;
-
- /* muliple negprots are not premitted */
- if (smb->negotiate.auth_context) {
- DEBUG(3,("get challenge: is this a secondary negprot? auth_context is non-NULL!\n"));
- smb_panic("secondary negprot");
- }
-
- DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
-
- nt_status = make_auth_context_subsystem(&smb->negotiate.auth_context);
-
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
- smb_panic("cannot make_negprot_global_auth_context!\n");
- }
-
- DEBUG(10, ("get challenge: getting challenge\n"));
- cryptkey = smb->negotiate.auth_context->get_ntlm_challenge(smb->negotiate.auth_context);
- memcpy(buff, cryptkey, 8);
-}
-
-/****************************************************************************
- Reply for the core protocol.
-****************************************************************************/
-static void reply_corep(struct request_context *req, uint16 choice)
-{
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), choice);
-
- req->smb->negotiate.protocol = PROTOCOL_CORE;
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply for the coreplus protocol.
-this is quite incomplete - we only fill in a small part of the reply, but as nobody uses
-this any more it probably doesn't matter
-****************************************************************************/
-static void reply_coreplus(struct request_context *req, uint16 choice)
-{
- uint16 raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
-
- req_setup_reply(req, 13, 0);
-
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(req->out.hdr,HDR_FLG,
- CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
-
- SSVAL(req->out.vwv, VWV(0), choice);
- SSVAL(req->out.vwv, VWV(1), 0x1); /* user level security, don't encrypt */
-
- /* tell redirector we support
- readbraw and writebraw (possibly) */
- SSVAL(req->out.vwv, VWV(5), raw);
-
- req->smb->negotiate.protocol = PROTOCOL_COREPLUS;
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply for the lanman 1.0 protocol.
-****************************************************************************/
-static void reply_lanman1(struct request_context *req, uint16 choice)
-{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = req->request_time.tv_sec;
-
- req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
-
- if (lp_security() != SEC_SHARE)
- secword |= NEGOTIATE_SECURITY_USER_LEVEL;
-
- if (req->smb->negotiate.encrypted_passwords)
- secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
-
- req->smb->negotiate.protocol = PROTOCOL_LANMAN1;
-
- req_setup_reply(req, 13, req->smb->negotiate.encrypted_passwords ? 8 : 0);
-
- /* SMBlockread, SMBwritelock supported. */
- SCVAL(req->out.hdr,HDR_FLG,
- CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
-
- SSVAL(req->out.vwv, VWV(0), choice);
- SSVAL(req->out.vwv, VWV(1), secword);
- SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
- SSVAL(req->out.vwv, VWV(3), lp_maxmux());
- SSVAL(req->out.vwv, VWV(4), 1);
- SSVAL(req->out.vwv, VWV(5), raw);
- SIVAL(req->out.vwv, VWV(6), req->smb->pid);
- put_dos_date(req->out.vwv, VWV(8), t);
- SSVAL(req->out.vwv, VWV(10), TimeDiff(t)/60);
-
- /* Create a token value and add it to the outgoing packet. */
- if (req->smb->negotiate.encrypted_passwords) {
- SSVAL(req->out.vwv, VWV(11), 8);
- get_challenge(req->smb, req->out.data);
- }
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply for the lanman 2.0 protocol.
-****************************************************************************/
-static void reply_lanman2(struct request_context *req, uint16 choice)
-{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = req->request_time.tv_sec;
-
- req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
-
- if (lp_security() != SEC_SHARE)
- secword |= NEGOTIATE_SECURITY_USER_LEVEL;
-
- if (req->smb->negotiate.encrypted_passwords)
- secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
-
- req->smb->negotiate.protocol = PROTOCOL_LANMAN2;
-
- req_setup_reply(req, 13, 0);
-
- SSVAL(req->out.vwv, VWV(0), choice);
- SSVAL(req->out.vwv, VWV(1), secword);
- SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
- SSVAL(req->out.vwv, VWV(3), lp_maxmux());
- SSVAL(req->out.vwv, VWV(4), 1);
- SSVAL(req->out.vwv, VWV(5), raw);
- SIVAL(req->out.vwv, VWV(6), req->smb->pid);
- put_dos_date(req->out.vwv, VWV(8), t);
- SSVAL(req->out.vwv, VWV(10), TimeDiff(t)/60);
-
- /* Create a token value and add it to the outgoing packet. */
- if (req->smb->negotiate.encrypted_passwords) {
- SSVAL(req->out.vwv, VWV(11), 8);
- req_grow_data(req, 8);
- get_challenge(req->smb, req->out.data);
- }
-
- req_push_str(req, NULL, lp_workgroup(), -1, STR_TERMINATE);
-
- req_send_reply(req);
-}
-
-
-#if 0
-/****************************************************************************
- Generate the spnego negprot reply blob. Return the number of bytes used.
-****************************************************************************/
-static DATA_BLOB negprot_spnego(struct server_context *smb)
-{
- DATA_BLOB blob;
- uint8 guid[16];
- const char *OIDs_krb5[] = {OID_KERBEROS5,
- OID_KERBEROS5_OLD,
- OID_NTLMSSP,
- NULL};
- const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
- char *principal;
-
- smb->negotiate.spnego_negotiated = True;
-
- memset(guid, 0, 16);
- safe_strcpy((char *)guid, lp_netbios_name(), 16);
- strlower((char *)guid);
-
-#if 0
- /* strangely enough, NT does not send the single OID NTLMSSP when
- not a ADS member, it sends no OIDs at all
-
- we can't do this until we teach our sesssion setup parser to know
- about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
- */
- if (lp_security() != SEC_ADS) {
- memcpy(p, guid, 16);
- return 16;
- }
-#endif
- if (lp_security() != SEC_ADS) {
- blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
- } else {
- asprintf(&principal, "%s$@%s", guid, lp_realm());
- blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
- free(principal);
- }
-
- return blob;
-}
-#endif
-
-/****************************************************************************
- Reply for the nt protocol.
-****************************************************************************/
-static void reply_nt1(struct request_context *req, uint16 choice)
-{
- /* dual names + lock_and_read + nt SMBs + remote API calls */
- int capabilities;
- int secword=0;
- time_t t = req->request_time.tv_sec;
- BOOL negotiate_spnego = False;
-
- capabilities =
- CAP_NT_FIND | CAP_LOCK_AND_READ |
- CAP_LEVEL_II_OPLOCKS | CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
-
- req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
-
- /* do spnego in user level security if the client
- supports it and we can do encrypted passwords */
-
- if (req->smb->negotiate.encrypted_passwords &&
- (lp_security() != SEC_SHARE) &&
- lp_use_spnego() &&
- (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
-/* REWRITE negotiate_spnego = True;
- capabilities |= CAP_EXTENDED_SECURITY;
-*/
- }
-
- if (lp_unix_extensions()) {
- capabilities |= CAP_UNIX;
- }
-
- if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
- capabilities |= CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS;
- }
-
- if (SMB_OFF_T_BITS >= 64) {
- capabilities |= CAP_LARGE_FILES;
- }
-
- if (lp_readraw() && lp_writeraw()) {
- capabilities |= CAP_RAW_MODE;
- }
-
- /* allow for disabling unicode */
- if (lp_unicode()) {
- capabilities |= CAP_UNICODE;
- }
-
- if (lp_nt_status_support()) {
- capabilities |= CAP_STATUS32;
- }
-
- if (lp_host_msdfs()) {
- capabilities |= CAP_DFS;
- }
-
- if (lp_security() != SEC_SHARE) {
- secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- }
-
- if (req->smb->negotiate.encrypted_passwords) {
- secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- }
-
- req->smb->negotiate.protocol = PROTOCOL_NT1;
-
- req_setup_reply(req, 17, 0);
-
- SSVAL(req->out.vwv, VWV(0), choice);
- SCVAL(req->out.vwv, VWV(1), secword);
-
- /* notice the strange +1 on vwv here? That's because
- this is the one and only SMB packet that is malformed in
- the specification - all the command words after the secword
- are offset by 1 byte */
- SSVAL(req->out.vwv+1, VWV(1), lp_maxmux());
- SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */
- SIVAL(req->out.vwv+1, VWV(3), req->smb->negotiate.max_recv);
- SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */
- SIVAL(req->out.vwv+1, VWV(7), req->smb->pid); /* session key */
- SIVAL(req->out.vwv+1, VWV(9), capabilities);
- put_long_date(req->out.vwv + VWV(11) + 1, t);
- SSVALS(req->out.vwv+1,VWV(15), TimeDiff(t)/60);
-
- if (!negotiate_spnego) {
- /* Create a token value and add it to the outgoing packet. */
- if (req->smb->negotiate.encrypted_passwords) {
- req_grow_data(req, 8);
- /* note that we do not send a challenge at all if
- we are using plaintext */
- get_challenge(req->smb, req->out.ptr);
- req->out.ptr += 8;
- SCVAL(req->out.vwv+1, VWV(16), 8);
- }
- req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
- DEBUG(3,("not using SPNEGO\n"));
- } else {
-#if 0
- DATA_BLOB blob = negprot_spnego(req->smb);
-
- req_grow_data(req, blob.length);
- memcpy(req->out.ptr, blob.data, blob.length);
- DEBUG(3,("using SPNEGO\n"));
-#else
- exit_server(req->smb, "no SPNEGO please");
-#endif
- }
-
- req_send_reply(req);
-}
-
-/* these are the protocol lists used for auto architecture detection:
-
-WinNT 3.51:
-protocol [PC NETWORK PROGRAM 1.0]
-protocol [XENIX CORE]
-protocol [MICROSOFT NETWORKS 1.03]
-protocol [LANMAN1.0]
-protocol [Windows for Workgroups 3.1a]
-protocol [LM1.2X002]
-protocol [LANMAN2.1]
-protocol [NT LM 0.12]
-
-Win95:
-protocol [PC NETWORK PROGRAM 1.0]
-protocol [XENIX CORE]
-protocol [MICROSOFT NETWORKS 1.03]
-protocol [LANMAN1.0]
-protocol [Windows for Workgroups 3.1a]
-protocol [LM1.2X002]
-protocol [LANMAN2.1]
-protocol [NT LM 0.12]
-
-Win2K:
-protocol [PC NETWORK PROGRAM 1.0]
-protocol [LANMAN1.0]
-protocol [Windows for Workgroups 3.1a]
-protocol [LM1.2X002]
-protocol [LANMAN2.1]
-protocol [NT LM 0.12]
-
-OS/2:
-protocol [PC NETWORK PROGRAM 1.0]
-protocol [XENIX CORE]
-protocol [LANMAN1.0]
-protocol [LM1.2X002]
-protocol [LANMAN2.1]
-*/
-
-/*
- * Modified to recognize the architecture of the remote machine better.
- *
- * This appears to be the matrix of which protocol is used by which
- * MS product.
- Protocol WfWg Win95 WinNT Win2K OS/2
- PC NETWORK PROGRAM 1.0 1 1 1 1 1
- XENIX CORE 2 2
- MICROSOFT NETWORKS 3.0 2 2
- DOS LM1.2X002 3 3
- MICROSOFT NETWORKS 1.03 3
- DOS LANMAN2.1 4 4
- LANMAN1.0 4 2 3
- Windows for Workgroups 3.1a 5 5 5 3
- LM1.2X002 6 4 4
- LANMAN2.1 7 5 5
- NT LM 0.12 6 8 6
- *
- * tim@fsg.com 09/29/95
- * Win2K added by matty 17/7/99
- */
-
-#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
-#define ARCH_WIN95 0x2
-#define ARCH_WINNT 0x4
-#define ARCH_WIN2K 0xC /* Win2K is like NT */
-#define ARCH_OS2 0x14 /* Again OS/2 is like NT */
-#define ARCH_SAMBA 0x20
-
-#define ARCH_ALL 0x3F
-
-/* List of supported protocols, most desired first */
-static const struct {
- const char *proto_name;
- const char *short_name;
- void (*proto_reply_fn)(struct request_context *req, uint16 choice);
- int protocol_level;
-} supported_protocols[] = {
- {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
- {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
- {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
- {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
- {NULL,NULL,NULL,0},
-};
-
-/****************************************************************************
- Reply to a negprot.
-****************************************************************************/
-
-void reply_negprot(struct request_context *req)
-{
- int Index=0;
- int choice = -1;
- int protocol;
- char *p;
- int arch = ARCH_ALL;
-
- if (req->smb->negotiate.done_negprot) {
- exit_server(req->smb, "multiple negprot's are not permitted");
- }
- req->smb->negotiate.done_negprot = True;
-
- p = req->in.data + 1;
-
- while (p < req->in.data + req->in.data_size) {
- Index++;
- DEBUG(3,("Requested protocol [%s]\n",p));
- if (strcmp(p,"Windows for Workgroups 3.1a") == 0)
- arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcmp(p,"DOS LM1.2X002") == 0)
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcmp(p,"DOS LANMAN2.1") == 0)
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcmp(p,"NT LM 0.12") == 0)
- arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcmp(p,"LANMAN2.1") == 0)
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcmp(p,"LM1.2X002") == 0)
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcmp(p,"MICROSOFT NETWORKS 1.03") == 0)
- arch &= ARCH_WINNT;
- else if (strcmp(p,"XENIX CORE") == 0)
- arch &= ( ARCH_WINNT | ARCH_OS2 );
- else if (strcmp(p,"Samba") == 0) {
- arch = ARCH_SAMBA;
- break;
- }
-
- p += strlen(p) + 2;
- }
-
- switch (arch) {
- case ARCH_SAMBA:
- set_remote_arch(req->smb, RA_SAMBA);
- break;
- case ARCH_WFWG:
- set_remote_arch(req->smb, RA_WFWG);
- break;
- case ARCH_WIN95:
- set_remote_arch(req->smb, RA_WIN95);
- break;
- case ARCH_WINNT:
- if (req->flags2==FLAGS2_WIN2K_SIGNATURE)
- set_remote_arch(req->smb, RA_WIN2K);
- else
- set_remote_arch(req->smb, RA_WINNT);
- break;
- case ARCH_WIN2K:
- set_remote_arch(req->smb, RA_WIN2K);
- break;
- case ARCH_OS2:
- set_remote_arch(req->smb, RA_OS2);
- break;
- default:
- set_remote_arch(req->smb, RA_UNKNOWN);
- break;
- }
-
- /* possibly reload - change of architecture */
- reload_services(req->smb, True);
-
- /* Check for protocols, most desirable first */
- for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
- p = req->in.data+1;
- Index = 0;
- if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
- (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
- while (p < (req->in.data + req->in.data_size)) {
- if (strequal(p,supported_protocols[protocol].proto_name))
- choice = Index;
- Index++;
- p += strlen(p) + 2;
- }
- if(choice != -1)
- break;
- }
-
- if(choice != -1) {
- sub_set_remote_proto(supported_protocols[protocol].short_name);
- reload_services(req->smb, True);
- supported_protocols[protocol].proto_reply_fn(req, choice);
- DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
- } else {
- DEBUG(0,("No protocol supported !\n"));
- }
-
- DEBUG(5,("negprot index=%d\n", choice));
-}
diff --git a/source4/smbd/nttrans.c b/source4/smbd/nttrans.c
deleted file mode 100644
index 13afdeeea2..0000000000
--- a/source4/smbd/nttrans.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NT transaction handling
- Copyright (C) Andrew Tridgell 2003
- Copyright (C) James J Myers 2003 <myersjj@samba.org>
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/*
- This file handles the parsing of transact2 requests
-*/
-
-#include "includes.h"
-
-
-#define CHECK_MIN_BLOB_SIZE(blob, size) do { \
- if ((blob)->length < (size)) { \
- return NT_STATUS_INFO_LENGTH_MISMATCH; \
- }} while (0)
-
-
-/* setup a nttrans reply, given the data and params sizes */
-static void nttrans_setup_reply(struct request_context *req,
- struct smb_nttrans *trans,
- uint16 param_size, uint16 data_size,
- uint16 setup_count)
-{
- trans->out.setup_count = setup_count;
- if (setup_count != 0) {
- trans->out.setup = talloc_zero(req->mem_ctx, sizeof(uint16) * setup_count);
- }
- trans->out.params = data_blob_talloc(req->mem_ctx, NULL, param_size);
- trans->out.data = data_blob_talloc(req->mem_ctx, NULL, data_size);
-}
-
-
-/* parse NTTRANS_CREATE request
- */
-static NTSTATUS nttrans_create(struct request_context *req,
- struct smb_nttrans *trans)
-{
- return NT_STATUS_FOOBAR;
-}
-
-/* parse NTTRANS_RENAME request
- */
-static NTSTATUS nttrans_rename(struct request_context *req,
- struct smb_nttrans *trans)
-{
- return NT_STATUS_FOOBAR;
-}
-/* parse NTTRANS_IOCTL request
- */
-static NTSTATUS nttrans_ioctl(struct request_context *req,
- struct smb_nttrans *trans)
-{
- union smb_ioctl nt;
- uint32 function;
- uint16 fnum;
- uint8 filter;
- BOOL fsctl;
- DATA_BLOB *blob;
-
- /* should have at least 4 setup words */
- if (trans->in.setup_count != 4) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- function = IVAL(trans->in.setup, 0);
- fnum = SVAL(trans->in.setup, 4);
- fsctl = CVAL(trans->in.setup, 6);
- filter = CVAL(trans->in.setup, 7);
-
- blob = &trans->in.data;
-
- nt.ntioctl.level = RAW_IOCTL_NTIOCTL;
- nt.ntioctl.in.fnum = fnum;
- nt.ntioctl.in.function = function;
- nt.ntioctl.in.fsctl = fsctl;
- nt.ntioctl.in.filter = filter;
-
- nttrans_setup_reply(req, trans, 0, 0, 1);
- trans->out.setup[0] = 0;
-
- return req->conn->ntvfs_ops->ioctl(req, &nt);
-}
-
-/*
- backend for nttrans requests
-*/
-static NTSTATUS nttrans_backend(struct request_context *req,
- struct smb_nttrans *trans)
-{
- DEBUG(9,("nttrans_backend: setup_count=%d function=%d\n",
- trans->in.setup_count, trans->in.function));
- /* must have at least one setup word */
- if (trans->in.setup_count < 1) {
- return NT_STATUS_FOOBAR;
- }
-
- /* the nttrans command is in function */
- switch (trans->in.function) {
- case NT_TRANSACT_CREATE:
- return nttrans_create(req, trans);
- case NT_TRANSACT_IOCTL:
- return nttrans_ioctl(req, trans);
- case NT_TRANSACT_RENAME:
- return nttrans_rename(req, trans);
- }
-
- /* an unknown nttrans command */
- return NT_STATUS_FOOBAR;
-}
-
-
-/****************************************************************************
- Reply to an SMBnttrans request
-****************************************************************************/
-void reply_nttrans(struct request_context *req)
-{
- struct smb_nttrans trans;
- int i;
- uint16 param_ofs, data_ofs;
- uint16 param_count, data_count;
- uint16 params_left, data_left;
- uint16 param_total, data_total;
- char *params, *data;
- NTSTATUS status;
-
- /* parse request */
- if (req->in.wct < 19) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- trans.in.max_setup = CVAL(req->in.vwv, 0);
- param_total = IVAL(req->in.vwv, 3);
- data_total = IVAL(req->in.vwv, 7);
- trans.in.max_param = IVAL(req->in.vwv, 11);
- trans.in.max_data = IVAL(req->in.vwv, 15);
- param_count = IVAL(req->in.vwv, 19);
- param_ofs = IVAL(req->in.vwv, 23);
- data_count = IVAL(req->in.vwv, 27);
- data_ofs = IVAL(req->in.vwv, 31);
- trans.in.setup_count = CVAL(req->in.vwv, 35);
- trans.in.function = SVAL(req->in.vwv, 36);
-
- if (req->in.wct != 19 + trans.in.setup_count) {
- req_reply_dos_error(req, ERRSRV, ERRerror);
- return;
- }
-
- /* parse out the setup words */
- trans.in.setup = talloc(req->mem_ctx, trans.in.setup_count * sizeof(uint16));
- if (!trans.in.setup) {
- req_reply_error(req, NT_STATUS_NO_MEMORY);
- return;
- }
- for (i=0;i<trans.in.setup_count;i++) {
- trans.in.setup[i] = SVAL(req->in.vwv, VWV(19+i));
- }
-
- if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans.in.params) ||
- !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans.in.data)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- /* is it a partial request? if so, then send a 'send more' message */
- if (param_total > param_count ||
- data_total > data_count) {
- DEBUG(0,("REWRITE: not handling partial nttrans requests!\n"));
- return;
- }
-
- /* its a full request, give it to the backend */
- status = nttrans_backend(req, &trans);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- params_left = trans.out.params.length;
- data_left = trans.out.data.length;
- params = trans.out.params.data;
- data = trans.out.data.data;
-
- req->control_flags |= REQ_CONTROL_PROTECTED;
-
- /* we need to divide up the reply into chunks that fit into
- the negotiated buffer size */
- do {
- uint16 this_data, this_param, max_bytes;
- uint_t align1 = 1, align2 = (params_left ? 2 : 0);
-
- req_setup_reply(req, 18 + trans.out.setup_count, 0);
-
- max_bytes = req_max_data(req) - (align1 + align2);
-
- this_param = params_left;
- if (this_param > max_bytes) {
- this_param = max_bytes;
- }
- max_bytes -= this_param;
-
- this_data = data_left;
- if (this_data > max_bytes) {
- this_data = max_bytes;
- }
-
- req_grow_data(req, this_param + this_data + (align1 + align2));
-
- SIVAL(req->out.vwv, 3, trans.out.params.length);
- SIVAL(req->out.vwv, 7, trans.out.data.length);
-
- SIVAL(req->out.vwv, 11, this_param);
- SIVAL(req->out.vwv, 15, align1 + PTR_DIFF(req->out.data, req->out.hdr));
- SIVAL(req->out.vwv, 19, PTR_DIFF(params, trans.out.params.data));
-
- SIVAL(req->out.vwv, 23, this_data);
- SIVAL(req->out.vwv, 27, align1 + align2 +
- PTR_DIFF(req->out.data + this_param, req->out.hdr));
- SIVAL(req->out.vwv, 31, PTR_DIFF(data, trans.out.data.data));
-
- SCVAL(req->out.vwv, 35, trans.out.setup_count);
- for (i=0;i<trans.out.setup_count;i++) {
- SSVAL(req->out.vwv, VWV(18+i)+1, trans.out.setup[i]);
- }
-
- memset(req->out.data, 0, align1);
- if (this_param != 0) {
- memcpy(req->out.data + align1, params, this_param);
- }
- memset(req->out.data+this_param+align1, 0, align2);
- if (this_data != 0) {
- memcpy(req->out.data+this_param+align1+align2, data, this_data);
- }
-
- params_left -= this_param;
- data_left -= this_data;
- params += this_param;
- data += this_data;
-
- /* if this is the last chunk then the request can be destroyed */
- if (params_left == 0 && data_left == 0) {
- req->control_flags &= ~REQ_CONTROL_PROTECTED;
- }
-
- req_send_reply(req);
- } while (params_left != 0 || data_left != 0);
-}
-
-
-/****************************************************************************
- Reply to an SMBnttranss request
-****************************************************************************/
-void reply_nttranss(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
diff --git a/source4/smbd/password.c b/source4/smbd/password.c
deleted file mode 100644
index 53530abf7a..0000000000
--- a/source4/smbd/password.c
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Password and authentication handling
- Copyright (C) Andrew Tridgell 1992-1998
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-
-/****************************************************************************
-check if a uid has been validated, and return an pointer to the user_struct
-if it has. NULL if not. vuid is biased by an offset. This allows us to
-tell random client vuid's (normally zero) from valid vuids.
-****************************************************************************/
-struct user_struct *get_valid_user_struct(struct server_context *smb, uint16 vuid)
-{
- user_struct *usp;
- int count=0;
-
- if (vuid == UID_FIELD_INVALID)
- return NULL;
-
- for (usp=smb->users.validated_users;usp;usp=usp->next,count++) {
- if (vuid == usp->vuid) {
- if (count > 10) {
- DLIST_PROMOTE(smb->users.validated_users, usp);
- }
- return usp;
- }
- }
-
- return NULL;
-}
-
-/****************************************************************************
-invalidate a uid
-****************************************************************************/
-void invalidate_vuid(struct server_context *smb, uint16 vuid)
-{
- user_struct *vuser = get_valid_user_struct(smb, vuid);
-
- if (vuser == NULL)
- return;
-
- SAFE_FREE(vuser->homedir);
- SAFE_FREE(vuser->unix_homedir);
- SAFE_FREE(vuser->logon_script);
-
- session_yield(vuser);
-
- free_server_info(&vuser->server_info);
-
- DLIST_REMOVE(smb->users.validated_users, vuser);
-
- /* clear the vuid from the 'cache' on each connection, and
- from the vuid 'owner' of connections */
- /* REWRITE: conn_clear_vuid_cache(smb, vuid); */
-
- SAFE_FREE(vuser->groups);
- delete_nt_token(&vuser->nt_user_token);
- SAFE_FREE(vuser);
- smb->users.num_validated_vuids--;
-}
-
-/****************************************************************************
-invalidate all vuid entries for this process
-****************************************************************************/
-void invalidate_all_vuids(struct server_context *smb)
-{
- user_struct *usp, *next=NULL;
-
- for (usp=smb->users.validated_users;usp;usp=next) {
- next = usp->next;
-
- invalidate_vuid(smb, usp->vuid);
- }
-}
-
-/**
- * register that a valid login has been performed, establish 'session'.
- * @param server_info The token returned from the authentication process.
- * (now 'owned' by register_vuid)
- *
- * @return Newly allocated vuid, biased by an offset. (This allows us to
- * tell random client vuid's (normally zero) from valid vuids.)
- *
- */
-
-int register_vuid(struct server_context *smb,
- struct auth_serversupplied_info *server_info,
- const char *smb_name)
-{
- user_struct *vuser = NULL;
-
- /* Ensure no vuid gets registered in share level security. */
- if(lp_security() == SEC_SHARE)
- return UID_FIELD_INVALID;
-
- /* Limit allowed vuids to 16bits - VUID_OFFSET. */
- if (smb->users.num_validated_vuids >= 0xFFFF-VUID_OFFSET)
- return UID_FIELD_INVALID;
-
- if((vuser = (user_struct *)malloc( sizeof(user_struct) )) == NULL) {
- DEBUG(0,("Failed to malloc users struct!\n"));
- return UID_FIELD_INVALID;
- }
-
- ZERO_STRUCTP(vuser);
-
- /* Allocate a free vuid. Yes this is a linear search... :-) */
- while (get_valid_user_struct(smb, smb->users.next_vuid) != NULL ) {
- smb->users.next_vuid++;
- /* Check for vuid wrap. */
- if (smb->users.next_vuid == UID_FIELD_INVALID)
- smb->users.next_vuid = VUID_OFFSET;
- }
-
- DEBUG(10,("register_vuid: allocated vuid = %u\n",
- (unsigned int)smb->users.next_vuid));
-
- vuser->vuid = smb->users.next_vuid;
-
- /* the next functions should be done by a SID mapping system (SMS) as
- * the new real sam db won't have reference to unix uids or gids
- */
- if (!IS_SAM_UNIX_USER(server_info->sam_account)) {
- DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n"));
- free(vuser);
- free_server_info(&server_info);
- return UID_FIELD_INVALID;
- }
-
- vuser->uid = pdb_get_uid(server_info->sam_account);
- vuser->gid = pdb_get_gid(server_info->sam_account);
-
- vuser->n_groups = server_info->n_groups;
- if (vuser->n_groups) {
- if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
- DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
- free(vuser);
- free_server_info(&server_info);
- return UID_FIELD_INVALID;
- }
- }
-
- vuser->guest = server_info->guest;
- fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account));
-
- /* This is a potentially untrusted username */
- alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));
-
- fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
- fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
-
- {
- /* Keep the homedir handy */
- const char *homedir = pdb_get_homedir(server_info->sam_account);
- const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
- const char *logon_script = pdb_get_logon_script(server_info->sam_account);
- if (homedir) {
- vuser->homedir = smb_xstrdup(homedir);
- }
-
- if (unix_homedir) {
- vuser->unix_homedir = smb_xstrdup(unix_homedir);
- }
-
- if (logon_script) {
- vuser->logon_script = smb_xstrdup(logon_script);
- }
- }
-
- memcpy(vuser->session_key, server_info->session_key, sizeof(vuser->session_key));
-
- DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n",
- (unsigned int)vuser->uid,
- (unsigned int)vuser->gid,
- vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest ));
-
- DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));
-
- if (server_info->ptok) {
- vuser->nt_user_token = dup_nt_token(server_info->ptok);
- } else {
- DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
- free_server_info(&server_info);
- SAFE_FREE(vuser->homedir);
- SAFE_FREE(vuser->unix_homedir);
- SAFE_FREE(vuser->logon_script);
-
- SAFE_FREE(vuser);
- return UID_FIELD_INVALID;
- }
-
- /* use this to keep tabs on all our info from the authentication */
- vuser->server_info = server_info;
-
- DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
-
- smb->users.next_vuid++;
- smb->users.num_validated_vuids++;
-
- DLIST_ADD(smb->users.validated_users, vuser);
-
- if (!session_claim(smb, vuser)) {
- DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));
- invalidate_vuid(smb, vuser->vuid);
- return -1;
- }
-
- /* Register a home dir service for this user */
- if ((!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) {
- DEBUG(3, ("Adding/updating homes service for user '%s' using home direcotry: '%s'\n",
- vuser->user.unix_name, vuser->unix_homedir));
- vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir);
- } else {
- vuser->homes_snum = -1;
- }
-
- return vuser->vuid;
-}
-
-
-/****************************************************************************
-add a name to the session users list
-****************************************************************************/
-void add_session_user(struct server_context *smb, const char *user)
-{
- char *suser;
- struct passwd *passwd;
-
- if (!(passwd = Get_Pwnam(user))) return;
-
- suser = strdup(passwd->pw_name);
- if (!suser) {
- return;
- }
-
- if (suser && *suser && !in_list(suser,smb->users.session_users,False)) {
- char *p;
- if (!smb->users.session_users) {
- asprintf(&p, "%s", suser);
- } else {
- asprintf(&p, "%s %s", smb->users.session_users, suser);
- }
- SAFE_FREE(smb->users.session_users);
- smb->users.session_users = p;
- }
-
- free(suser);
-}
-
-
-/****************************************************************************
-check if a username is valid
-****************************************************************************/
-BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
-{
- char **valid, **invalid;
- BOOL ret;
-
- valid = invalid = NULL;
- ret = True;
-
- if (lp_invalid_users(snum)) {
- str_list_copy(&invalid, lp_invalid_users(snum));
- if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) {
- ret = !user_in_list(user, (const char **)invalid, groups, n_groups);
- }
- }
- if (invalid)
- str_list_free (&invalid);
-
- if (ret && lp_valid_users(snum)) {
- str_list_copy(&valid, lp_valid_users(snum));
- if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) {
- ret = user_in_list(user, (const char **)valid, groups, n_groups);
- }
- }
- if (valid)
- str_list_free (&valid);
-
- if (ret && lp_onlyuser(snum)) {
- char **user_list = str_list_make (lp_username(snum), NULL);
- if (user_list && str_list_substitute(user_list, "%S", lp_servicename(snum))) {
- ret = user_in_list(user, (const char **)user_list, groups, n_groups);
- }
- if (user_list) str_list_free (&user_list);
- }
-
- return(ret);
-}
-
-/****************************************************************************
-validate a group username entry. Return the username or NULL
-****************************************************************************/
-static const char *validate_group(struct server_context *smb, const char *group, DATA_BLOB password,int snum)
-{
-#ifdef HAVE_NETGROUP
- {
- char *host, *user, *domain;
- setnetgrent(group);
- while (getnetgrent(&host, &user, &domain)) {
- if (user) {
- if (user_ok(user, snum, NULL, 0) &&
- password_ok(smb, user,password)) {
- endnetgrent();
- return(user);
- }
- }
- }
- endnetgrent();
- }
-#endif
-
-#ifdef HAVE_GETGRENT
- {
- struct group *gptr;
- setgrent();
- while ((gptr = (struct group *)getgrent())) {
- if (strequal(gptr->gr_name,group))
- break;
- }
-
- /*
- * As user_ok can recurse doing a getgrent(), we must
- * copy the member list into a pstring on the stack before
- * use. Bug pointed out by leon@eatworms.swmed.edu.
- */
-
- if (gptr) {
- pstring member_list;
- char *member;
- size_t copied_len = 0;
- int i;
-
- *member_list = '\0';
- member = member_list;
-
- for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
- size_t member_len = strlen(gptr->gr_mem[i]) + 1;
- if( copied_len + member_len < sizeof(pstring)) {
-
- DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i]));
-
- safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1);
- copied_len += member_len;
- member += copied_len;
- } else {
- *member = '\0';
- }
- }
-
- endgrent();
-
- member = member_list;
- while (*member) {
- const char *name = member;
- if (user_ok(name,snum, NULL, 0) &&
- password_ok(smb,name,password)) {
- endgrent();
- return(&name[0]);
- }
-
- DEBUG(10,("validate_group = member = %s\n", member));
-
- member += strlen(member) + 1;
- }
- } else {
- endgrent();
- return NULL;
- }
- }
-#endif
- return(NULL);
-}
-
-/****************************************************************************
- Check for authority to login to a service with a given username/password.
- Note this is *NOT* used when logging on using sessionsetup_and_X.
-****************************************************************************/
-
-BOOL authorise_login(struct server_context *smb,
- int snum, const char *user, DATA_BLOB password,
- BOOL *guest)
-{
- BOOL ok = False;
-
-#if DEBUG_PASSWORD
- DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n",
- user,password.data));
-#endif
-
- *guest = False;
-
- /* there are several possibilities:
- 1) login as the given user with given password
- 2) login as a previously registered username with the given password
- 3) login as a session list username with the given password
- 4) login as a previously validated user/password pair
- 5) login as the "user =" user with given password
- 6) login as the "user =" user with no password (guest connection)
- 7) login as guest user with no password
-
- if the service is guest_only then steps 1 to 5 are skipped
- */
-
- /* now check the list of session users */
- if (!ok) {
- char *auser;
- char *user_list = strdup(smb->users.session_users);
- if (!user_list)
- return(False);
-
- for (auser=strtok(user_list,LIST_SEP); !ok && auser;
- auser = strtok(NULL,LIST_SEP)) {
- const char *user2 = auser;
-
- if (!user_ok(user2,snum, NULL, 0))
- continue;
-
- if (password_ok(smb, user2,password)) {
- ok = True;
- DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \
-and given password ok\n", user2));
- }
- }
-
- SAFE_FREE(user_list);
- }
-
- /* check the user= fields and the given password */
- if (!ok && lp_username(snum)) {
- const char *auser;
- pstring user_list;
- StrnCpy(user_list,lp_username(snum),sizeof(pstring));
-
- pstring_sub(user_list,"%S",lp_servicename(snum));
-
- for (auser=strtok(user_list,LIST_SEP); auser && !ok;
- auser = strtok(NULL,LIST_SEP)) {
- if (*auser == '@') {
- auser = validate_group(smb, auser+1,password,snum);
- if (auser) {
- ok = True;
- DEBUG(3,("authorise_login: ACCEPTED: group username \
-and given password ok (%s)\n", auser));
- }
- } else {
- const char *user2 = auser;
- if (user_ok(user2,snum, NULL, 0) && password_ok(smb, user2,password)) {
- ok = True;
- DEBUG(3,("authorise_login: ACCEPTED: user list username \
-and given password ok (%s)\n", user2));
- }
- }
- }
- }
-
- /* check for a normal guest connection */
- if (!ok && GUEST_OK(snum)) {
- const char *guestname = lp_guestaccount();
- if (Get_Pwnam(guestname)) {
- ok = True;
- DEBUG(3,("authorise_login: ACCEPTED: guest account and guest ok (%s)\n", guestname));
- } else {
- DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname));
- }
- *guest = True;
- }
-
- if (ok && !user_ok(user, snum, NULL, 0)) {
- DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
- ok = False;
- }
-
- return(ok);
-}
diff --git a/source4/smbd/process.c b/source4/smbd/process.c
index f3ca69ea32..38f76417f6 100644
--- a/source4/smbd/process.c
+++ b/source4/smbd/process.c
@@ -21,754 +21,6 @@
#include "includes.h"
-
-/*
- send an oplock break request to a client
-*/
-BOOL req_send_oplock_break(struct tcon_context *conn, uint16 fnum, uint8 level)
-{
- struct request_context *req;
-
- req = init_smb_request(conn->smb);
-
- req_setup_reply(req, 8, 0);
-
- SCVAL(req->out.hdr,HDR_COM,SMBlockingX);
- SSVAL(req->out.hdr,HDR_TID,conn->cnum);
- SSVAL(req->out.hdr,HDR_PID,0xFFFF);
- SSVAL(req->out.hdr,HDR_UID,0);
- SSVAL(req->out.hdr,HDR_MID,0xFFFF);
- SCVAL(req->out.hdr,HDR_FLG,0);
- SSVAL(req->out.hdr,HDR_FLG2,0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), fnum);
- SSVAL(req->out.vwv, VWV(3), level);
- SIVAL(req->out.vwv, VWV(4), 0);
- SSVAL(req->out.vwv, VWV(6), 0);
- SSVAL(req->out.vwv, VWV(7), 0);
-
- req_send_reply(req);
- return True;
-}
-
-/****************************************************************************
-receive a SMB request from the wire, forming a request_context from the result
-****************************************************************************/
-static struct request_context *receive_smb_request(struct server_context *smb)
-{
- ssize_t len, len2;
- char header[4];
- struct request_context *req;
-
- len = read_data(smb->socket.fd, header, 4);
- if (len != 4) {
- return NULL;
- }
-
- len = smb_len(header);
-
- req = init_smb_request(smb);
-
- GetTimeOfDay(&req->request_time);
- req->chained_fnum = -1;
-
- /* allocate the incoming buffer at the right size */
- req->in.buffer = talloc(req->mem_ctx, len + NBT_HDR_SIZE);
-
- /* fill in the already received header */
- memcpy(req->in.buffer, header, 4);
-
- len2 = read_data(smb->socket.fd, req->in.buffer + NBT_HDR_SIZE, len);
- if (len2 != len) {
- return NULL;
- }
-
- /* fill in the rest of the req->in structure */
- req->in.size = len + NBT_HDR_SIZE;
- req->in.allocated = req->in.size;
- req->in.hdr = req->in.buffer + NBT_HDR_SIZE;
- req->in.vwv = req->in.hdr + HDR_VWV;
- req->in.wct = CVAL(req->in.hdr, HDR_WCT);
- if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) {
- req->in.data = req->in.vwv + VWV(req->in.wct) + 2;
- req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
-
- /* the bcc length is only 16 bits, but some packets
- (such as SMBwriteX) can be much larger than 64k. We
- detect this by looking for a large non-chained NBT
- packet (at least 64k bigger than what is
- specified). If it is detected then the NBT size is
- used instead of the bcc size */
- if (req->in.data_size + 0x10000 <=
- req->in.size - PTR_DIFF(req->in.data, req->in.buffer) &&
- (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE)) {
- /* its an oversized packet! fun for all the family */
- req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer);
- }
- }
-
- return req;
-}
-
-/*
- setup the user_ctx element of a request
-*/
-static void setup_user_context(struct request_context *req)
-{
- struct user_context *ctx;
-
- ctx = talloc(req->mem_ctx, sizeof(*ctx));
- ctx->vuid = SVAL(req->in.hdr, HDR_UID);
- ctx->vuser = get_valid_user_struct(req->smb, ctx->vuid);
-
- req->user_ctx = ctx;
-}
-
-
-/*
-These flags determine some of the permissions required to do an operation
-
-Note that I don't set NEED_WRITE on some write operations because they
-are used by some brain-dead clients when printing, and I don't want to
-force write permissions on print services.
-*/
-#define AS_USER (1<<0)
-#define NEED_WRITE (1<<1)
-#define TIME_INIT (1<<2)
-#define CAN_IPC (1<<3)
-#define AS_GUEST (1<<5)
-#define USE_MUTEX (1<<7)
-
-/*
- define a list of possible SMB messages and their corresponding
- functions. Any message that has a NULL function is unimplemented -
- please feel free to contribute implementations!
-*/
-static const struct smb_message_struct
-{
- const char *name;
- void (*fn)(struct request_context *);
- int flags;
-}
- smb_messages[256] = {
-/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
-/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
-/* 0x02 */ { "SMBopen",reply_open,AS_USER },
-/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
-/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
-/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
-/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
-/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
-/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
-/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
-/* 0x0a */ { "SMBread",reply_read,AS_USER},
-/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
-/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
-/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
-/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
-/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
-/* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
-/* 0x11 */ { "SMBexit",reply_exit,0},
-/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
-/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
-/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
-/* 0x15 */ { NULL, NULL, 0 },
-/* 0x16 */ { NULL, NULL, 0 },
-/* 0x17 */ { NULL, NULL, 0 },
-/* 0x18 */ { NULL, NULL, 0 },
-/* 0x19 */ { NULL, NULL, 0 },
-/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
-/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
-/* 0x1c */ { "SMBreadBs",NULL,0 },
-/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
-/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
-/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
-/* 0x20 */ { "SMBwritec",NULL,0},
-/* 0x21 */ { NULL, NULL, 0 },
-/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
-/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
-/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
-/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
-/* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
-/* 0x27 */ { "SMBioctl",reply_ioctl,0},
-/* 0x28 */ { "SMBioctls",NULL,AS_USER},
-/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
-/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
-/* 0x2b */ { "SMBecho",reply_echo,0},
-/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
-/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
-/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
-/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
-/* 0x30 */ { NULL, NULL, 0 },
-/* 0x31 */ { NULL, NULL, 0 },
-/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC },
-/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER},
-/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER},
-/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER},
-/* 0x36 */ { NULL, NULL, 0 },
-/* 0x37 */ { NULL, NULL, 0 },
-/* 0x38 */ { NULL, NULL, 0 },
-/* 0x39 */ { NULL, NULL, 0 },
-/* 0x3a */ { NULL, NULL, 0 },
-/* 0x3b */ { NULL, NULL, 0 },
-/* 0x3c */ { NULL, NULL, 0 },
-/* 0x3d */ { NULL, NULL, 0 },
-/* 0x3e */ { NULL, NULL, 0 },
-/* 0x3f */ { NULL, NULL, 0 },
-/* 0x40 */ { NULL, NULL, 0 },
-/* 0x41 */ { NULL, NULL, 0 },
-/* 0x42 */ { NULL, NULL, 0 },
-/* 0x43 */ { NULL, NULL, 0 },
-/* 0x44 */ { NULL, NULL, 0 },
-/* 0x45 */ { NULL, NULL, 0 },
-/* 0x46 */ { NULL, NULL, 0 },
-/* 0x47 */ { NULL, NULL, 0 },
-/* 0x48 */ { NULL, NULL, 0 },
-/* 0x49 */ { NULL, NULL, 0 },
-/* 0x4a */ { NULL, NULL, 0 },
-/* 0x4b */ { NULL, NULL, 0 },
-/* 0x4c */ { NULL, NULL, 0 },
-/* 0x4d */ { NULL, NULL, 0 },
-/* 0x4e */ { NULL, NULL, 0 },
-/* 0x4f */ { NULL, NULL, 0 },
-/* 0x50 */ { NULL, NULL, 0 },
-/* 0x51 */ { NULL, NULL, 0 },
-/* 0x52 */ { NULL, NULL, 0 },
-/* 0x53 */ { NULL, NULL, 0 },
-/* 0x54 */ { NULL, NULL, 0 },
-/* 0x55 */ { NULL, NULL, 0 },
-/* 0x56 */ { NULL, NULL, 0 },
-/* 0x57 */ { NULL, NULL, 0 },
-/* 0x58 */ { NULL, NULL, 0 },
-/* 0x59 */ { NULL, NULL, 0 },
-/* 0x5a */ { NULL, NULL, 0 },
-/* 0x5b */ { NULL, NULL, 0 },
-/* 0x5c */ { NULL, NULL, 0 },
-/* 0x5d */ { NULL, NULL, 0 },
-/* 0x5e */ { NULL, NULL, 0 },
-/* 0x5f */ { NULL, NULL, 0 },
-/* 0x60 */ { NULL, NULL, 0 },
-/* 0x61 */ { NULL, NULL, 0 },
-/* 0x62 */ { NULL, NULL, 0 },
-/* 0x63 */ { NULL, NULL, 0 },
-/* 0x64 */ { NULL, NULL, 0 },
-/* 0x65 */ { NULL, NULL, 0 },
-/* 0x66 */ { NULL, NULL, 0 },
-/* 0x67 */ { NULL, NULL, 0 },
-/* 0x68 */ { NULL, NULL, 0 },
-/* 0x69 */ { NULL, NULL, 0 },
-/* 0x6a */ { NULL, NULL, 0 },
-/* 0x6b */ { NULL, NULL, 0 },
-/* 0x6c */ { NULL, NULL, 0 },
-/* 0x6d */ { NULL, NULL, 0 },
-/* 0x6e */ { NULL, NULL, 0 },
-/* 0x6f */ { NULL, NULL, 0 },
-/* 0x70 */ { "SMBtcon",reply_tcon,USE_MUTEX},
-/* 0x71 */ { "SMBtdis",reply_tdis,0},
-/* 0x72 */ { "SMBnegprot",reply_negprot,USE_MUTEX},
-/* 0x73 */ { "SMBsesssetupX",reply_sesssetup,USE_MUTEX},
-/* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
-/* 0x75 */ { "SMBtconX",reply_tcon_and_X,USE_MUTEX},
-/* 0x76 */ { NULL, NULL, 0 },
-/* 0x77 */ { NULL, NULL, 0 },
-/* 0x78 */ { NULL, NULL, 0 },
-/* 0x79 */ { NULL, NULL, 0 },
-/* 0x7a */ { NULL, NULL, 0 },
-/* 0x7b */ { NULL, NULL, 0 },
-/* 0x7c */ { NULL, NULL, 0 },
-/* 0x7d */ { NULL, NULL, 0 },
-/* 0x7e */ { NULL, NULL, 0 },
-/* 0x7f */ { NULL, NULL, 0 },
-/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
-/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
-/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
-/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
-/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
-/* 0x85 */ { NULL, NULL, 0 },
-/* 0x86 */ { NULL, NULL, 0 },
-/* 0x87 */ { NULL, NULL, 0 },
-/* 0x88 */ { NULL, NULL, 0 },
-/* 0x89 */ { NULL, NULL, 0 },
-/* 0x8a */ { NULL, NULL, 0 },
-/* 0x8b */ { NULL, NULL, 0 },
-/* 0x8c */ { NULL, NULL, 0 },
-/* 0x8d */ { NULL, NULL, 0 },
-/* 0x8e */ { NULL, NULL, 0 },
-/* 0x8f */ { NULL, NULL, 0 },
-/* 0x90 */ { NULL, NULL, 0 },
-/* 0x91 */ { NULL, NULL, 0 },
-/* 0x92 */ { NULL, NULL, 0 },
-/* 0x93 */ { NULL, NULL, 0 },
-/* 0x94 */ { NULL, NULL, 0 },
-/* 0x95 */ { NULL, NULL, 0 },
-/* 0x96 */ { NULL, NULL, 0 },
-/* 0x97 */ { NULL, NULL, 0 },
-/* 0x98 */ { NULL, NULL, 0 },
-/* 0x99 */ { NULL, NULL, 0 },
-/* 0x9a */ { NULL, NULL, 0 },
-/* 0x9b */ { NULL, NULL, 0 },
-/* 0x9c */ { NULL, NULL, 0 },
-/* 0x9d */ { NULL, NULL, 0 },
-/* 0x9e */ { NULL, NULL, 0 },
-/* 0x9f */ { NULL, NULL, 0 },
-/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
-/* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
-/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
-/* 0xa3 */ { NULL, NULL, 0 },
-/* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
-/* 0xa5 */ { "SMBntrename", reply_ntrename, 0 },
-/* 0xa6 */ { NULL, NULL, 0 },
-/* 0xa7 */ { NULL, NULL, 0 },
-/* 0xa8 */ { NULL, NULL, 0 },
-/* 0xa9 */ { NULL, NULL, 0 },
-/* 0xaa */ { NULL, NULL, 0 },
-/* 0xab */ { NULL, NULL, 0 },
-/* 0xac */ { NULL, NULL, 0 },
-/* 0xad */ { NULL, NULL, 0 },
-/* 0xae */ { NULL, NULL, 0 },
-/* 0xaf */ { NULL, NULL, 0 },
-/* 0xb0 */ { NULL, NULL, 0 },
-/* 0xb1 */ { NULL, NULL, 0 },
-/* 0xb2 */ { NULL, NULL, 0 },
-/* 0xb3 */ { NULL, NULL, 0 },
-/* 0xb4 */ { NULL, NULL, 0 },
-/* 0xb5 */ { NULL, NULL, 0 },
-/* 0xb6 */ { NULL, NULL, 0 },
-/* 0xb7 */ { NULL, NULL, 0 },
-/* 0xb8 */ { NULL, NULL, 0 },
-/* 0xb9 */ { NULL, NULL, 0 },
-/* 0xba */ { NULL, NULL, 0 },
-/* 0xbb */ { NULL, NULL, 0 },
-/* 0xbc */ { NULL, NULL, 0 },
-/* 0xbd */ { NULL, NULL, 0 },
-/* 0xbe */ { NULL, NULL, 0 },
-/* 0xbf */ { NULL, NULL, 0 },
-/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER },
-/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
-/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
-/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
-/* 0xc4 */ { NULL, NULL, 0 },
-/* 0xc5 */ { NULL, NULL, 0 },
-/* 0xc6 */ { NULL, NULL, 0 },
-/* 0xc7 */ { NULL, NULL, 0 },
-/* 0xc8 */ { NULL, NULL, 0 },
-/* 0xc9 */ { NULL, NULL, 0 },
-/* 0xca */ { NULL, NULL, 0 },
-/* 0xcb */ { NULL, NULL, 0 },
-/* 0xcc */ { NULL, NULL, 0 },
-/* 0xcd */ { NULL, NULL, 0 },
-/* 0xce */ { NULL, NULL, 0 },
-/* 0xcf */ { NULL, NULL, 0 },
-/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
-/* 0xd1 */ { "SMBsendb",NULL,AS_GUEST},
-/* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST},
-/* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST},
-/* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST},
-/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
-/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
-/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
-/* 0xd8 */ { NULL, NULL, 0 },
-/* 0xd9 */ { NULL, NULL, 0 },
-/* 0xda */ { NULL, NULL, 0 },
-/* 0xdb */ { NULL, NULL, 0 },
-/* 0xdc */ { NULL, NULL, 0 },
-/* 0xdd */ { NULL, NULL, 0 },
-/* 0xde */ { NULL, NULL, 0 },
-/* 0xdf */ { NULL, NULL, 0 },
-/* 0xe0 */ { NULL, NULL, 0 },
-/* 0xe1 */ { NULL, NULL, 0 },
-/* 0xe2 */ { NULL, NULL, 0 },
-/* 0xe3 */ { NULL, NULL, 0 },
-/* 0xe4 */ { NULL, NULL, 0 },
-/* 0xe5 */ { NULL, NULL, 0 },
-/* 0xe6 */ { NULL, NULL, 0 },
-/* 0xe7 */ { NULL, NULL, 0 },
-/* 0xe8 */ { NULL, NULL, 0 },
-/* 0xe9 */ { NULL, NULL, 0 },
-/* 0xea */ { NULL, NULL, 0 },
-/* 0xeb */ { NULL, NULL, 0 },
-/* 0xec */ { NULL, NULL, 0 },
-/* 0xed */ { NULL, NULL, 0 },
-/* 0xee */ { NULL, NULL, 0 },
-/* 0xef */ { NULL, NULL, 0 },
-/* 0xf0 */ { NULL, NULL, 0 },
-/* 0xf1 */ { NULL, NULL, 0 },
-/* 0xf2 */ { NULL, NULL, 0 },
-/* 0xf3 */ { NULL, NULL, 0 },
-/* 0xf4 */ { NULL, NULL, 0 },
-/* 0xf5 */ { NULL, NULL, 0 },
-/* 0xf6 */ { NULL, NULL, 0 },
-/* 0xf7 */ { NULL, NULL, 0 },
-/* 0xf8 */ { NULL, NULL, 0 },
-/* 0xf9 */ { NULL, NULL, 0 },
-/* 0xfa */ { NULL, NULL, 0 },
-/* 0xfb */ { NULL, NULL, 0 },
-/* 0xfc */ { NULL, NULL, 0 },
-/* 0xfd */ { NULL, NULL, 0 },
-/* 0xfe */ { NULL, NULL, 0 },
-/* 0xff */ { NULL, NULL, 0 }
-};
-
-/****************************************************************************
-return a string containing the function name of a SMB command
-****************************************************************************/
-static const char *smb_fn_name(uint8 type)
-{
- const char *unknown_name = "SMBunknown";
-
- if (smb_messages[type].name == NULL)
- return unknown_name;
-
- return smb_messages[type].name;
-}
-
-
-/****************************************************************************
- Do a switch on the message type and call the specific reply function for this
-message. Unlike earlier versions of Samba the reply functions are responsible
-for sending the reply themselves, rather than returning a size to this function
-The reply functions may also choose to delay the processing by pushing the message
-onto the message queue
-****************************************************************************/
-static void switch_message(int type, struct request_context *req)
-{
- int flags;
- uint16 session_tag;
- struct server_context *smb = req->smb;
-
- type &= 0xff;
-
- errno = 0;
-
- if (smb_messages[type].fn == NULL) {
- DEBUG(0,("Unknown message type %d!\n",type));
- reply_unknown(req);
- return;
- }
-
- flags = smb_messages[type].flags;
-
- /* In share mode security we must ignore the vuid. */
- session_tag = (lp_security() == SEC_SHARE) ?
- UID_FIELD_INVALID :
- SVAL(req->in.hdr,HDR_UID);
-
- req->conn = conn_find(req->smb, SVAL(req->in.hdr,HDR_TID));
-
- /* setup the user context for this request */
- setup_user_context(req);
-
- /* Ensure this value is replaced in the incoming packet. */
- SSVAL(req->in.hdr,HDR_UID,session_tag);
-
- if (req->user_ctx) {
- req->user_ctx->vuid = session_tag;
- }
- DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), smb->model_ops->get_id(req)));
-
- /* does this protocol need to be run as root? */
- if (!(flags & AS_USER)) {
- change_to_root_user();
- }
-
- /* does this protocol need a valid tree connection? */
- if ((flags & AS_USER) && !req->conn) {
- req_reply_error(req, NT_STATUS_NETWORK_NAME_DELETED);
- return;
- }
-
- /* does this protocol need to be run as the connected user? */
-#if HACK_REWRITE
- if ((flags & AS_USER) && !change_to_user(req->conn,session_tag)) {
- if (!(flags & AS_GUEST)) {
- req_reply_error(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- /* we'll run it as guest */
- flags &= ~AS_USER;
- }
-#endif
-
- /* this code is to work around a bug is MS client 3 without
- introducing a security hole - it needs to be able to do
- print queue checks as guest if it isn't logged in properly */
- if (flags & AS_USER) {
- flags &= ~AS_GUEST;
- }
-
- /* does it need write permission? */
- if ((flags & NEED_WRITE) && !CAN_WRITE(req->conn)) {
- req_reply_error(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- /* ipc services are limited */
- if (req->conn && req->conn->type == NTVFS_IPC && (flags & AS_USER) && !(flags & CAN_IPC)) {
- req_reply_error(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- /* load service specific parameters */
- if (req->conn && !set_current_service(req->conn,(flags & AS_USER)?True:False)) {
- req_reply_error(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- /* does this protocol need to be run as guest? */
-#if HACK_REWRITE
- if ((flags & AS_GUEST) &&
- !change_to_guest()) {
- req_reply_error(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-#endif
- /* THREAD TESTING: use mutex to serialize calls to critical functions with global state */
- if (flags & USE_MUTEX) {
- MUTEX_LOCK_BY_ID(MUTEX_SMBD);
- }
- smb_messages[type].fn(req);
- if (flags & USE_MUTEX) {
- MUTEX_UNLOCK_BY_ID(MUTEX_SMBD);
- }
-}
-
-
-/****************************************************************************
- Construct a reply to the incoming packet.
-****************************************************************************/
-static void construct_reply(struct request_context *req)
-{
- uint8 type = CVAL(req->in.hdr,HDR_COM);
-
- /* see if its a special NBT packet */
- if (CVAL(req->in.buffer,0) != 0) {
- reply_special(req);
- return;
- }
-
-
- /* Make sure this is an SMB packet */
- if (memcmp(req->in.hdr,"\377SMB",4) != 0) {
- DEBUG(2,("Non-SMB packet of length %d. Terminating connection\n",
- req->in.size));
- exit_server(req->smb, "Non-SMB packet");
- return;
- }
-
- if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) {
- DEBUG(2,("Invalid SMB word count %d\n", req->in.wct));
- exit_server(req->smb, "Invalid SMB packet");
- return;
- }
-
- if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) {
- DEBUG(2,("Invalid SMB buffer length count %d\n", req->in.data_size));
- exit_server(req->smb, "Invalid SMB packet");
- return;
- }
-
-
- req->smbpid = SVAL(req->in.hdr,HDR_PID);
- req->flags = CVAL(req->in.hdr, HDR_FLG);
- req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
-
- switch_message(type, req);
-}
-
-
-/*
- we call this when first first part of a possibly chained request has been completed
- and we need to call the 2nd part, if any
-*/
-void chain_reply(struct request_context *req)
-{
- uint16 chain_cmd, chain_offset;
- char *vwv, *data;
- uint16 wct;
- uint16 data_size;
-
- if (req->in.wct < 2 || req->out.wct < 2) {
- req_reply_dos_error(req, ERRSRV, ERRerror);
- return;
- }
-
- chain_cmd = CVAL(req->in.vwv, VWV(0));
- chain_offset = SVAL(req->in.vwv, VWV(1));
-
- if (chain_cmd == SMB_CHAIN_NONE) {
- /* end of chain */
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- req_send_reply(req);
- return;
- }
-
- if (chain_offset + req->in.hdr >= req->in.buffer + req->in.size) {
- goto error;
- }
-
- wct = CVAL(req->in.hdr, chain_offset);
- vwv = req->in.hdr + chain_offset + 1;
-
- if (vwv + VWV(wct) + 2 > req->in.buffer + req->in.size) {
- goto error;
- }
-
- data_size = SVAL(vwv, VWV(wct));
- data = vwv + VWV(wct) + 2;
-
- if (data + data_size > req->in.buffer + req->in.size) {
- goto error;
- }
-
- /* all seems legit */
- req->in.vwv = vwv;
- req->in.wct = wct;
- req->in.data = data;
- req->in.data_size = data_size;
- req->in.ptr = data;
-
- req->chain_count++;
-
- SSVAL(req->out.vwv, VWV(0), chain_cmd);
- SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
-
- /* the current request in the chain might have used an async reply,
- but that doesn't mean the next element needs to */
- ZERO_STRUCT(req->async);
- req->control_flags &= ~REQ_CONTROL_ASYNC;
-
- switch_message(chain_cmd, req);
- return;
-
-error:
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- req_reply_dos_error(req, ERRSRV, ERRerror);
-}
-
-
-/*
- close the socket and shutdown a server_context
-*/
-void server_terminate(struct server_context *smb)
-{
- close(smb->socket.fd);
- event_remove_fd_all(smb->events, smb->socket.fd);
-
- conn_close_all(smb);
-
- talloc_destroy(smb->mem_ctx);
-}
-
-
-/*
- called when a SMB socket becomes readable
-*/
-void smbd_read_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16 flags)
-{
- struct request_context *req;
- struct server_context *smb = fde->private;
-
- req = receive_smb_request(smb);
- if (!req) {
- smb->model_ops->terminate_connection(smb, "receive error");
- return;
- }
-
- construct_reply(req);
-
- /* free up temporary memory */
- lp_talloc_free();
-}
-
-
-/*
- process a message from an SMB socket while still processing a
- previous message this is used by backends who need to ensure that
- new messages from clients are still processed while they are
- performing long operations
-*/
-void smbd_process_async(struct server_context *smb)
-{
- struct request_context *req;
-
- req = receive_smb_request(smb);
- if (!req) {
- smb->model_ops->terminate_connection(smb, "receive error");
- return;
- }
-
- construct_reply(req);
-}
-
-
-/*
- initialise a server_context from a open socket and register a event handler
- for reading from that socket
-*/
-void init_smbsession(struct event_context *ev, struct model_ops *model_ops, int fd,
- void (*read_handler)(struct event_context *, struct fd_event *, time_t, uint16))
-{
- struct server_context *smb;
- TALLOC_CTX *mem_ctx;
- struct fd_event fde;
- char *socket_addr;
-
- set_socket_options(fd,"SO_KEEPALIVE");
- set_socket_options(fd, lp_socket_options());
-
- mem_ctx = talloc_init("server_context");
-
- smb = (struct server_context *)talloc(mem_ctx, sizeof(*smb));
- if (!smb) return;
-
- ZERO_STRUCTP(smb);
-
- smb->mem_ctx = mem_ctx;
- smb->socket.fd = fd;
- smb->pid = getpid();
-
- sub_set_context(&smb->substitute);
-
- /* set an initial client name based on its IP address. This will be replaced with
- the netbios name later if it gives us one */
- socket_addr = get_socket_addr(smb->mem_ctx, fd);
- sub_set_remote_machine(socket_addr);
- smb->socket.client_addr = socket_addr;
-
- /* now initialise a few default values associated with this smb socket */
- smb->negotiate.max_send = 0xFFFF;
-
- /* this is the size that w2k uses, and it appears to be important for
- good performance */
- smb->negotiate.max_recv = 4356;
-
- smb->users.next_vuid = VUID_OFFSET;
-
- smb->events = ev;
- smb->model_ops = model_ops;
-
- conn_init(smb);
-
- /* setup a event handler for this socket. We are initially
- only interested in reading from the socket */
- fde.fd = fd;
- fde.handler = read_handler;
- fde.private = smb;
- fde.flags = EVENT_FD_READ;
-
- event_add_fd(ev, &fde);
-
- /* setup the DCERPC server subsystem */
- dcesrv_init_context(&smb->dcesrv);
-}
-
-
/*
* initialize an smb process
*/
diff --git a/source4/smbd/reply.c b/source4/smbd/reply.c
deleted file mode 100644
index 7d6450b395..0000000000
--- a/source4/smbd/reply.c
+++ /dev/null
@@ -1,2380 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- Main SMB reply routines
- Copyright (C) Andrew Tridgell 1992-2003
- Copyright (C) James J Myers 2003 <myersjj@samba.org>
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/*
- This file handles most of the reply_ calls that the server
- makes to handle specific protocols
-*/
-
-#include "includes.h"
-
-/* useful way of catching wct errors with file and line number */
-#define REQ_CHECK_WCT(req, wcount) do { \
- if ((req)->in.wct != (wcount)) { \
- DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
- (req)->in.wct, __FILE__, __LINE__, wcount)); \
- req_reply_dos_error(req, ERRSRV, ERRerror); \
- return; \
- }} while (0)
-
-/* check req->async.status and if not OK then send an error reply */
-#define CHECK_ASYNC_STATUS do { \
- if (!NT_STATUS_IS_OK(req->async.status)) { \
- req_reply_error(req, req->async.status); \
- return; \
- }} while (0)
-
-/* useful wrapper for talloc with NO_MEMORY reply */
-#define REQ_TALLOC(ptr, size) do { \
- ptr = talloc(req->mem_ctx, size); \
- if (!ptr) { \
- req_reply_error(req, NT_STATUS_NO_MEMORY); \
- return; \
- }} while (0)
-
-/*
- check if the backend wants to handle the request asynchronously.
- if it wants it handled synchronously then call the send function
- immediately
-*/
-#define REQ_ASYNC_TAIL do { \
- if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
- req->async.send_fn(req); \
- }} while (0)
-
-/* zero out some reserved fields in a reply */
-#define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
-
-/*
- put a NTTIME into a packet
-*/
-void push_nttime(void *base, uint16 offset, NTTIME *t)
-{
- SIVAL(base, offset, t->low);
- SIVAL(base, offset+4, t->high);
-}
-
-/*
- pull a NTTIME from a packet
-*/
-NTTIME pull_nttime(void *base, uint16 offset)
-{
- NTTIME ret;
- ret.low = IVAL(base, offset);
- ret.high = IVAL(base, offset+4);
- return ret;
-}
-
-
-/****************************************************************************
- Reply to a simple request (async send)
-****************************************************************************/
-static void reply_simple_send(struct request_context *req)
-{
- CHECK_ASYNC_STATUS;
-
- req_setup_reply(req, 0, 0);
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a tcon.
-****************************************************************************/
-void reply_tcon(struct request_context *req)
-{
- union smb_tcon con;
- NTSTATUS status;
- char *p;
-
- /* parse request */
- REQ_CHECK_WCT(req, 0);
-
- con.tcon.level = RAW_TCON_TCON;
-
- p = req->in.data;
- p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
- p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
- p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
-
- if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- /* call backend */
- status = tcon_backend(req, &con);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 2, 0);
-
- SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
- SSVAL(req->out.vwv, VWV(1), con.tcon.out.cnum);
- SSVAL(req->out.hdr, HDR_TID, req->conn->cnum);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a tcon and X.
-****************************************************************************/
-void reply_tcon_and_X(struct request_context *req)
-{
- NTSTATUS status;
- union smb_tcon con;
- char *p;
- uint16 passlen;
-
- con.tconx.level = RAW_TCON_TCONX;
-
- /* parse request */
- REQ_CHECK_WCT(req, 4);
-
- con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
- passlen = SVAL(req->in.vwv, VWV(3));
-
- p = req->in.data;
-
- if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
- req_reply_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
- return;
- }
- p += passlen;
-
- p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
-
- if (!con.tconx.in.path || !con.tconx.in.device) {
- req_reply_error(req, NT_STATUS_BAD_DEVICE_TYPE);
- return;
- }
-
- /* call backend */
- status = tcon_backend(req, &con);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply - two varients */
- if (req->smb->negotiate.protocol < PROTOCOL_NT1) {
- req_setup_reply(req, 2, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
-
- req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
- } else {
- req_setup_reply(req, 3, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
-
- req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
- req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
- }
-
- /* set the incoming and outgoing tid to the just created one */
- SSVAL(req->in.hdr, HDR_TID, con.tconx.out.cnum);
- SSVAL(req->out.hdr,HDR_TID, con.tconx.out.cnum);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
- Reply to an unknown request
-****************************************************************************/
-void reply_unknown(struct request_context *req)
-{
- int type;
-
- type = CVAL(req->in.hdr, HDR_COM);
-
- DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
-
- req_reply_dos_error(req, ERRSRV, ERRunknownsmb);
-}
-
-
-/****************************************************************************
- Reply to an ioctl (async reply)
-****************************************************************************/
-static void reply_ioctl_send(struct request_context *req)
-{
- union smb_ioctl *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* the +1 is for nicer alignment */
- req_setup_reply(req, 8, io->ioctl.out.blob.length+1);
- SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
- SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
- SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
-
- memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to an ioctl.
-****************************************************************************/
-void reply_ioctl(struct request_context *req)
-{
- union smb_ioctl *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(io, sizeof(*io));
-
- io->ioctl.level = RAW_IOCTL_IOCTL;
- io->ioctl.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
-
- req->async.send_fn = reply_ioctl_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->ioctl(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a chkpth.
-****************************************************************************/
-void reply_chkpth(struct request_context *req)
-{
- struct smb_chkpath *io;
-
- REQ_TALLOC(io, sizeof(*io));
-
- req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
-
- req->async.send_fn = reply_simple_send;
-
- req->async.status = req->conn->ntvfs_ops->chkpath(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a getatr (async reply)
-****************************************************************************/
-static void reply_getatr_send(struct request_context *req)
-{
- union smb_fileinfo *st = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 10, 0);
-
- SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
- put_dos_date3(req->out.vwv, VWV(1), st->getattr.out.write_time);
- SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
-
- REQ_VWV_RESERVED(5, 5);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a getatr.
-****************************************************************************/
-void reply_getatr(struct request_context *req)
-{
- union smb_fileinfo *st;
-
- REQ_TALLOC(st, sizeof(*st));
-
- st->getattr.level = RAW_FILEINFO_GETATTR;
-
- /* parse request */
- req_pull_ascii4(req, &st->getattr.in.fname, req->in.data, STR_TERMINATE);
- if (!st->getattr.in.fname) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_getatr_send;
- req->async.private = st;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->qpathinfo(req, st);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a setatr.
-****************************************************************************/
-void reply_setatr(struct request_context *req)
-{
- union smb_setfileinfo *st;
-
- /* parse request */
- REQ_CHECK_WCT(req, 8);
- REQ_TALLOC(st, sizeof(*st));
-
- st->setattr.level = RAW_SFILEINFO_SETATTR;
- st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
- st->setattr.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
-
- req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
-
- if (!st->setattr.file.fname) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->setpathinfo(req, st);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a dskattr (async reply)
-****************************************************************************/
-static void reply_dskattr_send(struct request_context *req)
-{
- union smb_fsinfo *fs = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 5, 0);
-
- SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
- SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
- SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
- SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
-
- REQ_VWV_RESERVED(4, 1);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a dskattr.
-****************************************************************************/
-void reply_dskattr(struct request_context *req)
-{
- union smb_fsinfo *fs;
-
- REQ_TALLOC(fs, sizeof(*fs));
-
- fs->dskattr.level = RAW_QFS_DSKATTR;
-
- req->async.send_fn = reply_dskattr_send;
- req->async.private = fs;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->fsinfo(req, fs);
-
- REQ_ASYNC_TAIL;
-}
-
-
-
-/****************************************************************************
- Reply to an open (async reply)
-****************************************************************************/
-static void reply_open_send(struct request_context *req)
-{
- union smb_open *oi = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 7, 0);
-
- SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
- SSVAL(req->out.vwv, VWV(1), oi->open.out.attrib);
- put_dos_date3(req->out.vwv, VWV(2), oi->open.out.write_time);
- SIVAL(req->out.vwv, VWV(4), oi->open.out.size);
- SSVAL(req->out.vwv, VWV(6), oi->open.out.rmode);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to an open.
-****************************************************************************/
-void reply_open(struct request_context *req)
-{
- union smb_open *oi;
-
- /* parse request */
- REQ_CHECK_WCT(req, 2);
- REQ_TALLOC(oi, sizeof(*oi));
-
- oi->open.level = RAW_OPEN_OPEN;
- oi->open.in.flags = SVAL(req->in.vwv, VWV(0));
- oi->open.in.search_attrs = SVAL(req->in.vwv, VWV(1));
-
- req_pull_ascii4(req, &oi->open.in.fname, req->in.data, STR_TERMINATE);
-
- if (!oi->open.in.fname) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_open_send;
- req->async.private = oi;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to an open and X (async reply)
-****************************************************************************/
-static void reply_open_and_X_send(struct request_context *req)
-{
- union smb_open *oi = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* build the reply */
- if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
- req_setup_reply(req, 19, 0);
- } else {
- req_setup_reply(req, 15, 0);
- }
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
- SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
- put_dos_date3(req->out.vwv, VWV(4), oi->openx.out.write_time);
- SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
- SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
- SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
- SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
- SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
- SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
- SSVAL(req->out.vwv, VWV(14),0); /* reserved */
- if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
- SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
- REQ_VWV_RESERVED(17, 2);
- }
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
- Reply to an open and X.
-****************************************************************************/
-void reply_open_and_X(struct request_context *req)
-{
- union smb_open *oi;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 15);
- REQ_TALLOC(oi, sizeof(*oi));
-
- oi->openx.level = RAW_OPEN_OPENX;
- oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
- oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
- oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
- oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
- oi->openx.in.write_time = make_unix_date3(req->in.vwv + VWV(6));
- oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
- oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
- oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
-
- req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
-
- if (!oi->openx.in.fname) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_open_and_X_send;
- req->async.private = oi;
-
- /* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a mknew or a create.
-****************************************************************************/
-static void reply_mknew_send(struct request_context *req)
-{
- union smb_open *oi = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* build the reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), oi->mknew.out.fnum);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a mknew or a create.
-****************************************************************************/
-void reply_mknew(struct request_context *req)
-{
- union smb_open *oi;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(oi, sizeof(*oi));
-
- oi->mknew.level = RAW_OPEN_MKNEW;
- oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
- oi->mknew.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
-
- req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
-
- if (!oi->mknew.in.fname) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_mknew_send;
- req->async.private = oi;
-
- /* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a create temporary file (async reply)
-****************************************************************************/
-static void reply_ctemp_send(struct request_context *req)
-{
- union smb_open *oi = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* build the reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
-
- /* the returned filename is relative to the directory */
- req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a create temporary file.
-****************************************************************************/
-void reply_ctemp(struct request_context *req)
-{
- union smb_open *oi;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(oi, sizeof(*oi));
-
- oi->ctemp.level = RAW_OPEN_CTEMP;
- oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
- oi->ctemp.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
-
- /* the filename is actually a directory name, the server provides a filename
- in that directory */
- req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
-
- if (!oi->ctemp.in.directory) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
-
- req->async.send_fn = reply_ctemp_send;
- req->async.private = oi;
-
- /* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a unlink
-****************************************************************************/
-void reply_unlink(struct request_context *req)
-{
- struct smb_unlink *unl;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 1);
- REQ_TALLOC(unl, sizeof(*unl));
-
- unl->in.attrib = SVAL(req->in.vwv, VWV(0));
-
- req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->unlink(req, unl);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a readbraw (core+ protocol).
- this is a strange packet because it doesn't use a standard SMB header in the reply,
- only the 4 byte NBT header
- This command must be replied to synchronously
-****************************************************************************/
-void reply_readbraw(struct request_context *req)
-{
- NTSTATUS status;
- union smb_read io;
-
- io.readbraw.level = RAW_READ_READBRAW;
-
- /* there are two varients, one with 10 and one with 8 command words */
- if (req->in.wct != 10) {
- REQ_CHECK_WCT(req, 8);
- }
-
- io.readbraw.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
- io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(3));
- io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(4));
- io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
-
- /* the 64 bit varient */
- if (req->in.wct == 10) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(8));
-#ifdef LARGE_SMB_OFF_T
- io.readbraw.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- goto failed;
- }
-#endif
- }
-
- /* before calling the backend we setup the raw buffer. This
- * saves a copy later */
- req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
- req->out.buffer = talloc(req->mem_ctx, req->out.size);
- if (req->out.buffer == NULL) {
- goto failed;
- }
- SIVAL(req->out.buffer, 0, 0); /* init NBT header */
-
- /* tell the backend where to put the data */
- io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
-
- /* call the backend */
- status = req->conn->ntvfs_ops->read(req, &io);
-
- if (!NT_STATUS_IS_OK(status)) {
- goto failed;
- }
-
- req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
-
- req_send_reply(req);
- return;
-
-failed:
- /* any failure in readbraw is equivalent to reading zero bytes */
- req->out.size = 4;
- req->out.buffer = talloc(req->mem_ctx, req->out.size);
- SIVAL(req->out.buffer, 0, 0); /* init NBT header */
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a lockread (async reply)
-****************************************************************************/
-static void reply_lockread_send(struct request_context *req)
-{
- union smb_read *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* trim packet */
- io->lockread.out.nread = MIN(io->lockread.out.nread,
- req_max_data(req) - 3);
- req_grow_data(req, 3 + io->lockread.out.nread);
-
- /* construct reply */
- SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
- REQ_VWV_RESERVED(1, 4);
-
- SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
- SSVAL(req->out.data, 1, io->lockread.out.nread);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a lockread (core+ protocol).
- note that the lock is a write lock, not a read lock!
-****************************************************************************/
-void reply_lockread(struct request_context *req)
-{
- union smb_read *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(io, sizeof(*io));
-
- io->lockread.level = RAW_READ_LOCKREAD;
- io->lockread.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
- io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
- io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
-
- /* setup the reply packet assuming the maximum possible read */
- req_setup_reply(req, 5, 3 + io->lockread.in.count);
-
- /* tell the backend where to put the data */
- io->lockread.out.data = req->out.data + 3;
-
- req->async.send_fn = reply_lockread_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-
-/****************************************************************************
- Reply to a read (async reply)
-****************************************************************************/
-static void reply_read_send(struct request_context *req)
-{
- union smb_read *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* trim packet */
- io->read.out.nread = MIN(io->read.out.nread,
- req_max_data(req) - 3);
- req_grow_data(req, 3 + io->read.out.nread);
-
- /* construct reply */
- SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
- REQ_VWV_RESERVED(1, 4);
-
- SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
- SSVAL(req->out.data, 1, io->read.out.nread);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a read.
-****************************************************************************/
-void reply_read(struct request_context *req)
-{
- union smb_read *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(io, sizeof(*io));
-
- io->read.level = RAW_READ_READ;
- io->read.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->read.in.count = SVAL(req->in.vwv, VWV(1));
- io->read.in.offset = IVAL(req->in.vwv, VWV(2));
- io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
-
- /* setup the reply packet assuming the maximum possible read */
- req_setup_reply(req, 5, 3 + io->read.in.count);
-
- /* tell the backend where to put the data */
- io->read.out.data = req->out.data + 3;
-
- req->async.send_fn = reply_read_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-
-/****************************************************************************
- Reply to a read and X (async reply)
-****************************************************************************/
-static void reply_read_and_X_send(struct request_context *req)
-{
- union smb_read *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* trim the packet to the right size */
- io->readx.out.nread = MIN(io->readx.out.nread,
- req_max_data(req) - 1);
- req_grow_data(req, 1 + io->readx.out.nread);
-
- /* construct reply */
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
- SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
- REQ_VWV_RESERVED(4, 1);
- SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
- SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
- SCVAL(req->out.data, 0, 0); /* padding */
- REQ_VWV_RESERVED(7, 5);
-
- chain_reply(req);
-}
-
-/****************************************************************************
- Reply to a read and X.
-****************************************************************************/
-void reply_read_and_X(struct request_context *req)
-{
- union smb_read *io;
-
- /* parse request */
- if (req->in.wct != 12) {
- REQ_CHECK_WCT(req, 10);
- }
-
- REQ_TALLOC(io, sizeof(*io));
-
- io->readx.level = RAW_READ_READX;
- io->readx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
- io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
- io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
- io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
- io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
-
- /* the 64 bit varient */
- if (req->in.wct == 12) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(10));
-#ifdef LARGE_SMB_OFF_T
- io->readx.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-#endif
- }
-
- /* setup the reply packet assuming the maximum possible read */
- req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
-
- /* tell the backend where to put the data. Notice the pad byte. */
- io->readx.out.data = req->out.data + 1;
-
- req->async.send_fn = reply_read_and_X_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->read(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a writebraw (core+ or LANMAN1.0 protocol).
-****************************************************************************/
-void reply_writebraw(struct request_context *req)
-{
- /* this one is damn complex - put it off for now */
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
- Reply to a writeunlock (async reply)
-****************************************************************************/
-static void reply_writeunlock_send(struct request_context *req)
-{
- union smb_write *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a writeunlock (core+).
-****************************************************************************/
-void reply_writeunlock(struct request_context *req)
-{
- union smb_write *io;
-
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(io, sizeof(*io));
-
- io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
- io->writeunlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
- io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
- io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
- io->writeunlock.in.data = req->in.data + 3;
-
- /* make sure they gave us the data they promised */
- if (io->writeunlock.in.count+3 > req->in.data_size) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- /* make sure the data block is big enough */
- if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_writeunlock_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-
-/****************************************************************************
- Reply to a write (async reply)
-****************************************************************************/
-static void reply_write_send(struct request_context *req)
-{
- union smb_write *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a write
-****************************************************************************/
-void reply_write(struct request_context *req)
-{
- union smb_write *io;
-
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(io, sizeof(*io));
-
- io->write.level = RAW_WRITE_WRITE;
- io->write.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->write.in.count = SVAL(req->in.vwv, VWV(1));
- io->write.in.offset = IVAL(req->in.vwv, VWV(2));
- io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
- io->write.in.data = req->in.data + 3;
-
- /* make sure they gave us the data they promised */
- if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- /* make sure the data block is big enough */
- if (SVAL(req->in.data, 1) < io->write.in.count) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_write_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a write and X (async reply)
-****************************************************************************/
-static void reply_write_and_X_send(struct request_context *req)
-{
- union smb_write *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 6, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
- SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
- SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
- REQ_VWV_RESERVED(5, 1);
-
- chain_reply(req);
-}
-
-/****************************************************************************
- Reply to a write and X.
-****************************************************************************/
-void reply_write_and_X(struct request_context *req)
-{
- union smb_write *io;
-
- if (req->in.wct != 14) {
- REQ_CHECK_WCT(req, 12);
- }
-
- REQ_TALLOC(io, sizeof(*io));
-
- io->writex.level = RAW_WRITE_WRITEX;
- io->writex.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
- io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
- io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
- io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
- io->writex.in.count = SVAL(req->in.vwv, VWV(10));
- io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
-
- if (req->in.wct == 14) {
- uint32 offset_high = IVAL(req->in.vwv, VWV(12));
- uint16 count_high = SVAL(req->in.vwv, VWV(9));
-#ifdef LARGE_SMB_OFF_T
- io->writex.in.offset |= (((SMB_OFF_T)offset_high) << 32);
-#else
- if (offset_high != 0) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-#endif
- io->writex.in.count |= ((uint32)count_high) << 16;
- }
-
- /* make sure the data is in bounds */
- if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_write_and_X_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a lseek (async reply)
-****************************************************************************/
-static void reply_lseek_send(struct request_context *req)
-{
- struct smb_seek *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 2, 0);
-
- SIVALS(req->out.vwv, VWV(0), io->out.offset);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a lseek.
-****************************************************************************/
-void reply_lseek(struct request_context *req)
-{
- struct smb_seek *io;
-
- REQ_CHECK_WCT(req, 4);
- REQ_TALLOC(io, sizeof(*io));
-
- io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->in.mode = SVAL(req->in.vwv, VWV(1));
- io->in.offset = IVALS(req->in.vwv, VWV(2));
-
- req->async.send_fn = reply_lseek_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->seek(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a flush.
-****************************************************************************/
-void reply_flush(struct request_context *req)
-{
- struct smb_flush *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 1);
- REQ_TALLOC(io, sizeof(*io));
-
- io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->flush(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a exit.
-****************************************************************************/
-void reply_exit(struct request_context *req)
-{
- REQ_CHECK_WCT(req, 0);
-
- req->async.send_fn = reply_simple_send;
-
- if (!req->conn) {
- req_reply_error(req, NT_STATUS_INVALID_HANDLE);
- return;
- }
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->exit(req);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a close
-
- Note that this has to deal with closing a directory opened by NT SMB's.
-****************************************************************************/
-void reply_close(struct request_context *req)
-{
- union smb_close *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(io, sizeof(*io));
-
- io->close.level = RAW_CLOSE_CLOSE;
- io->close.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->close.in.write_time = make_unix_date3(req->in.vwv + VWV(1));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->close(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-
-/****************************************************************************
- Reply to a writeclose (async reply)
-****************************************************************************/
-static void reply_writeclose_send(struct request_context *req)
-{
- union smb_write *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a writeclose (Core+ protocol).
-****************************************************************************/
-void reply_writeclose(struct request_context *req)
-{
- union smb_write *io;
-
- /* this one is pretty weird - the wct can be 6 or 12 */
- if (req->in.wct != 12) {
- REQ_CHECK_WCT(req, 6);
- }
-
- REQ_TALLOC(io, sizeof(*io));
-
- io->writeclose.level = RAW_WRITE_WRITECLOSE;
- io->writeclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
- io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
- io->writeclose.in.mtime = make_unix_date3(req->in.vwv + VWV(4));
- io->writeclose.in.data = req->in.data + 1;
-
- /* make sure they gave us the data they promised */
- if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_writeclose_send;
- req->async.private = io;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a lock.
-****************************************************************************/
-void reply_lock(struct request_context *req)
-{
- union smb_lock *lck;
-
- /* parse request */
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(lck, sizeof(*lck));
-
- lck->lock.level = RAW_LOCK_LOCK;
- lck->lock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
- lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a unlock.
-****************************************************************************/
-void reply_unlock(struct request_context *req)
-{
- union smb_lock *lck;
-
- /* parse request */
- REQ_CHECK_WCT(req, 5);
- REQ_TALLOC(lck, sizeof(*lck));
-
- lck->unlock.level = RAW_LOCK_UNLOCK;
- lck->unlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
- lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a tdis.
-****************************************************************************/
-void reply_tdis(struct request_context *req)
-{
- REQ_CHECK_WCT(req, 0);
-
- close_cnum(req->conn);
-
- /* construct reply */
- req_setup_reply(req, 0, 0);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a echo. This is one of the few calls that is handled directly (the
- backends don't see it at all)
-****************************************************************************/
-void reply_echo(struct request_context *req)
-{
- uint16 count;
- int i;
-
- REQ_CHECK_WCT(req, 0);
-
- count = SVAL(req->in.vwv, VWV(0));
-
- req_setup_reply(req, 1, req->in.data_size);
-
- memcpy(req->out.data, req->in.data, req->in.data_size);
-
- /* we need to make sure the request isn't destroyed till the
- * last packet */
- req->control_flags |= REQ_CONTROL_PROTECTED;
-
- for (i=1; i <= count;i++) {
- if (i == count) {
- req->control_flags &= ~REQ_CONTROL_PROTECTED;
- }
-
- SSVAL(req->out.vwv, VWV(0), i);
- req_send_reply(req);
- }
-}
-
-
-
-/****************************************************************************
- Reply to a printopen (async reply)
-****************************************************************************/
-static void reply_printopen_send(struct request_context *req)
-{
- union smb_open *oi = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), oi->open.out.fnum);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a printopen.
-****************************************************************************/
-void reply_printopen(struct request_context *req)
-{
- union smb_open *oi;
-
- /* parse request */
- REQ_CHECK_WCT(req, 2);
- REQ_TALLOC(oi, sizeof(*oi));
-
- oi->splopen.level = RAW_OPEN_SPLOPEN;
- oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
- oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
-
- req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
-
- req->async.send_fn = reply_printopen_send;
- req->async.private = oi;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->open(req, oi);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a printclose.
-****************************************************************************/
-void reply_printclose(struct request_context *req)
-{
- union smb_close *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(io, sizeof(*io));
-
- io->splclose.level = RAW_CLOSE_SPLCLOSE;
- io->splclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->close(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a printqueue.
-****************************************************************************/
-void reply_printqueue_send(struct request_context *req)
-{
- union smb_lpq *lpq = req->async.private;
- int i, maxcount;
- const uint_t el_size = 28;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 2, 0);
-
- /* truncate the returned list to fit in the negotiated buffer size */
- maxcount = (req_max_data(req) - 3) / el_size;
- if (maxcount < lpq->retq.out.count) {
- lpq->retq.out.count = maxcount;
- }
-
- /* setup enough space in the reply */
- req_grow_data(req, 3 + el_size*lpq->retq.out.count);
-
- /* and fill it in */
- SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
- SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
-
- SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
- SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
-
- req->out.ptr = req->out.data + 3;
-
- for (i=0;i<lpq->retq.out.count;i++) {
- put_dos_date2(req->out.ptr, 0 , lpq->retq.out.queue[i].time);
- SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
- SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
- SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
- SCVAL(req->out.ptr, 11, 0); /* reserved */
- req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
- req->out.ptr += el_size;
- }
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a printqueue.
-****************************************************************************/
-void reply_printqueue(struct request_context *req)
-{
- union smb_lpq *lpq;
-
- /* parse request */
- REQ_CHECK_WCT(req, 2);
- REQ_TALLOC(lpq, sizeof(*lpq));
-
- lpq->retq.level = RAW_LPQ_RETQ;
- lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
- lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
-
- req->async.send_fn = reply_printqueue_send;
- req->async.private = lpq;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->lpq(req, lpq);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a printwrite.
-****************************************************************************/
-void reply_printwrite(struct request_context *req)
-{
- union smb_write *io;
-
- /* parse request */
- REQ_CHECK_WCT(req, 1);
- REQ_TALLOC(io, sizeof(*io));
-
- io->splwrite.level = RAW_WRITE_SPLWRITE;
-
- if (req->in.data_size < 3) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- io->splwrite.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
- io->splwrite.in.count = SVAL(req->in.data, 1);
- io->splwrite.in.data = req->in.data + 3;
-
- /* make sure they gave us the data they promised */
- if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->write(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a mkdir.
-****************************************************************************/
-void reply_mkdir(struct request_context *req)
-{
- union smb_mkdir *io;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 0);
- REQ_TALLOC(io, sizeof(*io));
-
- io->generic.level = RAW_MKDIR_MKDIR;
- req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->mkdir(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a rmdir.
-****************************************************************************/
-void reply_rmdir(struct request_context *req)
-{
- struct smb_rmdir *io;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 0);
- REQ_TALLOC(io, sizeof(*io));
-
- req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->rmdir(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a mv.
-****************************************************************************/
-void reply_mv(struct request_context *req)
-{
- union smb_rename *io;
- char *p;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 1);
- REQ_TALLOC(io, sizeof(*io));
-
- io->generic.level = RAW_RENAME_RENAME;
- io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
-
- p = req->in.data;
- p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
- p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
-
- if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->rename(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to an NT rename.
-****************************************************************************/
-void reply_ntrename(struct request_context *req)
-{
- union smb_rename *io;
- char *p;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 4);
- REQ_TALLOC(io, sizeof(*io));
-
- io->generic.level = RAW_RENAME_NTRENAME;
- io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
- io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
- io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
-
- p = req->in.data;
- p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
- p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
-
- if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->rename(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a file copy (async reply)
-****************************************************************************/
-static void reply_copy_send(struct request_context *req)
-{
- struct smb_copy *cp = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* build the reply */
- req_setup_reply(req, 1, 0);
-
- SSVAL(req->out.vwv, VWV(0), cp->out.count);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a file copy.
-****************************************************************************/
-void reply_copy(struct request_context *req)
-{
- struct smb_copy *cp;
- char *p;
-
- /* parse request */
- REQ_CHECK_WCT(req, 3);
- REQ_TALLOC(cp, sizeof(*cp));
-
- cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
- cp->in.ofun = SVAL(req->in.vwv, VWV(1));
- cp->in.flags = SVAL(req->in.vwv, VWV(2));
-
- p = req->in.data;
- p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
- p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
-
- if (!cp->in.path1 || !cp->in.path2) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_copy_send;
- req->async.private = cp;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->copy(req, cp);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a lockingX request (async send)
-****************************************************************************/
-static void reply_lockingX_send(struct request_context *req)
-{
- union smb_lock *lck = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* if it was an oplock break ack then we only send a reply if
- there was an error */
- if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
- req_destroy(req);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 2, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a lockingX request.
-****************************************************************************/
-void reply_lockingX(struct request_context *req)
-{
- union smb_lock *lck;
- uint_t total_locks, i;
- uint_t lck_size;
- char *p;
-
- /* parse request */
- REQ_CHECK_WCT(req, 8);
- REQ_TALLOC(lck, sizeof(*lck));
-
- lck->lockx.level = RAW_LOCK_LOCKX;
- lck->lockx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
- lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
- lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
- lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
- lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
-
- total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
-
- /* there are two varients, one with 64 bit offsets and counts */
- if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
- lck_size = 20;
- } else {
- lck_size = 10;
- }
-
- /* make sure we got the promised data */
- if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- /* allocate the locks array */
- if (total_locks) {
- REQ_TALLOC(lck->lockx.in.locks, total_locks * sizeof(lck->lockx.in.locks[0]));
- }
-
- p = req->in.data;
-
- /* construct the locks array */
- for (i=0;i<total_locks;i++) {
- uint32 ofs_high=0, count_high=0;
-
- lck->lockx.in.locks[i].pid = SVAL(p, 0);
-
- if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
- ofs_high = IVAL(p, 4);
- lck->lockx.in.locks[i].offset = IVAL(p, 8);
- count_high = IVAL(p, 12);
- lck->lockx.in.locks[i].count = IVAL(p, 16);
- } else {
- lck->lockx.in.locks[i].offset = IVAL(p, 2);
- lck->lockx.in.locks[i].count = IVAL(p, 6);
- }
- if (ofs_high != 0 || count_high != 0) {
-#ifdef LARGE_SMB_OFF_T
- lck->lockx.in.locks[i].count |= ((SMB_OFF_T)count_high) << 32;
- lck->lockx.in.locks[i].offset |= ((SMB_OFF_T)ofs_high) << 32;
-#else
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
-#endif
- }
- p += lck_size;
- }
-
- req->async.send_fn = reply_lockingX_send;
- req->async.private = lck;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->lock(req, lck);
-
- REQ_ASYNC_TAIL;
-}
-
-/****************************************************************************
- Reply to a SMBreadbmpx (read block multiplex) request.
-****************************************************************************/
-void reply_readbmpx(struct request_context *req)
-{
- /* tell the client to not use a multiplexed read - its too broken to use */
- req_reply_dos_error(req, ERRSRV, ERRuseSTD);
-}
-
-
-/****************************************************************************
- Reply to a SMBsetattrE.
-****************************************************************************/
-void reply_setattrE(struct request_context *req)
-{
- union smb_setfileinfo *info;
-
- /* parse request */
- REQ_CHECK_WCT(req, 7);
- REQ_TALLOC(info, sizeof(*info));
-
- info->setattre.level = RAW_SFILEINFO_SETATTRE;
- info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
- info->setattre.in.create_time = make_unix_date2(req->in.vwv + VWV(1));
- info->setattre.in.access_time = make_unix_date2(req->in.vwv + VWV(3));
- info->setattre.in.write_time = make_unix_date2(req->in.vwv + VWV(5));
-
- req->async.send_fn = reply_simple_send;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->setfileinfo(req, info);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to a SMBwritebmpx (write block multiplex primary) request.
-****************************************************************************/
-void reply_writebmpx(struct request_context *req)
-{
- /* we will need to implement this one for OS/2, but right now I can't be bothered */
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
- Reply to a SMBwritebs (write block multiplex secondary) request.
-****************************************************************************/
-void reply_writebs(struct request_context *req)
-{
- /* see reply_writebmpx */
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-
-/****************************************************************************
- Reply to a SMBgetattrE (async reply)
-****************************************************************************/
-static void reply_getattrE_send(struct request_context *req)
-{
- union smb_fileinfo *info = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* setup reply */
- req_setup_reply(req, 11, 0);
-
- put_dos_date2(req->out.vwv, VWV(0), info->getattre.out.create_time);
- put_dos_date2(req->out.vwv, VWV(2), info->getattre.out.access_time);
- put_dos_date2(req->out.vwv, VWV(4), info->getattre.out.write_time);
- SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
- SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
- SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to a SMBgetattrE.
-****************************************************************************/
-void reply_getattrE(struct request_context *req)
-{
- union smb_fileinfo *info;
-
- /* parse request */
- REQ_CHECK_WCT(req, 1);
- REQ_TALLOC(info, sizeof(*info));
-
- info->getattr.level = RAW_FILEINFO_GETATTRE;
- info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
-
- req->async.send_fn = reply_getattrE_send;
- req->async.private = info;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->qfileinfo(req, info);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
-reply to an old style session setup command
-****************************************************************************/
-static void reply_sesssetup_old(struct request_context *req)
-{
- NTSTATUS status;
- union smb_sesssetup sess;
- char *p;
- uint16 passlen;
-
- sess.old.level = RAW_SESSSETUP_OLD;
-
- /* parse request */
- sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
- sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
- sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
- sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
- passlen = SVAL(req->in.vwv, VWV(7));
-
- /* check the request isn't malformed */
- if (req_data_oob(req, req->in.data, passlen)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- p = req->in.data;
- if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
- p += passlen;
-
- p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
-
- /* call the generic handler */
- status = sesssetup_backend(req, &sess);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 3, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
-
- SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
-reply to an NT1 style session setup command
-****************************************************************************/
-static void reply_sesssetup_nt1(struct request_context *req)
-{
- NTSTATUS status;
- union smb_sesssetup sess;
- char *p;
- uint16 passlen1, passlen2;
-
- sess.nt1.level = RAW_SESSSETUP_NT1;
-
- /* parse request */
- sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
- sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
- sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
- sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
- passlen1 = SVAL(req->in.vwv, VWV(7));
- passlen2 = SVAL(req->in.vwv, VWV(8));
- sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
-
- /* check the request isn't malformed */
- if (req_data_oob(req, req->in.data, passlen1) ||
- req_data_oob(req, req->in.data + passlen1, passlen2)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- p = req->in.data;
- if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
- p += passlen1;
- if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
- p += passlen2;
-
- p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
-
- /* call the generic handler */
- status = sesssetup_backend(req, &sess);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 3, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
-
- SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
-
- req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
- req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
- req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
-reply to an SPNEGO style session setup command
-****************************************************************************/
-static void reply_sesssetup_spnego(struct request_context *req)
-{
- NTSTATUS status;
- union smb_sesssetup sess;
- char *p;
- uint16 blob_len;
-
- sess.spnego.level = RAW_SESSSETUP_SPNEGO;
-
- /* parse request */
- sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
- sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
- sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
- sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
- blob_len = SVAL(req->in.vwv, VWV(7));
- sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
-
- p = req->in.data;
- if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
- p += blob_len;
-
- p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
- p += req_pull_string(req, &sess.spnego.in.domain, p, -1, STR_TERMINATE);
-
- /* call the generic handler */
- status = sesssetup_backend(req, &sess);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 4, sess.spnego.out.secblob.length);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
- SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
-
- SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
-
- memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
- req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
- req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
-reply to a session setup command
-****************************************************************************/
-void reply_sesssetup(struct request_context *req)
-{
- switch (req->in.wct) {
- case 10:
- /* a pre-NT1 call */
- reply_sesssetup_old(req);
- return;
- case 13:
- /* a NT1 call */
- reply_sesssetup_nt1(req);
- return;
- case 12:
- /* a SPNEGO call */
- reply_sesssetup_spnego(req);
- return;
- }
-
- /* unsupported varient */
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
- Reply to a SMBulogoffX.
-****************************************************************************/
-void reply_ulogoffX(struct request_context *req)
-{
- uint16 vuid;
-
- vuid = SVAL(req->in.hdr, HDR_UID);
-
- /* in user level security we are supposed to close any files
- open by this user */
- if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
- DEBUG(0,("REWRITE: not closing user files\n"));
- }
-
- invalidate_vuid(req->smb, vuid);
-
- req_setup_reply(req, 2, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
-
- chain_reply(req);
-}
-
-
-/****************************************************************************
- Reply to an SMBfindclose request
-****************************************************************************/
-void reply_findclose(struct request_context *req)
-{
- NTSTATUS status;
- union smb_search_close io;
-
- io.findclose.level = RAW_FINDCLOSE_CLOSE;
-
- /* parse request */
- REQ_CHECK_WCT(req, 1);
-
- io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
-
- /* call backend */
- status = req->conn->ntvfs_ops->search_close(req, &io);
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- /* construct reply */
- req_setup_reply(req, 0, 0);
-
- req_send_reply(req);
-}
-
-/****************************************************************************
- Reply to an SMBfindnclose request
-****************************************************************************/
-void reply_findnclose(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-/****************************************************************************
- Reply to an SMBntcreateX request (async send)
-****************************************************************************/
-static void reply_ntcreate_and_X_send(struct request_context *req)
-{
- union smb_open *io = req->async.private;
-
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 34, 0);
-
- SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
- SSVAL(req->out.vwv, VWV(1), 0);
- SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
-
- /* the rest of the parameters are not aligned! */
- SSVAL(req->out.vwv, 5, io->ntcreatex.out.fnum);
- SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
- push_nttime(req->out.vwv, 11, &io->ntcreatex.out.create_time);
- push_nttime(req->out.vwv, 19, &io->ntcreatex.out.access_time);
- push_nttime(req->out.vwv, 27, &io->ntcreatex.out.write_time);
- push_nttime(req->out.vwv, 35, &io->ntcreatex.out.change_time);
- SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
- SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
- SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
- SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
- SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
- SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
-
- chain_reply(req);
-}
-
-/****************************************************************************
- Reply to an SMBntcreateX request
-****************************************************************************/
-void reply_ntcreate_and_X(struct request_context *req)
-{
- union smb_open *io;
- uint16 fname_len;
-
- /* parse the request */
- REQ_CHECK_WCT(req, 24);
- REQ_TALLOC(io, sizeof(*io));
-
- io->ntcreatex.level = RAW_OPEN_NTCREATEX;
-
- /* notice that the word parameters are not word aligned, so we don't use VWV() */
- fname_len = SVAL(req->in.vwv, 5);
- io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
- io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
- io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
- io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
- io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
- io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
- io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
- io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
- io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
- io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
-
- /* we need a neater way to handle this alignment */
- if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
- ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
- fname_len++;
- }
-
- req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
- if (!io->ntcreatex.in.fname) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- req->async.send_fn = reply_ntcreate_and_X_send;
- req->async.private = io;
-
- /* call the backend */
- req->async.status = req->conn->ntvfs_ops->open(req, io);
-
- REQ_ASYNC_TAIL;
-}
-
-
-/****************************************************************************
- Reply to an SMBntcancel request
-****************************************************************************/
-void reply_ntcancel(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-/****************************************************************************
- Reply to an SMBsends request
-****************************************************************************/
-void reply_sends(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-/****************************************************************************
- Reply to an SMBsendstrt request
-****************************************************************************/
-void reply_sendstrt(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-/****************************************************************************
- Reply to an SMBsendend request
-****************************************************************************/
-void reply_sendend(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-/****************************************************************************
- Reply to an SMBsendtxt request
-****************************************************************************/
-void reply_sendtxt(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-
-
-/****************************************************************************
- Reply to a special message - a SMB packet with non zero NBT message type
-****************************************************************************/
-void reply_special(struct request_context *req)
-{
- uint8 msg_type;
- char buf[4];
-
- msg_type = CVAL(req->in.buffer,0);
-
- SIVAL(buf, 0, 0);
-
- switch (msg_type) {
- case 0x81: /* session request */
- if (req->smb->negotiate.done_nbt_session) {
- exit_server(req->smb, "multiple session request not permitted");
- }
-
- SCVAL(buf,0,0x82);
- SCVAL(buf,3,0);
-
- DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
-
- req->smb->negotiate.done_nbt_session = True;
-
- req->out.buffer = buf;
- req->out.size = 4;
- req_send_reply(req);
- return;
-
- case 0x89: /* session keepalive request
- (some old clients produce this?) */
- SCVAL(buf, 0, SMBkeepalive);
- SCVAL(buf, 3, 0);
- req->out.buffer = buf;
- req->out.size = 4;
- req_send_reply(req);
- return;
-
- case SMBkeepalive:
- /* session keepalive - swallow it */
- req_destroy(req);
- return;
- }
-
- DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
- req_destroy(req);
-}
diff --git a/source4/smbd/request.c b/source4/smbd/request.c
deleted file mode 100644
index 065e63a8d2..0000000000
--- a/source4/smbd/request.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Andrew Tridgell 2003
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*
- this file implements functions for manipulating the 'struct request_context' structure in smbd
-*/
-
-#include "includes.h"
-
-/* we over allocate the data buffer to prevent too many realloc calls */
-#define REQ_OVER_ALLOCATION 256
-
-/* destroy a request structure */
-void req_destroy(struct request_context *req)
-{
- /* the request might be marked protected. This is done by the
- * SMBecho code for example */
- if (req->control_flags & REQ_CONTROL_PROTECTED) {
- return;
- }
-
- /* ahh, its so nice to destroy a complex structure in such a
- * simple way! */
- talloc_destroy(req->mem_ctx);
-}
-
-/****************************************************************************
-construct a basic request packet, mostly used to construct async packets
-such as change notify and oplock break requests
-****************************************************************************/
-struct request_context *init_smb_request(struct server_context *smb)
-{
- struct request_context *req;
- TALLOC_CTX *mem_ctx;
-
- /* each request gets its own talloc context. The request
- structure itself is also allocated inside this context, so
- we need to allocate it before we construct the request
- */
- mem_ctx = talloc_init("request_context[%d]", smb->socket.pkt_count);
- if (!mem_ctx) {
- return NULL;
- }
-
- smb->socket.pkt_count++;
-
- req = talloc(mem_ctx, sizeof(*req));
- if (!req) {
- return NULL;
- }
-
- ZERO_STRUCTP(req);
-
- /* setup the request context */
- req->smb = smb;
- req->mem_ctx = mem_ctx;
-
- return req;
-}
-
-
-/*
- setup a chained reply in req->out with the given word count and initial data buffer size.
-*/
-static void req_setup_chain_reply(struct request_context *req, unsigned wct, unsigned buflen)
-{
- uint32 chain_base_size = req->out.size;
-
- /* we need room for the wct value, the words, the buffer length and the buffer */
- req->out.size += 1 + VWV(wct) + 2 + buflen;
-
- /* over allocate by a small amount */
- req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
-
- req->out.buffer = talloc_realloc(req->mem_ctx, req->out.buffer, req->out.allocated);
- if (!req->out.buffer) {
- exit_server(req->smb, "allocation failed");
- }
-
- req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
- req->out.vwv = req->out.buffer + chain_base_size + 1;
- req->out.wct = wct;
- req->out.data = req->out.vwv + VWV(wct) + 2;
- req->out.data_size = buflen;
- req->out.ptr = req->out.data;
-
- SCVAL(req->out.buffer, chain_base_size, wct);
- SSVAL(req->out.vwv, VWV(wct), buflen);
-}
-
-
-/*
- setup a reply in req->out with the given word count and initial data buffer size.
- the caller will then fill in the command words and data before calling req_send_reply() to
- send the reply on its way
-*/
-void req_setup_reply(struct request_context *req, unsigned wct, unsigned buflen)
-{
- if (req->chain_count != 0) {
- req_setup_chain_reply(req, wct, buflen);
- return;
- }
-
- req->out.size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen;
-
- /* over allocate by a small amount */
- req->out.allocated = req->out.size + REQ_OVER_ALLOCATION;
-
- req->out.buffer = talloc(req->mem_ctx, req->out.allocated);
- if (!req->out.buffer) {
- exit_server(req->smb, "allocation failed");
- }
-
- req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
- req->out.vwv = req->out.hdr + HDR_VWV;
- req->out.wct = wct;
- req->out.data = req->out.vwv + VWV(wct) + 2;
- req->out.data_size = buflen;
- req->out.ptr = req->out.data;
-
- SIVAL(req->out.hdr, HDR_RCLS, 0);
-
- SCVAL(req->out.hdr, HDR_WCT, wct);
- SSVAL(req->out.vwv, VWV(wct), buflen);
-
-
- memcpy(req->out.hdr, "\377SMB", 4);
- SCVAL(req->out.hdr,HDR_FLG, FLAG_REPLY | FLAG_CASELESS_PATHNAMES);
- SSVAL(req->out.hdr,HDR_FLG2,
- (req->flags2 & FLAGS2_UNICODE_STRINGS) |
- FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_32_BIT_ERROR_CODES | FLAGS2_EXTENDED_SECURITY);
-
- SSVAL(req->out.hdr,HDR_PIDHIGH,0);
- memset(req->out.hdr + HDR_SS_FIELD, 0, 10);
-
- if (req->in.hdr) {
- /* copy the cmd, tid, pid, uid and mid from the request */
- SCVAL(req->out.hdr,HDR_COM,CVAL(req->in.hdr,HDR_COM));
- SSVAL(req->out.hdr,HDR_TID,SVAL(req->in.hdr,HDR_TID));
- SSVAL(req->out.hdr,HDR_PID,SVAL(req->in.hdr,HDR_PID));
- SSVAL(req->out.hdr,HDR_UID,SVAL(req->in.hdr,HDR_UID));
- SSVAL(req->out.hdr,HDR_MID,SVAL(req->in.hdr,HDR_MID));
- } else {
- SSVAL(req->out.hdr,HDR_TID,0);
- SSVAL(req->out.hdr,HDR_PID,0);
- SSVAL(req->out.hdr,HDR_UID,0);
- SSVAL(req->out.hdr,HDR_MID,0);
- }
-}
-
-/*
- work out the maximum data size we will allow for this reply, given
- the negotiated max_xmit. The basic reply packet must be setup before
- this call
-
- note that this is deliberately a signed integer reply
-*/
-int req_max_data(struct request_context *req)
-{
- int ret;
- ret = req->smb->negotiate.max_send;
- ret -= PTR_DIFF(req->out.data, req->out.hdr);
- if (ret < 0) ret = 0;
- return ret;
-}
-
-
-/*
- grow the allocation of the data buffer portion of a reply
- packet. Note that as this can reallocate the packet buffer this
- invalidates any local pointers into the packet.
-
- To cope with this req->out.ptr is supplied. This will be updated to
- point at the same offset into the packet as before this call
-*/
-static void req_grow_allocation(struct request_context *req, unsigned new_size)
-{
- int delta;
- char *buf2;
-
- delta = new_size - req->out.data_size;
- if (delta + req->out.size <= req->out.allocated) {
- /* it fits in the preallocation */
- return;
- }
-
- /* we need to realloc */
- req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
- buf2 = talloc_realloc(req->mem_ctx, req->out.buffer, req->out.allocated);
- if (buf2 == NULL) {
- smb_panic("out of memory in req_grow_allocation");
- }
-
- if (buf2 == req->out.buffer) {
- /* the malloc library gave us the same pointer */
- return;
- }
-
- /* update the pointers into the packet */
- req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
- req->out.ptr = buf2 + PTR_DIFF(req->out.ptr, req->out.buffer);
- req->out.vwv = buf2 + PTR_DIFF(req->out.vwv, req->out.buffer);
- req->out.hdr = buf2 + PTR_DIFF(req->out.hdr, req->out.buffer);
-
- req->out.buffer = buf2;
-}
-
-
-/*
- grow the data buffer portion of a reply packet. Note that as this
- can reallocate the packet buffer this invalidates any local pointers
- into the packet.
-
- To cope with this req->out.ptr is supplied. This will be updated to
- point at the same offset into the packet as before this call
-*/
-void req_grow_data(struct request_context *req, unsigned new_size)
-{
- int delta;
-
- if (!(req->control_flags & REQ_CONTROL_LARGE) && new_size > req_max_data(req)) {
- smb_panic("reply buffer too large!");
- }
-
- req_grow_allocation(req, new_size);
-
- delta = new_size - req->out.data_size;
-
- req->out.size += delta;
- req->out.data_size += delta;
-
- /* set the BCC to the new data size */
- SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
-}
-
-/*
- send a reply and destroy the request buffer
-
- note that this only looks at req->out.buffer and req->out.size, allowing manually
- constructed packets to be sent
-*/
-void req_send_reply(struct request_context *req)
-{
- if (req->out.size > NBT_HDR_SIZE) {
- _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
- }
-
- if (write_data(req->smb->socket.fd, req->out.buffer, req->out.size) != req->out.size) {
- smb_panic("failed to send reply\n");
- }
-
- req_destroy(req);
-}
-
-
-
-/*
- construct and send an error packet with a forced DOS error code
- this is needed to match win2000 behaviour for some parts of the protocol
-*/
-void req_reply_dos_error(struct request_context *req, uint8 eclass, uint16 ecode)
-{
- /* if the basic packet hasn't been setup yet then do it now */
- if (req->out.buffer == NULL) {
- req_setup_reply(req, 0, 0);
- }
-
- SCVAL(req->out.hdr, HDR_RCLS, eclass);
- SSVAL(req->out.hdr, HDR_ERR, ecode);
-
- SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) & ~FLAGS2_32_BIT_ERROR_CODES);
-
- req_send_reply(req);
-}
-
-/*
- construct and send an error packet, then destroy the request
- auto-converts to DOS error format when appropriate
-*/
-void req_reply_error(struct request_context *req, NTSTATUS status)
-{
- req_setup_reply(req, 0, 0);
-
- /* error returns never have any data */
- req_grow_data(req, 0);
-
- if (!lp_nt_status_support() || !(req->smb->negotiate.client_caps & CAP_STATUS32)) {
- /* convert to DOS error codes */
- uint8 eclass;
- uint32 ecode;
- ntstatus_to_dos(status, &eclass, &ecode);
- req_reply_dos_error(req, eclass, ecode);
- return;
- }
-
- SIVAL(req->out.hdr, HDR_RCLS, NT_STATUS_V(status));
- SSVAL(req->out.hdr, HDR_FLG2, SVAL(req->out.hdr, HDR_FLG2) | FLAGS2_32_BIT_ERROR_CODES);
-
- req_send_reply(req);
-}
-
-
-/*
- push a string into the data portion of the request packet, growing it if necessary
- this gets quite tricky - please be very careful to cover all cases when modifying this
-
- if dest is NULL, then put the string at the end of the data portion of the packet
-
- if dest_len is -1 then no limit applies
-*/
-size_t req_push_str(struct request_context *req, char *dest, const char *str, int dest_len, unsigned flags)
-{
- size_t len;
- unsigned grow_size;
- char *buf0;
- const int max_bytes_per_char = 3;
-
- if (!(flags & (STR_ASCII|STR_UNICODE))) {
- flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
- }
-
- if (dest == NULL) {
- dest = req->out.data + req->out.data_size;
- }
-
- if (dest_len != -1) {
- len = dest_len;
- } else {
- len = (strlen(str)+2) * max_bytes_per_char;
- }
-
- grow_size = len + PTR_DIFF(dest, req->out.data);
- buf0 = req->out.buffer;
-
- req_grow_allocation(req, grow_size);
-
- if (buf0 != req->out.buffer) {
- dest = req->out.buffer + PTR_DIFF(dest, buf0);
- }
-
- len = push_string(req->out.hdr, dest, str, len, flags);
-
- grow_size = len + PTR_DIFF(dest, req->out.data);
-
- if (grow_size > req->out.data_size) {
- req_grow_data(req, grow_size);
- }
-
- return len;
-}
-
-/*
- append raw bytes into the data portion of the request packet
- return the number of bytes added
-*/
-size_t req_append_bytes(struct request_context *req,
- const uint8 *bytes, size_t byte_len)
-{
- req_grow_allocation(req, byte_len + req->out.data_size);
- memcpy(req->out.data + req->out.data_size, bytes, byte_len);
- req_grow_data(req, byte_len + req->out.data_size);
- return byte_len;
-}
-/*
- append variable block (type 5 buffer) into the data portion of the request packet
- return the number of bytes added
-*/
-size_t req_append_var_block(struct request_context *req,
- const uint8 *bytes, uint16 byte_len)
-{
- req_grow_allocation(req, byte_len + 3 + req->out.data_size);
- SCVAL(req->out.data + req->out.data_size, 0, 5);
- SSVAL(req->out.data + req->out.data_size, 1, byte_len); /* add field length */
- if (byte_len > 0) {
- memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
- }
- req_grow_data(req, byte_len + 3 + req->out.data_size);
- return byte_len + 3;
-}
-/*
- pull a UCS2 string from a request packet, returning a talloced unix string
-
- the string length is limited by the 3 things:
- - the data size in the request (end of packet)
- - the passed 'byte_len' if it is not -1
- - the end of string (null termination)
-
- Note that 'byte_len' is the number of bytes in the packet
-
- on failure zero is returned and *dest is set to NULL, otherwise the number
- of bytes consumed in the packet is returned
-*/
-static size_t req_pull_ucs2(struct request_context *req, const char **dest, const char *src, int byte_len, unsigned flags)
-{
- int src_len, src_len2, alignment=0;
- ssize_t ret;
-
- if (!(flags & STR_NOALIGN) && ucs2_align(req->in.buffer, src, flags)) {
- src++;
- alignment=1;
- if (byte_len != -1) {
- byte_len--;
- }
- }
-
- if (flags & STR_NO_RANGE_CHECK) {
- src_len = byte_len;
- } else {
- src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
- if (src_len < 0) {
- *dest = NULL;
- return 0;
- }
-
- if (byte_len != -1 && src_len > byte_len) {
- src_len = byte_len;
- }
- }
-
- src_len2 = strnlen_w((const smb_ucs2_t *)src, src_len/2) * 2;
-
- if (src_len2 <= src_len - 2) {
- /* include the termination if we didn't reach the end of the packet */
- src_len2 += 2;
- }
-
- ret = convert_string_talloc(req->mem_ctx, CH_UCS2, CH_UNIX, src, src_len2, (const void **)dest);
-
- if (ret == -1) {
- *dest = NULL;
- return 0;
- }
-
- return src_len2 + alignment;
-}
-
-/*
- pull a ascii string from a request packet, returning a talloced string
-
- the string length is limited by the 3 things:
- - the data size in the request (end of packet)
- - the passed 'byte_len' if it is not -1
- - the end of string (null termination)
-
- Note that 'byte_len' is the number of bytes in the packet
-
- on failure zero is returned and *dest is set to NULL, otherwise the number
- of bytes consumed in the packet is returned
-*/
-static size_t req_pull_ascii(struct request_context *req, const char **dest, const char *src, int byte_len, unsigned flags)
-{
- int src_len, src_len2;
- ssize_t ret;
-
- if (flags & STR_NO_RANGE_CHECK) {
- src_len = byte_len;
- } else {
- src_len = req->in.data_size - PTR_DIFF(src, req->in.data);
- if (src_len < 0) {
- *dest = NULL;
- return 0;
- }
- if (byte_len != -1 && src_len > byte_len) {
- src_len = byte_len;
- }
- }
-
- src_len2 = strnlen(src, src_len);
- if (src_len2 <= src_len - 1) {
- /* include the termination if we didn't reach the end of the packet */
- src_len2++;
- }
-
- ret = convert_string_talloc(req->mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (const void **)dest);
-
- if (ret == -1) {
- *dest = NULL;
- return 0;
- }
-
- return src_len2;
-}
-
-/*
- pull a string from a request packet, returning a talloced string
-
- the string length is limited by the 3 things:
- - the data size in the request (end of packet)
- - the passed 'byte_len' if it is not -1
- - the end of string (null termination)
-
- Note that 'byte_len' is the number of bytes in the packet
-
- on failure zero is returned and *dest is set to NULL, otherwise the number
- of bytes consumed in the packet is returned
-*/
-size_t req_pull_string(struct request_context *req, const char **dest, const char *src, int byte_len, unsigned flags)
-{
- if (!(flags & STR_ASCII) &&
- (((flags & STR_UNICODE) || (req->flags2 & FLAGS2_UNICODE_STRINGS)))) {
- return req_pull_ucs2(req, dest, src, byte_len, flags);
- }
-
- return req_pull_ascii(req, dest, src, byte_len, flags);
-}
-
-
-/*
- pull a ASCII4 string buffer from a request packet, returning a talloced string
-
- an ASCII4 buffer is a null terminated string that has a prefix
- of the character 0x4. It tends to be used in older parts of the protocol.
-
- on failure *dest is set to the zero length string. This seems to
- match win2000 behaviour
-*/
-size_t req_pull_ascii4(struct request_context *req, const char **dest, const char *src, unsigned flags)
-{
- ssize_t ret;
-
- if (PTR_DIFF(src, req->in.data) + 1 > req->in.data_size) {
- /* win2000 treats this as the NULL string! */
- (*dest) = talloc_strdup(req->mem_ctx, "");
- return 0;
- }
-
- /* this consumes the 0x4 byte. We don't check whether the byte
- is actually 0x4 or not. This matches win2000 server
- behaviour */
- src++;
-
- ret = req_pull_string(req, dest, src, -1, flags);
- if (ret == -1) {
- (*dest) = talloc_strdup(req->mem_ctx, "");
- return 1;
- }
-
- return ret + 1;
-}
-
-/*
- pull a DATA_BLOB from a request packet, returning a talloced blob
-
- return False if any part is outside the data portion of the packet
-*/
-BOOL req_pull_blob(struct request_context *req, const char *src, int len, DATA_BLOB *blob)
-{
- if (len != 0 && req_data_oob(req, src, len)) {
- return False;
- }
-
- (*blob) = data_blob_talloc(req->mem_ctx, src, len);
-
- return True;
-}
-
-/* check that a lump of data in a request is within the bounds of the data section of
- the packet */
-BOOL req_data_oob(struct request_context *req, const char *ptr, uint32 count)
-{
- if (count == 0) {
- return False;
- }
-
- /* be careful with wraparound! */
- if (ptr < req->in.data ||
- ptr >= req->in.data + req->in.data_size ||
- count > req->in.data_size ||
- ptr + count > req->in.data + req->in.data_size) {
- return True;
- }
- return False;
-}
-
-
-/*
- pull an open file handle from a packet, taking account of the chained_fnum
-*/
-uint16 req_fnum(struct request_context *req, const char *base, unsigned offset)
-{
- if (req->chained_fnum != -1) {
- return req->chained_fnum;
- }
- return SVAL(base, offset);
-}
diff --git a/source4/smbd/search.c b/source4/smbd/search.c
deleted file mode 100644
index 9d01a0e98f..0000000000
--- a/source4/smbd/search.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMBsearch handling
- Copyright (C) Andrew Tridgell 2003
- Copyright (C) James J Myers 2003 <myersjj@samba.org>
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/*
- This file handles the parsing of transact2 requests
-*/
-
-#include "includes.h"
-
-/* check req->async.status and if not OK then send an error reply */
-#define CHECK_ASYNC_STATUS do { \
- if (!NT_STATUS_IS_OK(req->async.status)) { \
- req_reply_error(req, req->async.status); \
- return; \
- }} while (0)
-
-/*
- check if the backend wants to handle the request asynchronously.
- if it wants it handled synchronously then call the send function
- immediately
-*/
-#define REQ_ASYNC_TAIL do { \
- if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
- req->async.send_fn(req); \
- }} while (0)
-
-/* useful wrapper for talloc with NO_MEMORY reply */
-#define REQ_TALLOC(ptr, size) do { \
- ptr = talloc(req->mem_ctx, size); \
- if (!ptr) { \
- req_reply_error(req, NT_STATUS_NO_MEMORY); \
- return; \
- }} while (0)
-
-#define CHECK_MIN_BLOB_SIZE(blob, size) do { \
- if ((blob)->length < (size)) { \
- return NT_STATUS_INFO_LENGTH_MISMATCH; \
- }} while (0)
-
-/* a structure to encapsulate the state information about
- * an in-progress search first/next operation */
-struct search_state {
- struct request_context *req;
- union smb_search_data *file;
- uint16 last_entry_offset;
-};
-
-/*
- fill a single entry in a search find reply
-*/
-static void find_fill_info(struct request_context *req,
- union smb_search_data *file)
-{
- char *p = req->out.data + req->out.data_size;
- uint32 dos_date;
- char search_name[13];
-
- DEBUG(9,("find_fill_info: input file data: attr=0x%x size=%u time=0x%x name=%13s\n",
- file->search.attrib, file->search.size,
- (uint32)file->search.write_time, file->search.name));
-
- p += req_append_bytes(req, file->search.search_id.data, 21);
- p += req_append_bytes(req, (char*)&file->search.attrib, 1);
- put_dos_date((char*)&dos_date, 0, file->search.write_time);
- p += req_append_bytes(req, (char*)&dos_date, 4);
- p += req_append_bytes(req, (char*)&file->search.size, 4);
- memset(&search_name[0], ' ', 13);
- memcpy(&search_name[0], file->search.name,
- MAX(13, strlen(file->search.name)));
- p += req_append_bytes(req, &search_name[0], 13);
-}
-
-/* callback function for search first/next */
-static BOOL find_callback(void *private, union smb_search_data *file)
-{
- struct search_state *state = (struct search_state *)private;
-
- find_fill_info(state->req, file);
-
- return True;
-}
-
-/****************************************************************************
- Reply to a search.
-****************************************************************************/
-void reply_search(struct request_context *req)
-{
- union smb_search_first *sf;
- union smb_search_next *sn;
- DATA_BLOB resume_key;
- uint16 resume_key_length;
- struct search_state state;
- char *p;
-
- REQ_TALLOC(sf, sizeof(*sf));
-
- /* parse request */
- if (req->in.wct != 2) {
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- p = req->in.data;
- p += req_pull_ascii4(req, &sf->search_first.in.pattern,
- p, STR_TERMINATE);
- if (!sf->search_first.in.pattern) {
- req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
- return;
- }
- /* pull in type 5 byte and length */
- if (!req_pull_blob(req, p, 3, &resume_key))
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- resume_key_length = SVAL(resume_key.data, 1);
- p += 3;
- DEBUG(19,("reply_search: pattern=%s, key_length=%d\n",
- sf->search_first.in.pattern, resume_key_length));
-
- /* setup state for callback */
- state.req = req;
- state.file = NULL;
- state.last_entry_offset = 0;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
- req_append_var_block(req, NULL, 0);
-
- if (resume_key_length > 0) {
- /* do a search next operation */
- REQ_TALLOC(sn, sizeof(*sn));
- sn->search_next.level = RAW_SEARCH_SEARCH;
- req->async.private = sn;
- if (!req_pull_blob(req, req->in.data, resume_key_length,
- &(sn->search_next.in.search_id)))
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- sn->search_next.in.search_attrib = SVAL(req->in.vwv, VWV(1));
- sn->search_next.in.max_count = SVAL(req->in.vwv, VWV(0));
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->search_next(req,
- sn, &state, find_callback);
- SSVAL(req->out.vwv, VWV(0), sn->search_next.out.count);
- } else {
- /* do a search first operation */
- req->async.private = sf;
- sf->search_first.level = RAW_SEARCH_SEARCH;
- sf->search_first.in.search_attrib = SVAL(req->in.vwv, VWV(1));
- sf->search_first.in.max_count = SVAL(req->in.vwv, VWV(0));
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->search_first(req,
- sf, &state, find_callback);
- SSVAL(req->out.vwv, VWV(0), sf->search_first.out.count);
- }
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to a fclose (async reply)
-****************************************************************************/
-static void reply_fclose_send(struct request_context *req)
-{
- CHECK_ASYNC_STATUS;
-
- /* construct reply */
- req_setup_reply(req, 1, 0);
-
- req_send_reply(req);
-}
-
-
-/****************************************************************************
- Reply to fclose (stop directory search).
-****************************************************************************/
-void reply_fclose(struct request_context *req)
-{
- union smb_search_next *sn;
- DATA_BLOB resume_key;
- uint16 resume_key_length;
-
- REQ_TALLOC(sn, sizeof(*sn));
-
- /* parse request */
- if (req->in.wct != 2) {
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- sn->search_next.level = RAW_SEARCH_FCLOSE;
-
- /* pull in type 5 byte and length */
- if (!req_pull_blob(req, req->in.data, 3, &resume_key))
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- resume_key_length = SVAL(resume_key.data, 1);
- if (resume_key_length > 0) {
- /* do a search close operation */
- if (!req_pull_blob(req, req->in.data, resume_key_length,
- &(sn->search_next.in.search_id)))
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
- } else
- req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
-
- req->async.send_fn = reply_fclose_send;
- req->async.private = sn;
-
- /* call backend */
- req->async.status = req->conn->ntvfs_ops->search_next(req, sn,
- NULL, NULL);
-
- REQ_ASYNC_TAIL;
-}
diff --git a/source4/smbd/service.c b/source4/smbd/service.c
deleted file mode 100644
index d219e6cee0..0000000000
--- a/source4/smbd/service.c
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- service (connection) handling
- Copyright (C) Andrew Tridgell 1992-2003
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-
-/****************************************************************************
- Add a home service. Returns the new service number or -1 if fail.
-****************************************************************************/
-int add_home_service(const char *service, const char *username, const char *homedir)
-{
- int iHomeService;
-
- if (!service || !homedir)
- return -1;
-
- if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
- return -1;
-
- /*
- * If this is a winbindd provided username, remove
- * the domain component before adding the service.
- * Log a warning if the "path=" parameter does not
- * include any macros.
- */
-
- {
- const char *p = strchr(service,*lp_winbind_separator());
-
- /* We only want the 'user' part of the string */
- if (p) {
- service = p + 1;
- }
- }
-
- if (!lp_add_home(service, iHomeService, username, homedir)) {
- return -1;
- }
-
- return lp_servicenumber(service);
-
-}
-
-
-/**
- * Find a service entry. service is always in dos codepage.
- *
- * @param service is modified (to canonical form??)
- **/
-static int find_service(const char *service)
-{
- int iService;
-
- iService = lp_servicenumber(service);
-
- /* now handle the special case of a home directory */
- if (iService == -1) {
- char *phome_dir = get_user_home_dir(service);
-
- if(!phome_dir) {
- /*
- * Try mapping the servicename, it may
- * be a Windows to unix mapped user name.
- */
-/* REWRITE:
- if (map_username(service))
- phome_dir = get_user_home_dir(service);
-*/
- }
-
- DEBUG(3,("checking for home directory %s gave %s\n",service,
- phome_dir?phome_dir:"(NULL)"));
-
- iService = add_home_service(service,service /* 'username' */, phome_dir);
- }
-
- /* If we still don't have a service, attempt to add it as a printer. */
- if (iService == -1) {
- int iPrinterService;
-
- if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
- char *pszTemp;
-
- DEBUG(3,("checking whether %s is a valid printer name...\n", service));
- pszTemp = lp_printcapname();
- if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) {
- DEBUG(3,("%s is a valid printer name\n", service));
- DEBUG(3,("adding %s as a printer service\n", service));
- lp_add_printer(service, iPrinterService);
- iService = lp_servicenumber(service);
- if (iService < 0)
- DEBUG(0,("failed to add %s as a printer service!\n", service));
- } else {
- DEBUG(3,("%s is not a valid printer name\n", service));
- }
- }
- }
-
- /* Check for default vfs service? Unsure whether to implement this */
- if (iService == -1) {
- }
-
- /* just possibly it's a default service? */
- if (iService == -1) {
- char *pdefservice = lp_defaultservice();
- if (pdefservice && *pdefservice &&
- !strequal(pdefservice,service) &&
- !strstr(service,"..")) {
- /*
- * We need to do a local copy here as lp_defaultservice()
- * returns one of the rotating lp_string buffers that
- * could get overwritten by the recursive find_service() call
- * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
- */
- pstring defservice;
- pstrcpy(defservice, pdefservice);
- iService = find_service(defservice);
- if (iService >= 0) {
- /* REWRITE: all_string_sub(service, "_","/",0); */
- iService = lp_add_service(service, iService);
- }
- }
- }
-
- if (iService >= 0 && !VALID_SNUM(iService)) {
- DEBUG(0,("Invalid snum %d for %s\n",iService, service));
- iService = -1;
- }
-
- if (iService == -1) {
- DEBUG(3,("find_service() failed to find service %s\n", service));
- }
-
- return iService;
-}
-
-
-/****************************************************************************
- Make a connection, given the snum to connect to, and the vuser of the
- connecting user if appropriate.
-****************************************************************************/
-static NTSTATUS make_connection_snum(struct request_context *req,
- int snum, enum ntvfs_type type,
- DATA_BLOB password,
- const char *dev)
-{
- struct tcon_context *conn;
- NTSTATUS status;
-
- conn = conn_new(req->smb);
- if (!conn) {
- DEBUG(0,("Couldn't find free connection.\n"));
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
- req->conn = conn;
-
- conn->service = snum;
- conn->type = type;
-
- /*
- * New code to check if there's a share security descripter
- * added from NT server manager. This is done after the
- * smb.conf checks are done as we need a uid and token. JRA.
- *
- */
-
- if (!share_access_check(req, conn, snum, SA_RIGHT_FILE_WRITE_DATA)) {
- if (!share_access_check(req, conn, snum, SA_RIGHT_FILE_READ_DATA)) {
- /* No access, read or write. */
- DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
- lp_servicename(snum)));
- conn_free(req->smb, conn);
- return NT_STATUS_ACCESS_DENIED;
- } else {
- conn->read_only = True;
- }
- }
-
- /* check number of connections */
- if (!claim_connection(conn,
- lp_servicename(SNUM(conn)),
- lp_max_connections(SNUM(conn)),
- False,0)) {
- DEBUG(1,("too many connections - rejected\n"));
- conn_free(req->smb, conn);
- return NT_STATUS_INSUFFICIENT_RESOURCES;
- }
-
- /* init ntvfs function pointers */
- status = ntvfs_init_connection(req);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0, ("ntvfs_init_connection failed for service %s\n", lp_servicename(SNUM(conn))));
- conn_free(req->smb, conn);
- return status;
- }
-
- /* Invoke NTVFS connection hook */
- if (conn->ntvfs_ops->connect) {
- status = conn->ntvfs_ops->connect(req, lp_servicename(snum));
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("make_connection: NTVFS make connection failed!\n"));
- conn_free(req->smb, conn);
- return status;
- }
- }
-
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Make a connection to a service.
- *
- * @param service
-****************************************************************************/
-static NTSTATUS make_connection(struct request_context *req,
- const char *service, DATA_BLOB password,
- const char *dev, uint16 vuid)
-{
- int snum;
- enum ntvfs_type type;
- const char *type_str;
-
- /* the service might be of the form \\SERVER\SHARE. Should we put
- the server name we get from this somewhere? */
- if (strncmp(service, "\\\\", 2) == 0) {
- char *p = strchr(service+2, '\\');
- if (p) {
- service = p + 1;
- }
- }
-
- snum = find_service(service);
-
- if (snum == -1) {
- DEBUG(0,("%s couldn't find service %s\n",
- sub_get_remote_machine(), service));
- return NT_STATUS_BAD_NETWORK_NAME;
- }
-
- /* work out what sort of connection this is */
- if (strcmp(lp_fstype(snum), "IPC") == 0) {
- type = NTVFS_IPC;
- type_str = "IPC";
- } else if (lp_print_ok(snum)) {
- type = NTVFS_PRINT;
- type_str = "LPT:";
- } else {
- type = NTVFS_DISK;
- type_str = "A:";
- }
-
- if (strcmp(dev, "?????") != 0 && strcasecmp(type_str, dev) != 0) {
- /* the client gave us the wrong device type */
- return NT_STATUS_BAD_DEVICE_TYPE;
- }
-
- return make_connection_snum(req, snum, type, password, dev);
-}
-
-/****************************************************************************
-close a cnum
-****************************************************************************/
-void close_cnum(struct tcon_context *conn)
-{
- DEBUG(3, ("%s (%s) closed connection to service %s\n",
- sub_get_remote_machine(),conn->smb->socket.client_addr,
- lp_servicename(SNUM(conn))));
-
- yield_connection(conn, lp_servicename(SNUM(conn)));
-
- /* tell the ntvfs backend that we are disconnecting */
- conn->ntvfs_ops->disconnect(conn);
-
- conn_free(conn->smb, conn);
-}
-
-
-
-/*
- backend for tree connect call
-*/
-NTSTATUS tcon_backend(struct request_context *req, union smb_tcon *con)
-{
- NTSTATUS status;
-
- /* can only do bare tcon in share level security */
- if (req->user_ctx == NULL && lp_security() != SEC_SHARE) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- if (con->generic.level == RAW_TCON_TCON) {
- DATA_BLOB password;
- password = data_blob(con->tcon.in.password, strlen(con->tcon.in.password) + 1);
-
- status = make_connection(req, con->tcon.in.service, password, con->tcon.in.dev, req->user_ctx->vuid);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- con->tcon.out.max_xmit = req->smb->negotiate.max_recv;
- con->tcon.out.cnum = req->conn->cnum;
-
- return status;
- }
-
- status = make_connection(req, con->tconx.in.path, con->tconx.in.password,
- con->tconx.in.device, req->user_ctx->vuid);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- con->tconx.out.cnum = req->conn->cnum;
- con->tconx.out.dev_type = talloc_strdup(req->mem_ctx, req->conn->dev_type);
- con->tconx.out.fs_type = talloc_strdup(req->mem_ctx, req->conn->fs_type);
- con->tconx.out.options = SMB_SUPPORT_SEARCH_BITS | (lp_csc_policy(req->conn->service) << 2);
- if (lp_msdfs_root(req->conn->service) && lp_host_msdfs()) {
- con->tconx.out.options |= SMB_SHARE_IN_DFS;
- }
-
- return status;
-}
diff --git a/source4/smbd/session.c b/source4/smbd/session.c
deleted file mode 100644
index 7f85fca2ac..0000000000
--- a/source4/smbd/session.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- session handling for utmp and PAM
- Copyright (C) tridge@samba.org 2001
- Copyright (C) abartlet@pcug.org.au 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* a "session" is claimed when we do a SessionSetupX operation
- and is yielded when the corresponding vuid is destroyed.
-
- sessions are used to populate utmp and PAM session structures
-*/
-
-#include "includes.h"
-
-/* called when a session is created */
-BOOL session_claim(struct server_context *smb, user_struct *vuser)
-{
- DEBUG(0,("rewrite: Not doing session claim\n"));
- return True;
-}
-
-/* called when a session is destroyed */
-void session_yield(user_struct *vuser)
-{
- DEBUG(0,("rewrite: Not doing session yield\n"));
-}
-
diff --git a/source4/smbd/sesssetup.c b/source4/smbd/sesssetup.c
deleted file mode 100644
index 14e300c191..0000000000
--- a/source4/smbd/sesssetup.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- handle SMBsessionsetup
- Copyright (C) Andrew Tridgell 1998-2001
- Copyright (C) Andrew Bartlett 2001
- Copyright (C) Jim McDonough 2002
- Copyright (C) Luke Howard 2003
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/*
- setup the OS, Lanman and domain portions of a session setup reply
-*/
-static void sesssetup_common_strings(struct request_context *req,
- char **os, char **lanman, char **domain)
-{
- (*os) = talloc_asprintf(req->mem_ctx, "Unix");
- (*lanman) = talloc_asprintf(req->mem_ctx, "Samba %s", SAMBA_VERSION_STRING);
- (*domain) = talloc_asprintf(req->mem_ctx, "%s", lp_workgroup());
-}
-
-
-/*
- handler for old style session setup
-*/
-static NTSTATUS sesssetup_old(struct request_context *req, union smb_sesssetup *sess)
-{
- NTSTATUS status;
- auth_usersupplied_info *user_info = NULL;
- auth_serversupplied_info *server_info = NULL;
- DATA_BLOB null_blob;
-
- if (!req->smb->negotiate.done_sesssetup) {
- req->smb->negotiate.max_send = sess->old.in.bufsize;
- }
-
- null_blob.length = 0;
-
- status = make_user_info_for_reply_enc(&user_info,
- sess->old.in.user, sess->old.in.domain,
- sess->old.in.password,
- null_blob);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- status = req->smb->negotiate.auth_context->check_ntlm_password(req->smb->negotiate.auth_context,
- user_info,
- &server_info);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- sess->old.out.action = 0;
- sess->old.out.vuid = register_vuid(req->smb, server_info, sess->old.in.user);
- sesssetup_common_strings(req,
- &sess->old.out.os,
- &sess->old.out.lanman,
- &sess->old.out.domain);
-
- return NT_STATUS_OK;
-}
-
-
-/*
- handler for NT1 style session setup
-*/
-static NTSTATUS sesssetup_nt1(struct request_context *req, union smb_sesssetup *sess)
-{
- NTSTATUS status;
- auth_usersupplied_info *user_info = NULL;
- auth_serversupplied_info *server_info = NULL;
-
- if (!req->smb->negotiate.done_sesssetup) {
- req->smb->negotiate.max_send = sess->nt1.in.bufsize;
- req->smb->negotiate.client_caps = sess->nt1.in.capabilities;
- }
-
- status = make_user_info_for_reply_enc(&user_info,
- sess->nt1.in.user, sess->nt1.in.domain,
- sess->nt1.in.password1,
- sess->nt1.in.password2);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- status = req->smb->negotiate.auth_context->check_ntlm_password(req->smb->negotiate.auth_context,
- user_info,
- &server_info);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
- sess->nt1.out.action = 0;
- sess->nt1.out.vuid = register_vuid(req->smb, server_info, sess->old.in.user);
- sesssetup_common_strings(req,
- &sess->nt1.out.os,
- &sess->nt1.out.lanman,
- &sess->nt1.out.domain);
-
- return NT_STATUS_OK;
-}
-
-
-/*
- handler for SPNEGO style session setup
-*/
-static NTSTATUS sesssetup_spnego(struct request_context *req, union smb_sesssetup *sess)
-{
- /* defer this one for now */
- return NT_STATUS_INVALID_LEVEL;
-}
-
-/*
- backend for sessionsetup call - this takes all 3 varients of the call
-*/
-NTSTATUS sesssetup_backend(struct request_context *req,
- union smb_sesssetup *sess)
-{
- switch (sess->generic.level) {
- case RAW_SESSSETUP_OLD:
- return sesssetup_old(req, sess);
- case RAW_SESSSETUP_NT1:
- return sesssetup_nt1(req, sess);
- case RAW_SESSSETUP_SPNEGO:
- return sesssetup_spnego(req, sess);
- }
-
- req->smb->negotiate.done_sesssetup = True;
-
- return NT_STATUS_INVALID_LEVEL;
-}
-
-
diff --git a/source4/smbd/tcon.c b/source4/smbd/tcon.c
deleted file mode 100644
index b28b04f643..0000000000
--- a/source4/smbd/tcon.c
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/source4/smbd/trans2.c b/source4/smbd/trans2.c
deleted file mode 100644
index 6a15aad137..0000000000
--- a/source4/smbd/trans2.c
+++ /dev/null
@@ -1,1411 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- transaction2 handling
- Copyright (C) Andrew Tridgell 2003
-
- 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
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/*
- This file handles the parsing of transact2 requests
-*/
-
-#include "includes.h"
-
-
-#define CHECK_MIN_BLOB_SIZE(blob, size) do { \
- if ((blob)->length < (size)) { \
- return NT_STATUS_INFO_LENGTH_MISMATCH; \
- }} while (0)
-
-/* grow the data allocation size of a trans2 reply - this guarantees
- that requests to grow the data size later will not change the
- pointer */
-static void trans2_grow_data_allocation(struct request_context *req,
- struct smb_trans2 *trans,
- uint16 new_size)
-{
- if (new_size <= trans->out.data.length) {
- return;
- }
- trans->out.data.data = talloc_realloc(req->mem_ctx, trans->out.data.data, new_size);
-}
-
-
-/* grow the data size of a trans2 reply */
-static void trans2_grow_data(struct request_context *req,
- struct smb_trans2 *trans,
- uint16 new_size)
-{
- trans2_grow_data_allocation(req, trans, new_size);
- trans->out.data.length = new_size;
-}
-
-/* grow the data, zero filling any new bytes */
-static void trans2_grow_data_fill(struct request_context *req,
- struct smb_trans2 *trans,
- uint16 new_size)
-{
- uint16 old_size = trans->out.data.length;
- trans2_grow_data(req, trans, new_size);
- if (new_size > old_size) {
- memset(trans->out.data.data + old_size, 0, new_size - old_size);
- }
-}
-
-
-/* setup a trans2 reply, given the data and params sizes */
-static void trans2_setup_reply(struct request_context *req,
- struct smb_trans2 *trans,
- uint16 param_size, uint16 data_size,
- uint16 setup_count)
-{
- trans->out.setup_count = setup_count;
- if (setup_count != 0) {
- trans->out.setup = talloc_zero(req->mem_ctx, sizeof(uint16) * setup_count);
- }
- trans->out.params = data_blob_talloc(req->mem_ctx, NULL, param_size);
- trans->out.data = data_blob_talloc(req->mem_ctx, NULL, data_size);
-}
-
-
-/*
- pull a string from a blob in a trans2 request
-*/
-static size_t trans2_pull_blob_string(struct request_context *req,
- const DATA_BLOB *blob,
- uint16 offset,
- const char **str,
- int flags)
-{
- /* we use STR_NO_RANGE_CHECK because the params are allocated
- separately in a DATA_BLOB, so we need to do our own range
- checking */
- if (offset >= blob->length) {
- *str = NULL;
- return 0;
- }
-
- return req_pull_string(req, str,
- blob->data + offset,
- blob->length - offset,
- STR_NO_RANGE_CHECK | flags);
-}
-
-/*
- push a string into the data section of a trans2 request
- return the number of bytes consumed in the output
-*/
-static size_t trans2_push_data_string(struct request_context *req,
- struct smb_trans2 *trans,
- uint16 len_offset,
- uint16 offset,
- const WIRE_STRING *str,
- int dest_len,
- int flags)
-{
- int alignment = 0, ret = 0, pkt_len;
-
- /* we use STR_NO_RANGE_CHECK because the params are allocated
- separately in a DATA_BLOB, so we need to do our own range
- checking */
- if (!str->s || offset >= trans->out.data.length) {
- if (flags & STR_LEN8BIT) {
- SCVAL(trans->out.data.data, len_offset, 0);
- } else {
- SIVAL(trans->out.data.data, len_offset, 0);
- }
- return 0;
- }
-
- flags |= STR_NO_RANGE_CHECK;
-
- if (dest_len == -1 || (dest_len > trans->out.data.length - offset)) {
- dest_len = trans->out.data.length - offset;
- }
-
- if (!(flags & (STR_ASCII|STR_UNICODE))) {
- flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
- }
-
- if ((offset&1) && (flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
- alignment = 1;
- if (dest_len > 0) {
- SCVAL(trans->out.data.data + offset, 0, 0);
- ret = push_string(NULL, trans->out.data.data + offset + 1, str->s, dest_len-1, flags);
- }
- } else {
- ret = push_string(NULL, trans->out.data.data + offset, str->s, dest_len, flags);
- }
-
- /* sometimes the string needs to be terminated, but the length
- on the wire must not include the termination! */
- pkt_len = ret;
-
- if ((flags & STR_LEN_NOTERM) && (flags & STR_TERMINATE)) {
- if ((flags & STR_UNICODE) && ret >= 2) {
- pkt_len = ret-2;
- }
- if ((flags & STR_ASCII) && ret >= 1) {
- pkt_len = ret-1;
- }
- }
-
- if (flags & STR_LEN8BIT) {
- SCVAL(trans->out.data.data, len_offset, pkt_len);
- } else {
- SIVAL(trans->out.data.data, len_offset, pkt_len);
- }
-
- return ret + alignment;
-}
-
-/*
- append a string to the data section of a trans2 reply
- len_offset points to the place in the packet where the length field
- should go
-*/
-static void trans2_append_data_string(struct request_context *req,
- struct smb_trans2 *trans,
- const WIRE_STRING *str,
- uint_t len_offset,
- int flags)
-{
- size_t ret;
- uint16 offset;
- const int max_bytes_per_char = 3;
-
- offset = trans->out.data.length;
- trans2_grow_data(req, trans, offset + (2+strlen(str->s))*max_bytes_per_char);
- ret = trans2_push_data_string(req, trans, len_offset, offset, str, -1, flags);
- trans2_grow_data(req, trans, offset + ret);
-}
-
-
-/*
- trans2 qfsinfo implementation
-*/
-static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_fsinfo fsinfo;
- NTSTATUS status;
- uint16 level;
- uint_t i;
- DATA_BLOB guid_blob;
-
- /* make sure we got enough parameters */
- if (trans->in.params.length != 2) {
- return NT_STATUS_FOOBAR;
- }
-
- level = SVAL(trans->in.params.data, 0);
-
- switch (level) {
- case SMB_QFS_ALLOCATION:
- fsinfo.allocation.level = RAW_QFS_ALLOCATION;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 18, 0);
-
- SIVAL(trans->out.data.data, 0, fsinfo.allocation.out.fs_id);
- SIVAL(trans->out.data.data, 4, fsinfo.allocation.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 8, fsinfo.allocation.out.total_alloc_units);
- SIVAL(trans->out.data.data, 12, fsinfo.allocation.out.avail_alloc_units);
- SSVAL(trans->out.data.data, 16, fsinfo.allocation.out.bytes_per_sector);
-
- return NT_STATUS_OK;
-
- case SMB_QFS_VOLUME:
- fsinfo.volume.level = RAW_QFS_VOLUME;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 5, 0);
-
- SIVAL(trans->out.data.data, 0, fsinfo.volume.out.serial_number);
- /* w2k3 implements this incorrectly for unicode - it
- * leaves the last byte off the string */
- trans2_append_data_string(req, trans,
- &fsinfo.volume.out.volume_name,
- 4, STR_LEN8BIT|STR_NOALIGN);
-
- return NT_STATUS_OK;
-
- case SMB_QFS_VOLUME_INFO:
- case SMB_QFS_VOLUME_INFORMATION:
- fsinfo.volume_info.level = RAW_QFS_VOLUME_INFO;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 18, 0);
-
- push_nttime(trans->out.data.data, 0, &fsinfo.volume_info.out.create_time);
- SIVAL(trans->out.data.data, 8, fsinfo.volume_info.out.serial_number);
- trans2_append_data_string(req, trans,
- &fsinfo.volume_info.out.volume_name,
- 12, STR_UNICODE);
-
- return NT_STATUS_OK;
-
- case SMB_QFS_SIZE_INFO:
- case SMB_QFS_SIZE_INFORMATION:
- fsinfo.size_info.level = RAW_QFS_SIZE_INFO;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 24, 0);
-
- SBVAL(trans->out.data.data, 0, fsinfo.size_info.out.total_alloc_units);
- SBVAL(trans->out.data.data, 8, fsinfo.size_info.out.avail_alloc_units);
- SIVAL(trans->out.data.data, 16, fsinfo.size_info.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 20, fsinfo.size_info.out.bytes_per_sector);
-
- return NT_STATUS_OK;
-
- case SMB_QFS_DEVICE_INFO:
- case SMB_QFS_DEVICE_INFORMATION:
- fsinfo.device_info.level = RAW_QFS_DEVICE_INFO;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- trans2_setup_reply(req, trans, 0, 8, 0);
- SIVAL(trans->out.data.data, 0, fsinfo.device_info.out.device_type);
- SIVAL(trans->out.data.data, 4, fsinfo.device_info.out.characteristics);
- return NT_STATUS_OK;
-
-
- case SMB_QFS_ATTRIBUTE_INFO:
- case SMB_QFS_ATTRIBUTE_INFORMATION:
- fsinfo.attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 12, 0);
-
- SIVAL(trans->out.data.data, 0, fsinfo.attribute_info.out.fs_attr);
- SIVAL(trans->out.data.data, 4, fsinfo.attribute_info.out.max_file_component_length);
- /* this must not be null terminated or win98 gets
- confused! also note that w2k3 returns this as
- unicode even when ascii is negotiated */
- trans2_append_data_string(req, trans,
- &fsinfo.attribute_info.out.fs_type,
- 8, STR_UNICODE);
- return NT_STATUS_OK;
-
-
- case SMB_QFS_QUOTA_INFORMATION:
- fsinfo.quota_information.level = RAW_QFS_QUOTA_INFORMATION;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 48, 0);
-
- SBVAL(trans->out.data.data, 0, fsinfo.quota_information.out.unknown[0]);
- SBVAL(trans->out.data.data, 8, fsinfo.quota_information.out.unknown[1]);
- SBVAL(trans->out.data.data, 16, fsinfo.quota_information.out.unknown[2]);
- SBVAL(trans->out.data.data, 24, fsinfo.quota_information.out.quota_soft);
- SBVAL(trans->out.data.data, 32, fsinfo.quota_information.out.quota_hard);
- SBVAL(trans->out.data.data, 40, fsinfo.quota_information.out.quota_flags);
-
- return NT_STATUS_OK;
-
-
- case SMB_QFS_FULL_SIZE_INFORMATION:
- fsinfo.full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 32, 0);
-
- SBVAL(trans->out.data.data, 0, fsinfo.full_size_information.out.total_alloc_units);
- SBVAL(trans->out.data.data, 8, fsinfo.full_size_information.out.call_avail_alloc_units);
- SBVAL(trans->out.data.data, 16, fsinfo.full_size_information.out.actual_avail_alloc_units);
- SIVAL(trans->out.data.data, 24, fsinfo.full_size_information.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 28, fsinfo.full_size_information.out.bytes_per_sector);
-
- return NT_STATUS_OK;
-
- case SMB_QFS_OBJECTID_INFORMATION:
- fsinfo.objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
-
- status = req->conn->ntvfs_ops->fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 64, 0);
-
- status = ndr_push_struct_blob(&guid_blob, req->mem_ctx,
- &fsinfo.objectid_information.out.guid,
- (ndr_push_flags_fn_t)ndr_push_GUID);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- memcpy(trans->out.data.data, guid_blob.data, GUID_SIZE);
-
- for (i=0;i<6;i++) {
- SBVAL(trans->out.data.data, 16 + 8*i, fsinfo.objectid_information.out.unknown[i]);
- }
- return NT_STATUS_OK;
- }
-
- return NT_STATUS_INVALID_LEVEL;
-}
-
-/*
- fill in the reply from a qpathinfo or qfileinfo call
-*/
-static NTSTATUS trans2_fileinfo_fill(struct request_context *req, struct smb_trans2 *trans,
- union smb_fileinfo *st)
-{
- uint_t i;
-
- switch (st->generic.level) {
- case RAW_FILEINFO_GENERIC:
- case RAW_FILEINFO_GETATTR:
- case RAW_FILEINFO_GETATTRE:
- /* handled elsewhere */
- return NT_STATUS_INVALID_LEVEL;
-
- case RAW_FILEINFO_BASIC_INFO:
- case RAW_FILEINFO_BASIC_INFORMATION:
- trans2_setup_reply(req, trans, 2, 40, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
- push_nttime(trans->out.data.data, 0, &st->basic_info.out.create_time);
- push_nttime(trans->out.data.data, 8, &st->basic_info.out.access_time);
- push_nttime(trans->out.data.data, 16, &st->basic_info.out.write_time);
- push_nttime(trans->out.data.data, 24, &st->basic_info.out.change_time);
- SIVAL(trans->out.data.data, 32, st->basic_info.out.attrib);
- SIVAL(trans->out.data.data, 36, 0); /* padding */
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_STANDARD:
- trans2_setup_reply(req, trans, 2, 22, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
- put_dos_date2(trans->out.data.data, 0, st->standard.out.create_time);
- put_dos_date2(trans->out.data.data, 4, st->standard.out.access_time);
- put_dos_date2(trans->out.data.data, 8, st->standard.out.write_time);
- SIVAL(trans->out.data.data, 12, st->standard.out.size);
- SIVAL(trans->out.data.data, 16, st->standard.out.alloc_size);
- SSVAL(trans->out.data.data, 20, st->standard.out.attrib);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_EA_SIZE:
- trans2_setup_reply(req, trans, 2, 26, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
- put_dos_date2(trans->out.data.data, 0, st->ea_size.out.create_time);
- put_dos_date2(trans->out.data.data, 4, st->ea_size.out.access_time);
- put_dos_date2(trans->out.data.data, 8, st->ea_size.out.write_time);
- SIVAL(trans->out.data.data, 12, st->ea_size.out.size);
- SIVAL(trans->out.data.data, 16, st->ea_size.out.alloc_size);
- SSVAL(trans->out.data.data, 20, st->ea_size.out.attrib);
- SIVAL(trans->out.data.data, 22, st->ea_size.out.ea_size);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
- trans2_setup_reply(req, trans, 2, 56, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
- push_nttime(trans->out.data.data, 0, &st->network_open_information.out.create_time);
- push_nttime(trans->out.data.data, 8, &st->network_open_information.out.access_time);
- push_nttime(trans->out.data.data, 16, &st->network_open_information.out.write_time);
- push_nttime(trans->out.data.data, 24, &st->network_open_information.out.change_time);
- SBVAL(trans->out.data.data, 32, st->network_open_information.out.alloc_size);
- SBVAL(trans->out.data.data, 40, st->network_open_information.out.size);
- SIVAL(trans->out.data.data, 48, st->network_open_information.out.attrib);
- SIVAL(trans->out.data.data, 52, 0); /* padding */
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_STANDARD_INFO:
- case RAW_FILEINFO_STANDARD_INFORMATION:
- trans2_setup_reply(req, trans, 2, 24, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SBVAL(trans->out.data.data, 0, st->standard_info.out.alloc_size);
- SBVAL(trans->out.data.data, 8, st->standard_info.out.size);
- SIVAL(trans->out.data.data, 16, st->standard_info.out.nlink);
- SCVAL(trans->out.data.data, 20, st->standard_info.out.delete_pending);
- SCVAL(trans->out.data.data, 21, st->standard_info.out.directory);
- SSVAL(trans->out.data.data, 22, 0); /* padding */
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0, st->attribute_tag_information.out.attrib);
- SIVAL(trans->out.data.data, 4, st->attribute_tag_information.out.reparse_tag);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_EA_INFO:
- case RAW_FILEINFO_EA_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0, st->ea_info.out.ea_size);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_MODE_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0, st->mode_information.out.mode);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ALIGNMENT_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0,
- st->alignment_information.out.alignment_requirement);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ALL_EAS:
- if (st->all_eas.out.num_eas == 0) {
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0, 0);
- } else {
- uint32 list_size = ea_list_size(st->all_eas.out.num_eas,
- st->all_eas.out.eas);
- trans2_setup_reply(req, trans, 2, list_size, 0);
- SSVAL(trans->out.params.data, 0, 0);
- ea_put_list(trans->out.data.data,
- st->all_eas.out.num_eas, st->all_eas.out.eas);
- }
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ACCESS_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SIVAL(trans->out.data.data, 0, st->access_information.out.access_flags);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_POSITION_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SBVAL(trans->out.data.data, 0, st->position_information.out.position);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_COMPRESSION_INFO:
- case RAW_FILEINFO_COMPRESSION_INFORMATION:
- trans2_setup_reply(req, trans, 2, 16, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SBVAL(trans->out.data.data, 0, st->compression_info.out.compressed_size);
- SSVAL(trans->out.data.data, 8, st->compression_info.out.format);
- SCVAL(trans->out.data.data, 10, st->compression_info.out.unit_shift);
- SCVAL(trans->out.data.data, 11, st->compression_info.out.chunk_shift);
- SCVAL(trans->out.data.data, 12, st->compression_info.out.cluster_shift);
- SSVAL(trans->out.data.data, 13, 0); /* 3 bytes padding */
- SCVAL(trans->out.data.data, 15, 0);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_IS_NAME_VALID:
- trans2_setup_reply(req, trans, 2, 0, 0);
- SSVAL(trans->out.params.data, 0, 0);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_INTERNAL_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
- SSVAL(trans->out.params.data, 0, 0);
- SBVAL(trans->out.data.data, 0, st->internal_information.out.file_id);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ALL_INFO:
- case RAW_FILEINFO_ALL_INFORMATION:
- trans2_setup_reply(req, trans, 2, 72, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
- push_nttime(trans->out.data.data, 0, &st->all_info.out.create_time);
- push_nttime(trans->out.data.data, 8, &st->all_info.out.access_time);
- push_nttime(trans->out.data.data, 16, &st->all_info.out.write_time);
- push_nttime(trans->out.data.data, 24, &st->all_info.out.change_time);
- SIVAL(trans->out.data.data, 32, st->all_info.out.attrib);
- SBVAL(trans->out.data.data, 40, st->all_info.out.alloc_size);
- SBVAL(trans->out.data.data, 48, st->all_info.out.size);
- SIVAL(trans->out.data.data, 56, st->all_info.out.nlink);
- SCVAL(trans->out.data.data, 60, st->all_info.out.delete_pending);
- SCVAL(trans->out.data.data, 61, st->all_info.out.directory);
- SSVAL(trans->out.data.data, 62, 0); /* padding */
- SIVAL(trans->out.data.data, 64, st->all_info.out.ea_size);
- trans2_append_data_string(req, trans, &st->all_info.out.fname,
- 68, STR_UNICODE);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_NAME_INFO:
- case RAW_FILEINFO_NAME_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- trans2_append_data_string(req, trans, &st->name_info.out.fname, 0, STR_UNICODE);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_ALT_NAME_INFO:
- case RAW_FILEINFO_ALT_NAME_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
- SSVAL(trans->out.params.data, 0, 0);
- trans2_append_data_string(req, trans, &st->alt_name_info.out.fname, 0, STR_UNICODE);
- return NT_STATUS_OK;
-
- case RAW_FILEINFO_STREAM_INFO:
- case RAW_FILEINFO_STREAM_INFORMATION:
- trans2_setup_reply(req, trans, 2, 0, 0);
-
- SSVAL(trans->out.params.data, 0, 0);
-
- for (i=0;i<st->stream_info.out.num_streams;i++) {
- uint16 data_size = trans->out.data.length;
- char *data;
-
- trans2_grow_data(req, trans, data_size + 24);
- data = trans->out.data.data + data_size;
- SBVAL(data, 8, st->stream_info.out.streams[i].size);
- SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
- trans2_append_data_string(req, trans,
- &st->stream_info.out.streams[i].stream_name,
- data_size + 4, STR_UNICODE);
- if (i == st->stream_info.out.num_streams - 1) {
- SIVAL(trans->out.data.data, data_size, 0);
- } else {
- trans2_grow_data_fill(req, trans, (trans->out.data.length+7)&~7);
- SIVAL(trans->out.data.data, data_size,
- trans->out.data.length - data_size);
- }
- }
- return NT_STATUS_OK;
- }
-
- return NT_STATUS_INVALID_LEVEL;
-}
-
-/*
- trans2 qpathinfo implementation
-*/
-static NTSTATUS trans2_qpathinfo(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_fileinfo st;
- NTSTATUS status;
- uint16 level;
-
- /* make sure we got enough parameters */
- if (trans->in.params.length < 8) {
- return NT_STATUS_FOOBAR;
- }
-
- level = SVAL(trans->in.params.data, 0);
-
- trans2_pull_blob_string(req, &trans->in.params, 6, &st.generic.in.fname, 0);
- if (st.generic.in.fname == NULL) {
- return NT_STATUS_FOOBAR;
- }
-
- /* work out the backend level - we make it 1-1 in the header */
- st.generic.level = (enum fileinfo_level)level;
- if (st.generic.level >= RAW_FILEINFO_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- /* call the backend */
- status = req->conn->ntvfs_ops->qpathinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* fill in the reply parameters */
- status = trans2_fileinfo_fill(req, trans, &st);
-
- return status;
-}
-
-
-/*
- trans2 qpathinfo implementation
-*/
-static NTSTATUS trans2_qfileinfo(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_fileinfo st;
- NTSTATUS status;
- uint16 level;
-
- /* make sure we got enough parameters */
- if (trans->in.params.length < 4) {
- return NT_STATUS_FOOBAR;
- }
-
- st.generic.in.fnum = SVAL(trans->in.params.data, 0);
- level = SVAL(trans->in.params.data, 2);
-
- /* work out the backend level - we make it 1-1 in the header */
- st.generic.level = (enum fileinfo_level)level;
- if (st.generic.level >= RAW_FILEINFO_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- /* call the backend */
- status = req->conn->ntvfs_ops->qfileinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* fill in the reply parameters */
- status = trans2_fileinfo_fill(req, trans, &st);
-
- return status;
-}
-
-
-/*
- parse a trans2 setfileinfo/setpathinfo data blob
-*/
-static NTSTATUS trans2_parse_sfileinfo(struct request_context *req,
- union smb_setfileinfo *st,
- const DATA_BLOB *blob)
-{
- uint32 len;
-
- switch (st->generic.level) {
- case RAW_SFILEINFO_GENERIC:
- case RAW_SFILEINFO_SETATTR:
- case RAW_SFILEINFO_SETATTRE:
- /* handled elsewhere */
- return NT_STATUS_INVALID_LEVEL;
-
- case RAW_SFILEINFO_STANDARD:
- CHECK_MIN_BLOB_SIZE(blob, 12);
- st->standard.in.create_time = make_unix_date2(blob->data + 0);
- st->standard.in.access_time = make_unix_date2(blob->data + 4);
- st->standard.in.write_time = make_unix_date2(blob->data + 8);
- return NT_STATUS_OK;
-
- case RAW_SFILEINFO_EA_SET:
- CHECK_MIN_BLOB_SIZE(blob, 4);
- len = IVAL(blob->data, 0);
- if (len > blob->length || len < 4) {
- return NT_STATUS_INFO_LENGTH_MISMATCH;
- }
- {
- DATA_BLOB blob2;
- blob2.data = blob->data+4;
- blob2.length = len-4;
- len = ea_pull_struct(&blob2, req->mem_ctx, &st->ea_set.in.ea);
- }
- if (len == 0) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- return NT_STATUS_OK;
-
- case SMB_SFILEINFO_BASIC_INFO:
- case SMB_SFILEINFO_BASIC_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 36);
- st->basic_info.in.create_time = pull_nttime(blob->data, 0);
- st->basic_info.in.access_time = pull_nttime(blob->data, 8);
- st->basic_info.in.write_time = pull_nttime(blob->data, 16);
- st->basic_info.in.change_time = pull_nttime(blob->data, 24);
- st->basic_info.in.attrib = IVAL(blob->data, 32);
- return NT_STATUS_OK;
-
- case SMB_SFILEINFO_DISPOSITION_INFO:
- case SMB_SFILEINFO_DISPOSITION_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 1);
- st->disposition_info.in.delete_on_close = CVAL(blob->data, 0);
- return NT_STATUS_OK;
-
- case SMB_SFILEINFO_ALLOCATION_INFO:
- case SMB_SFILEINFO_ALLOCATION_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 8);
- st->allocation_info.in.alloc_size = BVAL(blob->data, 0);
- return NT_STATUS_OK;
-
- case RAW_SFILEINFO_END_OF_FILE_INFO:
- case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 8);
- st->end_of_file_info.in.size = BVAL(blob->data, 0);
- return NT_STATUS_OK;
-
- case RAW_SFILEINFO_RENAME_INFORMATION: {
- DATA_BLOB blob2;
-
- CHECK_MIN_BLOB_SIZE(blob, 12);
- st->rename_information.in.overwrite = CVAL(blob->data, 0);
- st->rename_information.in.root_fid = IVAL(blob->data, 4);
- len = IVAL(blob->data, 8);
- blob2.data = blob->data+12;
- blob2.length = MIN(blob->length, len);
- trans2_pull_blob_string(req, &blob2, 0,
- &st->rename_information.in.new_name, STR_UNICODE);
- return NT_STATUS_OK;
- }
-
- case RAW_SFILEINFO_POSITION_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 8);
- st->position_information.in.position = BVAL(blob->data, 0);
- return NT_STATUS_OK;
-
- case RAW_SFILEINFO_MODE_INFORMATION:
- CHECK_MIN_BLOB_SIZE(blob, 4);
- st->mode_information.in.mode = IVAL(blob->data, 0);
- return NT_STATUS_OK;
- }
-
- return NT_STATUS_INVALID_LEVEL;
-}
-
-/*
- trans2 setfileinfo implementation
-*/
-static NTSTATUS trans2_setfileinfo(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_setfileinfo st;
- NTSTATUS status;
- uint16 level, fnum;
- DATA_BLOB *blob;
-
- /* make sure we got enough parameters */
- if (trans->in.params.length < 4) {
- return NT_STATUS_FOOBAR;
- }
-
- fnum = SVAL(trans->in.params.data, 0);
- level = SVAL(trans->in.params.data, 2);
-
- blob = &trans->in.data;
-
- st.generic.file.fnum = fnum;
- st.generic.level = (enum setfileinfo_level)level;
-
- status = trans2_parse_sfileinfo(req, &st, blob);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = req->conn->ntvfs_ops->setfileinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 2, 0, 0);
- SSVAL(trans->out.params.data, 0, 0);
- return NT_STATUS_OK;
-}
-
-/*
- trans2 setpathinfo implementation
-*/
-static NTSTATUS trans2_setpathinfo(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_setfileinfo st;
- NTSTATUS status;
- uint16 level;
- DATA_BLOB *blob;
-
- /* make sure we got enough parameters */
- if (trans->in.params.length < 4) {
- return NT_STATUS_FOOBAR;
- }
-
- level = SVAL(trans->in.params.data, 0);
- blob = &trans->in.data;
- st.generic.level = (enum setfileinfo_level)level;
-
- trans2_pull_blob_string(req, &trans->in.params, 4, &st.generic.file.fname, 0);
- if (st.generic.file.fname == NULL) {
- return NT_STATUS_FOOBAR;
- }
-
- status = trans2_parse_sfileinfo(req, &st, blob);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = req->conn->ntvfs_ops->setpathinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 2, 0, 0);
- SSVAL(trans->out.params.data, 0, 0);
- return NT_STATUS_OK;
-}
-
-
-/* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
-struct find_state {
- struct request_context *req;
- struct smb_trans2 *trans;
- enum search_level level;
- uint16 last_entry_offset;
- uint16 flags;
-};
-
-/*
- fill a single entry in a trans2 find reply
-*/
-static void find_fill_info(struct request_context *req,
- struct smb_trans2 *trans,
- struct find_state *state,
- union smb_search_data *file)
-{
- char *data;
- uint_t ofs = trans->out.data.length;
-
- switch (state->level) {
- case RAW_SEARCH_SEARCH:
- case RAW_SEARCH_GENERIC:
- /* handled elsewhere */
- break;
-
- case RAW_SEARCH_STANDARD:
- if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- trans2_grow_data(req, trans, ofs + 27);
- SIVAL(trans->out.data.data, ofs, file->standard.resume_key);
- ofs += 4;
- } else {
- trans2_grow_data(req, trans, ofs + 23);
- }
- data = trans->out.data.data + ofs;
- put_dos_date2(data, 0, file->standard.create_time);
- put_dos_date2(data, 4, file->standard.access_time);
- put_dos_date2(data, 8, file->standard.write_time);
- SIVAL(data, 12, file->standard.size);
- SIVAL(data, 16, file->standard.alloc_size);
- SSVAL(data, 20, file->standard.attrib);
- trans2_append_data_string(req, trans, &file->standard.name,
- ofs + 22, STR_LEN8BIT | STR_TERMINATE | STR_LEN_NOTERM);
- break;
-
- case RAW_SEARCH_EA_SIZE:
- if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- trans2_grow_data(req, trans, ofs + 31);
- SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key);
- ofs += 4;
- } else {
- trans2_grow_data(req, trans, ofs + 27);
- }
- data = trans->out.data.data + ofs;
- put_dos_date2(data, 0, file->ea_size.create_time);
- put_dos_date2(data, 4, file->ea_size.access_time);
- put_dos_date2(data, 8, file->ea_size.write_time);
- SIVAL(data, 12, file->ea_size.size);
- SIVAL(data, 16, file->ea_size.alloc_size);
- SSVAL(data, 20, file->ea_size.attrib);
- SIVAL(data, 22, file->ea_size.ea_size);
- trans2_append_data_string(req, trans, &file->ea_size.name,
- ofs + 26, STR_LEN8BIT | STR_TERMINATE | STR_NOALIGN);
- break;
-
- case RAW_SEARCH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 64);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->directory_info.file_index);
- push_nttime(data, 8, &file->directory_info.create_time);
- push_nttime(data, 16, &file->directory_info.access_time);
- push_nttime(data, 24, &file->directory_info.write_time);
- push_nttime(data, 32, &file->directory_info.change_time);
- SBVAL(data, 40, file->directory_info.size);
- SBVAL(data, 48, file->directory_info.alloc_size);
- SIVAL(data, 56, file->directory_info.attrib);
- trans2_append_data_string(req, trans, &file->directory_info.name,
- ofs + 60, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
-
- case RAW_SEARCH_FULL_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 68);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->full_directory_info.file_index);
- push_nttime(data, 8, &file->full_directory_info.create_time);
- push_nttime(data, 16, &file->full_directory_info.access_time);
- push_nttime(data, 24, &file->full_directory_info.write_time);
- push_nttime(data, 32, &file->full_directory_info.change_time);
- SBVAL(data, 40, file->full_directory_info.size);
- SBVAL(data, 48, file->full_directory_info.alloc_size);
- SIVAL(data, 56, file->full_directory_info.attrib);
- SIVAL(data, 64, file->full_directory_info.ea_size);
- trans2_append_data_string(req, trans, &file->full_directory_info.name,
- ofs + 60, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
-
- case RAW_SEARCH_NAME_INFO:
- trans2_grow_data(req, trans, ofs + 12);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->name_info.file_index);
- trans2_append_data_string(req, trans, &file->name_info.name,
- ofs + 8, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
-
- case RAW_SEARCH_BOTH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 94);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->both_directory_info.file_index);
- push_nttime(data, 8, &file->both_directory_info.create_time);
- push_nttime(data, 16, &file->both_directory_info.access_time);
- push_nttime(data, 24, &file->both_directory_info.write_time);
- push_nttime(data, 32, &file->both_directory_info.change_time);
- SBVAL(data, 40, file->both_directory_info.size);
- SBVAL(data, 48, file->both_directory_info.alloc_size);
- SIVAL(data, 56, file->both_directory_info.attrib);
- SIVAL(data, 64, file->both_directory_info.ea_size);
- SCVAL(data, 69, 0); /* reserved */
- memset(data+70,0,24);
- trans2_push_data_string(req, trans,
- 68 + ofs, 70 + ofs,
- &file->both_directory_info.short_name,
- 24, STR_UNICODE | STR_LEN8BIT);
- trans2_append_data_string(req, trans, &file->both_directory_info.name,
- ofs + 60, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
-
- case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 80);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->id_full_directory_info.file_index);
- push_nttime(data, 8, &file->id_full_directory_info.create_time);
- push_nttime(data, 16, &file->id_full_directory_info.access_time);
- push_nttime(data, 24, &file->id_full_directory_info.write_time);
- push_nttime(data, 32, &file->id_full_directory_info.change_time);
- SBVAL(data, 40, file->id_full_directory_info.size);
- SBVAL(data, 48, file->id_full_directory_info.alloc_size);
- SIVAL(data, 56, file->id_full_directory_info.attrib);
- SIVAL(data, 64, file->id_full_directory_info.ea_size);
- SIVAL(data, 68, 0); /* padding */
- SBVAL(data, 72, file->id_full_directory_info.file_id);
- trans2_append_data_string(req, trans, &file->id_full_directory_info.name,
- ofs + 60, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
-
- case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 104);
- data = trans->out.data.data + ofs;
- SIVAL(data, 4, file->id_both_directory_info.file_index);
- push_nttime(data, 8, &file->id_both_directory_info.create_time);
- push_nttime(data, 16, &file->id_both_directory_info.access_time);
- push_nttime(data, 24, &file->id_both_directory_info.write_time);
- push_nttime(data, 32, &file->id_both_directory_info.change_time);
- SBVAL(data, 40, file->id_both_directory_info.size);
- SBVAL(data, 48, file->id_both_directory_info.alloc_size);
- SIVAL(data, 56, file->id_both_directory_info.attrib);
- SIVAL(data, 64, file->id_both_directory_info.ea_size);
- SCVAL(data, 69, 0); /* reserved */
- memset(data+70,0,24);
- trans2_push_data_string(req, trans,
- 68 + ofs, 70 + ofs,
- &file->id_both_directory_info.short_name,
- 24, STR_UNICODE | STR_LEN8BIT);
- SBVAL(data, 94, file->id_both_directory_info.file_id);
- SSVAL(data, 102, 0); /* reserved? */
- trans2_append_data_string(req, trans, &file->id_both_directory_info.name,
- ofs + 60, STR_TERMINATE_ASCII);
- data = trans->out.data.data + ofs;
- SIVAL(data, 0, trans->out.data.length - ofs);
- break;
- }
-}
-
-/* callback function for trans2 findfirst/findnext */
-static BOOL find_callback(void *private, union smb_search_data *file)
-{
- struct find_state *state = (struct find_state *)private;
- struct smb_trans2 *trans = state->trans;
- uint_t old_length;
-
- old_length = trans->out.data.length;
-
- find_fill_info(state->req, trans, state, file);
-
- /* see if we have gone beyond the user specified maximum */
- if (trans->out.data.length > trans->in.max_data) {
- /* restore the old length and tell the backend to stop */
- trans2_grow_data(state->req, trans, old_length);
- return False;
- }
-
- state->last_entry_offset = old_length;
- return True;
-}
-
-
-/*
- trans2 findfirst implementation
-*/
-static NTSTATUS trans2_findfirst(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_search_first search;
- NTSTATUS status;
- uint16 level;
- char *param;
- struct find_state state;
-
- /* make sure we got all the parameters */
- if (trans->in.params.length < 14) {
- return NT_STATUS_FOOBAR;
- }
-
- search.t2ffirst.in.search_attrib = SVAL(trans->in.params.data, 0);
- search.t2ffirst.in.max_count = SVAL(trans->in.params.data, 2);
- search.t2ffirst.in.flags = SVAL(trans->in.params.data, 4);
- level = SVAL(trans->in.params.data, 6);
- search.t2ffirst.in.storage_type = IVAL(trans->in.params.data, 8);
-
- trans2_pull_blob_string(req, &trans->in.params, 12, &search.t2ffirst.in.pattern, 0);
- if (search.t2ffirst.in.pattern == NULL) {
- return NT_STATUS_FOOBAR;
- }
-
- search.t2ffirst.level = (enum search_level)level;
- if (search.t2ffirst.level >= RAW_SEARCH_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- /* setup the private state structure that the backend will give us in the callback */
- state.req = req;
- state.trans = trans;
- state.level = search.t2ffirst.level;
- state.last_entry_offset = 0;
- state.flags = search.t2ffirst.in.flags;
-
- /* setup for just a header in the reply */
- trans2_setup_reply(req, trans, 10, 0, 0);
-
- /* call the backend */
- status = req->conn->ntvfs_ops->search_first(req, &search, &state, find_callback);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* fill in the findfirst reply header */
- param = trans->out.params.data;
- SSVAL(param, VWV(0), search.t2ffirst.out.handle);
- SSVAL(param, VWV(1), search.t2ffirst.out.count);
- SSVAL(param, VWV(2), search.t2ffirst.out.end_of_search);
- SSVAL(param, VWV(3), 0);
- SSVAL(param, VWV(4), state.last_entry_offset);
-
- return NT_STATUS_OK;
-}
-
-
-/*
- trans2 findnext implementation
-*/
-static NTSTATUS trans2_findnext(struct request_context *req, struct smb_trans2 *trans)
-{
- union smb_search_next search;
- NTSTATUS status;
- uint16 level;
- char *param;
- struct find_state state;
-
- /* make sure we got all the parameters */
- if (trans->in.params.length < 12) {
- return NT_STATUS_FOOBAR;
- }
-
- search.t2fnext.in.handle = SVAL(trans->in.params.data, 0);
- search.t2fnext.in.max_count = SVAL(trans->in.params.data, 2);
- level = SVAL(trans->in.params.data, 4);
- search.t2fnext.in.resume_key = IVAL(trans->in.params.data, 6);
- search.t2fnext.in.flags = SVAL(trans->in.params.data, 10);
-
- trans2_pull_blob_string(req, &trans->in.params, 12, &search.t2fnext.in.last_name, 0);
- if (search.t2fnext.in.last_name == NULL) {
- return NT_STATUS_FOOBAR;
- }
-
- search.t2fnext.level = (enum search_level)level;
- if (search.t2fnext.level >= RAW_SEARCH_GENERIC) {
- return NT_STATUS_INVALID_LEVEL;
- }
-
- /* setup the private state structure that the backend will give us in the callback */
- state.req = req;
- state.trans = trans;
- state.level = search.t2fnext.level;
- state.last_entry_offset = 0;
- state.flags = search.t2fnext.in.flags;
-
- /* setup for just a header in the reply */
- trans2_setup_reply(req, trans, 8, 0, 0);
-
- /* call the backend */
- status = req->conn->ntvfs_ops->search_next(req, &search, &state, find_callback);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* fill in the findfirst reply header */
- param = trans->out.params.data;
- SSVAL(param, VWV(0), search.t2fnext.out.count);
- SSVAL(param, VWV(1), search.t2fnext.out.end_of_search);
- SSVAL(param, VWV(2), 0);
- SSVAL(param, VWV(3), state.last_entry_offset);
-
- return NT_STATUS_OK;
-}
-
-
-/*
- backend for trans2 requests
-*/
-static NTSTATUS trans2_backend(struct request_context *req, struct smb_trans2 *trans)
-{
- if (req->conn->ntvfs_ops->trans2 != NULL) {
- /* direct trans2 pass thru */
- return req->conn->ntvfs_ops->trans2(req, trans);
- }
-
- /* must have at least one setup word */
- if (trans->in.setup_count < 1) {
- return NT_STATUS_FOOBAR;
- }
-
- /* the trans2 command is in setup[0] */
- switch (trans->in.setup[0]) {
- case TRANSACT2_FINDFIRST:
- return trans2_findfirst(req, trans);
- case TRANSACT2_FINDNEXT:
- return trans2_findnext(req, trans);
- case TRANSACT2_QPATHINFO:
- return trans2_qpathinfo(req, trans);
- case TRANSACT2_QFILEINFO:
- return trans2_qfileinfo(req, trans);
- case TRANSACT2_SETFILEINFO:
- return trans2_setfileinfo(req, trans);
- case TRANSACT2_SETPATHINFO:
- return trans2_setpathinfo(req, trans);
- case TRANSACT2_QFSINFO:
- return trans2_qfsinfo(req, trans);
- }
-
- /* an unknown trans2 command */
- return NT_STATUS_FOOBAR;
-}
-
-
-/*
- backend for trans requests
-*/
-static NTSTATUS trans_backend(struct request_context *req, struct smb_trans2 *trans)
-{
- if (!req->conn->ntvfs_ops->trans) {
- return NT_STATUS_NOT_IMPLEMENTED;
- }
- return req->conn->ntvfs_ops->trans(req, trans);
-}
-
-
-/****************************************************************************
- Reply to an SMBtrans or SMBtrans2 request
-****************************************************************************/
-void reply_trans_generic(struct request_context *req, uint8 command)
-{
- struct smb_trans2 trans;
- int i;
- uint16 param_ofs, data_ofs;
- uint16 param_count, data_count;
- uint16 params_left, data_left;
- uint16 param_total, data_total;
- char *params, *data;
- NTSTATUS status;
-
- /* parse request */
- if (req->in.wct < 14) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- param_total = SVAL(req->in.vwv, VWV(0));
- data_total = SVAL(req->in.vwv, VWV(1));
- trans.in.max_param = SVAL(req->in.vwv, VWV(2));
- trans.in.max_data = SVAL(req->in.vwv, VWV(3));
- trans.in.max_setup = CVAL(req->in.vwv, VWV(4));
- trans.in.flags = SVAL(req->in.vwv, VWV(5));
- trans.in.timeout = IVAL(req->in.vwv, VWV(6));
- param_count = SVAL(req->in.vwv, VWV(9));
- param_ofs = SVAL(req->in.vwv, VWV(10));
- data_count = SVAL(req->in.vwv, VWV(11));
- data_ofs = SVAL(req->in.vwv, VWV(12));
- trans.in.setup_count = CVAL(req->in.vwv, VWV(13));
-
- if (req->in.wct != 14 + trans.in.setup_count) {
- req_reply_dos_error(req, ERRSRV, ERRerror);
- return;
- }
-
- /* parse out the setup words */
- trans.in.setup = talloc(req->mem_ctx, trans.in.setup_count * sizeof(uint16));
- if (!trans.in.setup) {
- req_reply_error(req, NT_STATUS_NO_MEMORY);
- return;
- }
- for (i=0;i<trans.in.setup_count;i++) {
- trans.in.setup[i] = SVAL(req->in.vwv, VWV(14+i));
- }
-
- if (command == SMBtrans) {
- req_pull_string(req, &trans.in.trans_name, req->in.data, -1, STR_TERMINATE);
- }
-
- if (!req_pull_blob(req, req->in.hdr + param_ofs, param_count, &trans.in.params) ||
- !req_pull_blob(req, req->in.hdr + data_ofs, data_count, &trans.in.data)) {
- req_reply_error(req, NT_STATUS_FOOBAR);
- return;
- }
-
- /* is it a partial request? if so, then send a 'send more' message */
- if (param_total > param_count ||
- data_total > data_count) {
- DEBUG(0,("REWRITE: not handling partial trans requests!\n"));
- return;
- }
-
- /* its a full request, give it to the backend */
- if (command == SMBtrans) {
- status = trans_backend(req, &trans);
- } else {
- status = trans2_backend(req, &trans);
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- req_reply_error(req, status);
- return;
- }
-
- params_left = trans.out.params.length;
- data_left = trans.out.data.length;
- params = trans.out.params.data;
- data = trans.out.data.data;
-
- req->control_flags |= REQ_CONTROL_PROTECTED;
-
- /* we need to divide up the reply into chunks that fit into
- the negotiated buffer size */
- do {
- uint16 this_data, this_param, max_bytes;
- uint_t align1 = 1, align2 = (params_left ? 2 : 0);
-
- req_setup_reply(req, 10 + trans.out.setup_count, 0);
-
- max_bytes = req_max_data(req) - (align1 + align2);
-
- this_param = params_left;
- if (this_param > max_bytes) {
- this_param = max_bytes;
- }
- max_bytes -= this_param;
-
- this_data = data_left;
- if (this_data > max_bytes) {
- this_data = max_bytes;
- }
-
- req_grow_data(req, this_param + this_data + (align1 + align2));
-
- SSVAL(req->out.vwv, VWV(0), trans.out.params.length);
- SSVAL(req->out.vwv, VWV(1), trans.out.data.length);
- SSVAL(req->out.vwv, VWV(2), 0);
-
- SSVAL(req->out.vwv, VWV(3), this_param);
- SSVAL(req->out.vwv, VWV(4), align1 + PTR_DIFF(req->out.data, req->out.hdr));
- SSVAL(req->out.vwv, VWV(5), PTR_DIFF(params, trans.out.params.data));
-
- SSVAL(req->out.vwv, VWV(6), this_data);
- SSVAL(req->out.vwv, VWV(7), align1 + align2 +
- PTR_DIFF(req->out.data + this_param, req->out.hdr));
- SSVAL(req->out.vwv, VWV(8), PTR_DIFF(data, trans.out.data.data));
-
- SSVAL(req->out.vwv, VWV(9), trans.out.setup_count);
- for (i=0;i<trans.out.setup_count;i++) {
- SSVAL(req->out.vwv, VWV(10+i), trans.out.setup[i]);
- }
-
- memset(req->out.data, 0, align1);
- if (this_param != 0) {
- memcpy(req->out.data + align1, params, this_param);
- }
- memset(req->out.data+this_param+align1, 0, align2);
- if (this_data != 0) {
- memcpy(req->out.data+this_param+align1+align2, data, this_data);
- }
-
- params_left -= this_param;
- data_left -= this_data;
- params += this_param;
- data += this_data;
-
- /* if this is the last chunk then the request can be destroyed */
- if (params_left == 0 && data_left == 0) {
- req->control_flags &= ~REQ_CONTROL_PROTECTED;
- }
-
- req_send_reply(req);
- } while (params_left != 0 || data_left != 0);
-}
-
-
-/****************************************************************************
- Reply to an SMBtrans2
-****************************************************************************/
-void reply_trans2(struct request_context *req)
-{
- reply_trans_generic(req, SMBtrans2);
-}
-
-/****************************************************************************
- Reply to an SMBtrans
-****************************************************************************/
-void reply_trans(struct request_context *req)
-{
- reply_trans_generic(req, SMBtrans);
-}
-
-/****************************************************************************
- Reply to an SMBtranss2 request
-****************************************************************************/
-void reply_transs2(struct request_context *req)
-{
- req_reply_error(req, NT_STATUS_FOOBAR);
-}
-
-