1 /*
2    Copyright (C) Andrzej Hajda 2006
3    Contact: andrzej.hajda@wp.pl
4    License: GNU General Public License version 2
5 */
6 
7 #include "includes.h"
8 #include "libcli/libcli.h"
9 #include "winexe.h"
10 
list_enqueue(struct list * l,const void * data,int size)11 void list_enqueue(struct list *l, const void *data, int size)
12 {
13 	struct list_item *li =
14 	    talloc_size(0, sizeof(struct list_item) + size);
15 	memcpy(li->data, data, size);
16 	li->size = size;
17 	li->next = 0;
18 	if (l->end)
19 		l->end->next = li;
20 	else
21 		l->begin = li;
22 	l->end = li;
23 }
24 
list_dequeue(struct list * l)25 void list_dequeue(struct list *l)
26 {
27 	struct list_item *li = l->begin;
28 	if (!li)
29 		return;
30 	l->begin = li->next;
31 	if (!l->begin)
32 		l->end = 0;
33 	talloc_free(li);
34 }
35 
async_read_recv(struct smbcli_request * req)36 static void async_read_recv(struct smbcli_request *req)
37 {
38 	struct async_context *c = req->async.private;
39 	NTSTATUS status;
40 
41 	status = smb_raw_read_recv(req, c->io_read);
42 	c->rreq = NULL;
43 	if (!NT_STATUS_IS_OK(status)) {
44 		DEBUG(1,
45 		      ("ERROR: smb_raw_read_recv - %s\n",
46 		       nt_errstr(status)));
47 		if (c->cb_error)
48 			c->cb_error(c->cb_ctx, ASYNC_READ_RECV, status);
49 		return;
50 	}
51 
52 	if (c->cb_read)
53 		c->cb_read(c->cb_ctx, c->buffer,
54 			   c->io_read->readx.out.nread);
55 
56 	async_read(c);
57 }
58 
async_write_recv(struct smbcli_request * req)59 static void async_write_recv(struct smbcli_request *req)
60 {
61 	struct async_context *c = req->async.private;
62 	NTSTATUS status;
63 
64 	status = smb_raw_write_recv(req, c->io_write);
65 	c->wreq = NULL;
66 	if (!NT_STATUS_IS_OK(status)) {
67 		DEBUG(1,
68 		      ("ERROR: smb_raw_write_recv - %s\n",
69 		       nt_errstr(status)));
70 		talloc_free(c->io_write);
71 		c->io_write = 0;
72 		if (c->cb_error)
73 			c->cb_error(c->cb_ctx, ASYNC_WRITE_RECV, status);
74 		return;
75 	}
76 	if (c->wq.begin) {
77 		async_write(c, c->wq.begin->data, c->wq.begin->size);
78 		list_dequeue(&c->wq);
79 	}
80 }
81 
async_open_recv(struct smbcli_request * req)82 static void async_open_recv(struct smbcli_request *req)
83 {
84 	struct async_context *c = req->async.private;
85 	NTSTATUS status;
86 
87 	DEBUG(1, ("IN: async_open_recv\n"));
88 	status = smb_raw_open_recv(req, c, c->io_open);
89 	c->rreq = NULL;
90 	if (NT_STATUS_IS_OK(status))
91 #if 1
92 		c->fd = c->io_open->openx.out.file.fnum;
93 #else
94 		c->fd = c->io_open->ntcreatex.out.file.fnum;
95 #endif
96 	talloc_free(c->io_open);
97 	c->io_open = 0;
98 	if (!NT_STATUS_IS_OK(status)) {
99 		DEBUG(1,
100 		      ("ERROR: smb_raw_open_recv - %s\n",
101 		       nt_errstr(status)));
102 		if (c->cb_error)
103 			c->cb_error(c->cb_ctx, ASYNC_OPEN_RECV, status);
104 		return;
105 	}
106 	if (c->cb_open)
107 		c->cb_open(c->cb_ctx);
108 	async_read(c);
109 }
110 
async_close_recv(struct smbcli_request * req)111 static void async_close_recv(struct smbcli_request *req)
112 {
113 	struct async_context *c = req->async.private;
114 	NTSTATUS status;
115 
116 	status = smbcli_request_simple_recv(req);
117 	talloc_free(c->io_close);
118 	c->io_close = 0;
119 	if (c->io_open) {
120 		talloc_free(c->io_open);
121 		c->io_open = 0;
122 	}
123 	if (c->io_read) {
124 		talloc_free(c->io_read);
125 		c->io_read = 0;
126 	}
127 	if (c->io_write) {
128 		talloc_free(c->io_write);
129 		c->io_write = 0;
130 	}
131 	if (c->cb_close)
132 		c->cb_close(c->cb_ctx);
133 }
134 
async_read(struct async_context * c)135 int async_read(struct async_context *c)
136 {
137 	if (!c->io_read) {
138 		c->io_read = talloc(c->tree, union smb_read);
139 		c->io_read->readx.level = RAW_READ_READX;
140 		c->io_read->readx.in.file.fnum = c->fd;
141 		c->io_read->readx.in.offset = 0;
142 		c->io_read->readx.in.mincnt = sizeof(c->buffer);
143 		c->io_read->readx.in.maxcnt = sizeof(c->buffer);
144 		c->io_read->readx.in.remaining = 0;
145 		c->io_read->readx.in.read_for_execute = False;
146 		c->io_read->readx.out.data = (uint8_t *)c->buffer;
147 	}
148 	c->rreq = smb_raw_read_send(c->tree, c->io_read);
149 	if (!c->rreq) {
150 		if (c->cb_error)
151 			c->cb_error(c->cb_ctx, ASYNC_READ,
152 				    NT_STATUS_NO_MEMORY);
153 		return 0;
154 	}
155 	c->rreq->transport->options.request_timeout = 0;
156 	c->rreq->async.fn = async_read_recv;
157 	c->rreq->async.private = c;
158 	return 1;
159 }
160 
async_open(struct async_context * c,const char * fn,int open_mode)161 int async_open(struct async_context *c, const char *fn, int open_mode)
162 {
163 	DEBUG(1, ("IN: async_open(%s, %d)\n", fn, open_mode));
164 	c->io_open = talloc_zero(c, union smb_open);
165 	if (!c->io_open)
166 		goto failed;
167 #if 1
168 	c->io_open->openx.level = RAW_OPEN_OPENX;
169 	c->io_open->openx.in.flags = 0;
170 	c->io_open->openx.in.open_mode = open_mode;
171 	c->io_open->openx.in.search_attrs =
172 	    FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
173 	c->io_open->openx.in.file_attrs = 0;
174 	c->io_open->openx.in.write_time = 0;
175 	c->io_open->openx.in.open_func = 0;
176 	c->io_open->openx.in.size = 0;
177 	c->io_open->openx.in.timeout = 0;
178 	c->io_open->openx.in.fname = fn;
179 #else
180 	c->io_open->ntcreatex.level = RAW_OPEN_NTCREATEX;
181         c->io_open->ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
182         c->io_open->ntcreatex.in.access_mask = open_mode;
183         c->io_open->ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
184         c->io_open->ntcreatex.in.impersonation    = impersonation;
185         c->io_open->ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | NTCREATEX_OPTIONS_WRITE_THROUGH;
186         c->io_open->ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC | NTCREATEX_SECURITY_ALL;
187         c->io_open->ntcreatex.in.fname = fn;
188 #endif
189 	c->rreq = smb_raw_open_send(c->tree, c->io_open);
190 	if (!c->rreq)
191 		goto failed;
192 	c->rreq->async.fn = async_open_recv;
193 	c->rreq->async.private = c;
194 	return 1;
195       failed:
196 	DEBUG(1, ("ERROR: async_open\n"));
197 	talloc_free(c);
198 	return 0;
199 }
200 
async_write(struct async_context * c,const void * buf,int len)201 int async_write(struct async_context *c, const void *buf, int len)
202 {
203 	if (c->wreq) {
204 		list_enqueue(&c->wq, buf, len);
205 		return 0;
206 	}
207 	if (!c->io_write) {
208 		c->io_write = talloc_zero(c, union smb_write);
209 		if (!c->io_write)
210 			goto failed;
211 		c->io_write->write.level = RAW_WRITE_WRITE;
212 		c->io_write->write.in.remaining = 0;
213 		c->io_write->write.in.file.fnum = c->fd;
214 		c->io_write->write.in.offset = 0;
215 	}
216 	c->io_write->write.in.count = len;
217 	c->io_write->write.in.data = buf;
218 	struct smbcli_request *req =
219 	    smb_raw_write_send(c->tree, c->io_write);
220 	if (!req)
221 		goto failed;
222 	req->async.fn = async_write_recv;
223 	req->async.private = c;
224 	return 1;
225       failed:
226 	DEBUG(1, ("ERROR: async_write\n"));
227 	talloc_free(c->io_write);
228 	c->io_write = 0;
229 	return 0;
230 }
231 
async_close(struct async_context * c)232 int async_close(struct async_context *c)
233 {
234 	if (c->rreq)
235 		smbcli_request_destroy(c->rreq);
236 	if (c->wreq)
237 		smbcli_request_destroy(c->wreq);
238 	c->rreq = c->wreq = NULL;
239 	c->io_close = talloc_zero(c, union smb_close);
240 	if (!c->io_close)
241 		goto failed;
242 	c->io_close->close.level = RAW_CLOSE_CLOSE;
243 	c->io_close->close.in.file.fnum = c->fd;
244 	c->io_close->close.in.write_time = 0;
245 	struct smbcli_request *req =
246 	    smb_raw_close_send(c->tree, c->io_close);
247 	if (!req)
248 		goto failed;
249 	req->async.fn = async_close_recv;
250 	req->async.private = c;
251 	return 1;
252       failed:
253 	DEBUG(1, ("ERROR: async_close\n"));
254 	talloc_free(c->io_close);
255 	c->io_close = 0;
256 	return 0;
257 }
258