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