Files
wmic/Samba/source/winexe/async.c
T

258 lines
6.3 KiB
C
Raw Normal View History

2019-02-16 00:16:52 +01:00
/*
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;
}