258 lines
6.3 KiB
C
258 lines
6.3 KiB
C
|
|
/*
|
||
|
|
Copyright (C) Andrzej Hajda 2006
|
||
|
|
Contact: andrzej.hajda@wp.pl
|
||
|
|
License: GNU General Public License version 2
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "includes.h"
|
||
|
|
#include "libcli/libcli.h"
|
||
|
|
#include "winexe.h"
|
||
|
|
|
||
|
|
void list_enqueue(struct list *l, const void *data, int size)
|
||
|
|
{
|
||
|
|
struct list_item *li =
|
||
|
|
talloc_size(0, sizeof(struct list_item) + size);
|
||
|
|
memcpy(li->data, data, size);
|
||
|
|
li->size = size;
|
||
|
|
li->next = 0;
|
||
|
|
if (l->end)
|
||
|
|
l->end->next = li;
|
||
|
|
else
|
||
|
|
l->begin = li;
|
||
|
|
l->end = li;
|
||
|
|
}
|
||
|
|
|
||
|
|
void list_dequeue(struct list *l)
|
||
|
|
{
|
||
|
|
struct list_item *li = l->begin;
|
||
|
|
if (!li)
|
||
|
|
return;
|
||
|
|
l->begin = li->next;
|
||
|
|
if (!l->begin)
|
||
|
|
l->end = 0;
|
||
|
|
talloc_free(li);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void async_read_recv(struct smbcli_request *req)
|
||
|
|
{
|
||
|
|
struct async_context *c = req->async.private;
|
||
|
|
NTSTATUS status;
|
||
|
|
|
||
|
|
status = smb_raw_read_recv(req, c->io_read);
|
||
|
|
c->rreq = NULL;
|
||
|
|
if (!NT_STATUS_IS_OK(status)) {
|
||
|
|
DEBUG(1,
|
||
|
|
("ERROR: smb_raw_read_recv - %s\n",
|
||
|
|
nt_errstr(status)));
|
||
|
|
if (c->cb_error)
|
||
|
|
c->cb_error(c->cb_ctx, ASYNC_READ_RECV, status);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (c->cb_read)
|
||
|
|
c->cb_read(c->cb_ctx, c->buffer,
|
||
|
|
c->io_read->readx.out.nread);
|
||
|
|
|
||
|
|
async_read(c);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void async_write_recv(struct smbcli_request *req)
|
||
|
|
{
|
||
|
|
struct async_context *c = req->async.private;
|
||
|
|
NTSTATUS status;
|
||
|
|
|
||
|
|
status = smb_raw_write_recv(req, c->io_write);
|
||
|
|
c->wreq = NULL;
|
||
|
|
if (!NT_STATUS_IS_OK(status)) {
|
||
|
|
DEBUG(1,
|
||
|
|
("ERROR: smb_raw_write_recv - %s\n",
|
||
|
|
nt_errstr(status)));
|
||
|
|
talloc_free(c->io_write);
|
||
|
|
c->io_write = 0;
|
||
|
|
if (c->cb_error)
|
||
|
|
c->cb_error(c->cb_ctx, ASYNC_WRITE_RECV, status);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (c->wq.begin) {
|
||
|
|
async_write(c, c->wq.begin->data, c->wq.begin->size);
|
||
|
|
list_dequeue(&c->wq);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void async_open_recv(struct smbcli_request *req)
|
||
|
|
{
|
||
|
|
struct async_context *c = req->async.private;
|
||
|
|
NTSTATUS status;
|
||
|
|
|
||
|
|
DEBUG(1, ("IN: async_open_recv\n"));
|
||
|
|
status = smb_raw_open_recv(req, c, c->io_open);
|
||
|
|
c->rreq = NULL;
|
||
|
|
if (NT_STATUS_IS_OK(status))
|
||
|
|
#if 1
|
||
|
|
c->fd = c->io_open->openx.out.file.fnum;
|
||
|
|
#else
|
||
|
|
c->fd = c->io_open->ntcreatex.out.file.fnum;
|
||
|
|
#endif
|
||
|
|
talloc_free(c->io_open);
|
||
|
|
c->io_open = 0;
|
||
|
|
if (!NT_STATUS_IS_OK(status)) {
|
||
|
|
DEBUG(1,
|
||
|
|
("ERROR: smb_raw_open_recv - %s\n",
|
||
|
|
nt_errstr(status)));
|
||
|
|
if (c->cb_error)
|
||
|
|
c->cb_error(c->cb_ctx, ASYNC_OPEN_RECV, status);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (c->cb_open)
|
||
|
|
c->cb_open(c->cb_ctx);
|
||
|
|
async_read(c);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void async_close_recv(struct smbcli_request *req)
|
||
|
|
{
|
||
|
|
struct async_context *c = req->async.private;
|
||
|
|
NTSTATUS status;
|
||
|
|
|
||
|
|
status = smbcli_request_simple_recv(req);
|
||
|
|
talloc_free(c->io_close);
|
||
|
|
c->io_close = 0;
|
||
|
|
if (c->io_open) {
|
||
|
|
talloc_free(c->io_open);
|
||
|
|
c->io_open = 0;
|
||
|
|
}
|
||
|
|
if (c->io_read) {
|
||
|
|
talloc_free(c->io_read);
|
||
|
|
c->io_read = 0;
|
||
|
|
}
|
||
|
|
if (c->io_write) {
|
||
|
|
talloc_free(c->io_write);
|
||
|
|
c->io_write = 0;
|
||
|
|
}
|
||
|
|
if (c->cb_close)
|
||
|
|
c->cb_close(c->cb_ctx);
|
||
|
|
}
|
||
|
|
|
||
|
|
int async_read(struct async_context *c)
|
||
|
|
{
|
||
|
|
if (!c->io_read) {
|
||
|
|
c->io_read = talloc(c->tree, union smb_read);
|
||
|
|
c->io_read->readx.level = RAW_READ_READX;
|
||
|
|
c->io_read->readx.in.file.fnum = c->fd;
|
||
|
|
c->io_read->readx.in.offset = 0;
|
||
|
|
c->io_read->readx.in.mincnt = sizeof(c->buffer);
|
||
|
|
c->io_read->readx.in.maxcnt = sizeof(c->buffer);
|
||
|
|
c->io_read->readx.in.remaining = 0;
|
||
|
|
c->io_read->readx.in.read_for_execute = False;
|
||
|
|
c->io_read->readx.out.data = (uint8_t *)c->buffer;
|
||
|
|
}
|
||
|
|
c->rreq = smb_raw_read_send(c->tree, c->io_read);
|
||
|
|
if (!c->rreq) {
|
||
|
|
if (c->cb_error)
|
||
|
|
c->cb_error(c->cb_ctx, ASYNC_READ,
|
||
|
|
NT_STATUS_NO_MEMORY);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
c->rreq->transport->options.request_timeout = 0;
|
||
|
|
c->rreq->async.fn = async_read_recv;
|
||
|
|
c->rreq->async.private = c;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int async_open(struct async_context *c, const char *fn, int open_mode)
|
||
|
|
{
|
||
|
|
DEBUG(1, ("IN: async_open(%s, %d)\n", fn, open_mode));
|
||
|
|
c->io_open = talloc_zero(c, union smb_open);
|
||
|
|
if (!c->io_open)
|
||
|
|
goto failed;
|
||
|
|
#if 1
|
||
|
|
c->io_open->openx.level = RAW_OPEN_OPENX;
|
||
|
|
c->io_open->openx.in.flags = 0;
|
||
|
|
c->io_open->openx.in.open_mode = open_mode;
|
||
|
|
c->io_open->openx.in.search_attrs =
|
||
|
|
FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
|
||
|
|
c->io_open->openx.in.file_attrs = 0;
|
||
|
|
c->io_open->openx.in.write_time = 0;
|
||
|
|
c->io_open->openx.in.open_func = 0;
|
||
|
|
c->io_open->openx.in.size = 0;
|
||
|
|
c->io_open->openx.in.timeout = 0;
|
||
|
|
c->io_open->openx.in.fname = fn;
|
||
|
|
#else
|
||
|
|
c->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
|
||
|
|
c->io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
|
||
|
|
c->io_open->ntcreatex.in.access_mask = open_mode;
|
||
|
|
c->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
|
||
|
|
c->io_open->ntcreatex.in.impersonation = impersonation;
|
||
|
|
c->io_open->ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | NTCREATEX_OPTIONS_WRITE_THROUGH;
|
||
|
|
c->io_open->ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC | NTCREATEX_SECURITY_ALL;
|
||
|
|
c->io_open->ntcreatex.in.fname = fn;
|
||
|
|
#endif
|
||
|
|
c->rreq = smb_raw_open_send(c->tree, c->io_open);
|
||
|
|
if (!c->rreq)
|
||
|
|
goto failed;
|
||
|
|
c->rreq->async.fn = async_open_recv;
|
||
|
|
c->rreq->async.private = c;
|
||
|
|
return 1;
|
||
|
|
failed:
|
||
|
|
DEBUG(1, ("ERROR: async_open\n"));
|
||
|
|
talloc_free(c);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int async_write(struct async_context *c, const void *buf, int len)
|
||
|
|
{
|
||
|
|
if (c->wreq) {
|
||
|
|
list_enqueue(&c->wq, buf, len);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
if (!c->io_write) {
|
||
|
|
c->io_write = talloc_zero(c, union smb_write);
|
||
|
|
if (!c->io_write)
|
||
|
|
goto failed;
|
||
|
|
c->io_write->write.level = RAW_WRITE_WRITE;
|
||
|
|
c->io_write->write.in.remaining = 0;
|
||
|
|
c->io_write->write.in.file.fnum = c->fd;
|
||
|
|
c->io_write->write.in.offset = 0;
|
||
|
|
}
|
||
|
|
c->io_write->write.in.count = len;
|
||
|
|
c->io_write->write.in.data = buf;
|
||
|
|
struct smbcli_request *req =
|
||
|
|
smb_raw_write_send(c->tree, c->io_write);
|
||
|
|
if (!req)
|
||
|
|
goto failed;
|
||
|
|
req->async.fn = async_write_recv;
|
||
|
|
req->async.private = c;
|
||
|
|
return 1;
|
||
|
|
failed:
|
||
|
|
DEBUG(1, ("ERROR: async_write\n"));
|
||
|
|
talloc_free(c->io_write);
|
||
|
|
c->io_write = 0;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int async_close(struct async_context *c)
|
||
|
|
{
|
||
|
|
if (c->rreq)
|
||
|
|
smbcli_request_destroy(c->rreq);
|
||
|
|
if (c->wreq)
|
||
|
|
smbcli_request_destroy(c->wreq);
|
||
|
|
c->rreq = c->wreq = NULL;
|
||
|
|
c->io_close = talloc_zero(c, union smb_close);
|
||
|
|
if (!c->io_close)
|
||
|
|
goto failed;
|
||
|
|
c->io_close->close.level = RAW_CLOSE_CLOSE;
|
||
|
|
c->io_close->close.in.file.fnum = c->fd;
|
||
|
|
c->io_close->close.in.write_time = 0;
|
||
|
|
struct smbcli_request *req =
|
||
|
|
smb_raw_close_send(c->tree, c->io_close);
|
||
|
|
if (!req)
|
||
|
|
goto failed;
|
||
|
|
req->async.fn = async_close_recv;
|
||
|
|
req->async.private = c;
|
||
|
|
return 1;
|
||
|
|
failed:
|
||
|
|
DEBUG(1, ("ERROR: async_close\n"));
|
||
|
|
talloc_free(c->io_close);
|
||
|
|
c->io_close = 0;
|
||
|
|
return 0;
|
||
|
|
}
|