Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * SMB client Python bindings used internally by Samba (for things like
5 : * samba-tool). These Python bindings may change without warning, and so
6 : * should not be used outside of the Samba codebase.
7 : *
8 : * Copyright (C) Volker Lendecke 2012
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : /*
25 : Template code to use this library:
26 :
27 : -------------------------
28 : from samba.samba3 import libsmb_samba_internal as libsmb
29 : from samba.samba3 import param as s3param
30 : from samba import (credentials,NTSTATUSError)
31 :
32 : lp = s3param.get_context()
33 : lp.load("/etc/samba/smb.conf");
34 :
35 : creds = credentials.Credentials()
36 : creds.guess(lp)
37 : creds.set_username("administrator")
38 : creds.set_password("1234")
39 :
40 : c = libsmb.Conn("127.0.0.1",
41 : "tmp",
42 : lp,
43 : creds,
44 : multi_threaded=True)
45 : -------------------------
46 : */
47 :
48 : #include "lib/replace/system/python.h"
49 : #include "includes.h"
50 : #include "python/py3compat.h"
51 : #include "python/modules.h"
52 : #include "libcli/smb/smbXcli_base.h"
53 : #include "libcli/smb/smb2_negotiate_context.h"
54 : #include "libcli/smb/reparse.h"
55 : #include "libsmb/libsmb.h"
56 : #include "libcli/security/security.h"
57 : #include "system/select.h"
58 : #include "source4/libcli/util/pyerrors.h"
59 : #include "auth/credentials/pycredentials.h"
60 : #include "trans2.h"
61 : #include "libsmb/clirap.h"
62 : #include "librpc/rpc/pyrpc_util.h"
63 :
64 : #define LIST_ATTRIBUTE_MASK \
65 : (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN)
66 :
67 : static PyTypeObject *dom_sid_Type = NULL;
68 :
69 1434 : static PyTypeObject *get_pytype(const char *module, const char *type)
70 : {
71 0 : PyObject *mod;
72 0 : PyTypeObject *result;
73 :
74 1434 : mod = PyImport_ImportModule(module);
75 1434 : if (mod == NULL) {
76 0 : PyErr_Format(PyExc_RuntimeError,
77 : "Unable to import %s to check type %s",
78 : module, type);
79 0 : return NULL;
80 : }
81 1434 : result = (PyTypeObject *)PyObject_GetAttrString(mod, type);
82 1146 : Py_DECREF(mod);
83 1434 : if (result == NULL) {
84 0 : PyErr_Format(PyExc_RuntimeError,
85 : "Unable to find type %s in module %s",
86 : module, type);
87 0 : return NULL;
88 : }
89 1434 : return result;
90 : }
91 :
92 : /*
93 : * We're using "const char * const *" for keywords,
94 : * PyArg_ParseTupleAndKeywords expects a "char **". Confine the
95 : * inevitable warnings to just one place.
96 : */
97 10785 : static int ParseTupleAndKeywords(PyObject *args, PyObject *kw,
98 : const char *format, const char * const *keywords,
99 : ...)
100 : {
101 10785 : char **_keywords = discard_const_p(char *, keywords);
102 0 : va_list a;
103 0 : int ret;
104 10785 : va_start(a, keywords);
105 10785 : ret = PyArg_VaParseTupleAndKeywords(args, kw, format,
106 : _keywords, a);
107 10785 : va_end(a);
108 10785 : return ret;
109 : }
110 :
111 : struct py_cli_thread;
112 :
113 : struct py_cli_oplock_break {
114 : uint16_t fnum;
115 : uint8_t level;
116 : };
117 :
118 : struct py_cli_state {
119 : PyObject_HEAD
120 : struct cli_state *cli;
121 : struct tevent_context *ev;
122 : int (*req_wait_fn)(struct tevent_context *ev,
123 : struct tevent_req *req);
124 : struct py_cli_thread *thread_state;
125 :
126 : struct tevent_req *oplock_waiter;
127 : struct py_cli_oplock_break *oplock_breaks;
128 : struct py_tevent_cond *oplock_cond;
129 : };
130 :
131 : #ifdef HAVE_PTHREAD
132 :
133 : #include <pthread.h>
134 :
135 : struct py_cli_thread {
136 :
137 : /*
138 : * Pipe to make the poll thread wake up in our destructor, so
139 : * that we can exit and join the thread.
140 : */
141 : int shutdown_pipe[2];
142 : struct tevent_fd *shutdown_fde;
143 : bool do_shutdown;
144 : pthread_t id;
145 :
146 : /*
147 : * Thread state to release the GIL during the poll(2) syscall
148 : */
149 : PyThreadState *py_threadstate;
150 : };
151 :
152 2 : static void *py_cli_state_poll_thread(void *private_data)
153 : {
154 2 : struct py_cli_state *self = (struct py_cli_state *)private_data;
155 2 : struct py_cli_thread *t = self->thread_state;
156 0 : PyGILState_STATE gstate;
157 :
158 2 : gstate = PyGILState_Ensure();
159 :
160 1128 : while (!t->do_shutdown) {
161 0 : int ret;
162 1126 : ret = tevent_loop_once(self->ev);
163 1126 : assert(ret == 0);
164 : }
165 2 : PyGILState_Release(gstate);
166 2 : return NULL;
167 : }
168 :
169 3752 : static void py_cli_state_trace_callback(enum tevent_trace_point point,
170 : void *private_data)
171 : {
172 3752 : struct py_cli_state *self = (struct py_cli_state *)private_data;
173 3752 : struct py_cli_thread *t = self->thread_state;
174 :
175 3752 : switch(point) {
176 750 : case TEVENT_TRACE_BEFORE_WAIT:
177 750 : assert(t->py_threadstate == NULL);
178 750 : t->py_threadstate = PyEval_SaveThread();
179 750 : break;
180 750 : case TEVENT_TRACE_AFTER_WAIT:
181 750 : assert(t->py_threadstate != NULL);
182 750 : PyEval_RestoreThread(t->py_threadstate);
183 750 : t->py_threadstate = NULL;
184 750 : break;
185 2252 : default:
186 2252 : break;
187 : }
188 3752 : }
189 :
190 2 : static void py_cli_state_shutdown_handler(struct tevent_context *ev,
191 : struct tevent_fd *fde,
192 : uint16_t flags,
193 : void *private_data)
194 : {
195 2 : struct py_cli_state *self = (struct py_cli_state *)private_data;
196 2 : struct py_cli_thread *t = self->thread_state;
197 :
198 2 : if ((flags & TEVENT_FD_READ) == 0) {
199 0 : return;
200 : }
201 2 : TALLOC_FREE(t->shutdown_fde);
202 2 : t->do_shutdown = true;
203 : }
204 :
205 2 : static int py_cli_thread_destructor(struct py_cli_thread *t)
206 : {
207 2 : char c = 0;
208 0 : ssize_t written;
209 0 : int ret;
210 :
211 0 : do {
212 : /*
213 : * This will wake the poll thread from the poll(2)
214 : */
215 2 : written = write(t->shutdown_pipe[1], &c, 1);
216 2 : } while ((written == -1) && (errno == EINTR));
217 :
218 : /*
219 : * Allow the poll thread to do its own cleanup under the GIL
220 : */
221 2 : Py_BEGIN_ALLOW_THREADS
222 2 : ret = pthread_join(t->id, NULL);
223 2 : Py_END_ALLOW_THREADS
224 2 : assert(ret == 0);
225 :
226 2 : if (t->shutdown_pipe[0] != -1) {
227 2 : close(t->shutdown_pipe[0]);
228 2 : t->shutdown_pipe[0] = -1;
229 : }
230 2 : if (t->shutdown_pipe[1] != -1) {
231 2 : close(t->shutdown_pipe[1]);
232 2 : t->shutdown_pipe[1] = -1;
233 : }
234 2 : return 0;
235 : }
236 :
237 : static int py_tevent_cond_req_wait(struct tevent_context *ev,
238 : struct tevent_req *req);
239 :
240 2 : static bool py_cli_state_setup_mt_ev(struct py_cli_state *self)
241 : {
242 2 : struct py_cli_thread *t = NULL;
243 0 : int ret;
244 :
245 2 : self->ev = tevent_context_init_byname(NULL, "poll_mt");
246 2 : if (self->ev == NULL) {
247 0 : goto fail;
248 : }
249 2 : samba_tevent_set_debug(self->ev, "pylibsmb_tevent_mt");
250 2 : tevent_set_trace_callback(self->ev, py_cli_state_trace_callback, self);
251 :
252 2 : self->req_wait_fn = py_tevent_cond_req_wait;
253 :
254 2 : self->thread_state = talloc_zero(NULL, struct py_cli_thread);
255 2 : if (self->thread_state == NULL) {
256 0 : goto fail;
257 : }
258 2 : t = self->thread_state;
259 :
260 2 : ret = pipe(t->shutdown_pipe);
261 2 : if (ret == -1) {
262 0 : goto fail;
263 : }
264 2 : t->shutdown_fde = tevent_add_fd(
265 : self->ev, self->ev, t->shutdown_pipe[0], TEVENT_FD_READ,
266 : py_cli_state_shutdown_handler, self);
267 2 : if (t->shutdown_fde == NULL) {
268 0 : goto fail;
269 : }
270 :
271 2 : PyEval_InitThreads();
272 :
273 2 : ret = pthread_create(&t->id, NULL, py_cli_state_poll_thread, self);
274 2 : if (ret != 0) {
275 0 : goto fail;
276 : }
277 2 : talloc_set_destructor(self->thread_state, py_cli_thread_destructor);
278 2 : return true;
279 :
280 0 : fail:
281 0 : if (t != NULL) {
282 0 : TALLOC_FREE(t->shutdown_fde);
283 :
284 0 : if (t->shutdown_pipe[0] != -1) {
285 0 : close(t->shutdown_pipe[0]);
286 0 : t->shutdown_pipe[0] = -1;
287 : }
288 0 : if (t->shutdown_pipe[1] != -1) {
289 0 : close(t->shutdown_pipe[1]);
290 0 : t->shutdown_pipe[1] = -1;
291 : }
292 : }
293 :
294 0 : TALLOC_FREE(self->thread_state);
295 0 : TALLOC_FREE(self->ev);
296 0 : return false;
297 : }
298 :
299 : struct py_tevent_cond {
300 : pthread_mutex_t mutex;
301 : pthread_cond_t cond;
302 : bool is_done;
303 : };
304 :
305 : static void py_tevent_signalme(struct tevent_req *req);
306 :
307 182 : static int py_tevent_cond_wait(struct py_tevent_cond *cond)
308 : {
309 0 : int ret, result;
310 :
311 182 : result = pthread_mutex_init(&cond->mutex, NULL);
312 182 : if (result != 0) {
313 0 : goto fail;
314 : }
315 182 : result = pthread_cond_init(&cond->cond, NULL);
316 182 : if (result != 0) {
317 0 : goto fail_mutex;
318 : }
319 :
320 182 : result = pthread_mutex_lock(&cond->mutex);
321 182 : if (result != 0) {
322 0 : goto fail_cond;
323 : }
324 :
325 182 : cond->is_done = false;
326 :
327 364 : while (!cond->is_done) {
328 :
329 182 : Py_BEGIN_ALLOW_THREADS
330 182 : result = pthread_cond_wait(&cond->cond, &cond->mutex);
331 182 : Py_END_ALLOW_THREADS
332 :
333 182 : if (result != 0) {
334 0 : goto fail_unlock;
335 : }
336 : }
337 :
338 182 : fail_unlock:
339 182 : ret = pthread_mutex_unlock(&cond->mutex);
340 182 : assert(ret == 0);
341 182 : fail_cond:
342 182 : ret = pthread_cond_destroy(&cond->cond);
343 182 : assert(ret == 0);
344 182 : fail_mutex:
345 182 : ret = pthread_mutex_destroy(&cond->mutex);
346 182 : assert(ret == 0);
347 182 : fail:
348 182 : return result;
349 : }
350 :
351 182 : static int py_tevent_cond_req_wait(struct tevent_context *ev,
352 : struct tevent_req *req)
353 : {
354 0 : struct py_tevent_cond cond;
355 182 : tevent_req_set_callback(req, py_tevent_signalme, &cond);
356 182 : return py_tevent_cond_wait(&cond);
357 : }
358 :
359 182 : static void py_tevent_cond_signal(struct py_tevent_cond *cond)
360 : {
361 0 : int ret;
362 :
363 182 : ret = pthread_mutex_lock(&cond->mutex);
364 182 : assert(ret == 0);
365 :
366 182 : cond->is_done = true;
367 :
368 182 : ret = pthread_cond_signal(&cond->cond);
369 182 : assert(ret == 0);
370 182 : ret = pthread_mutex_unlock(&cond->mutex);
371 182 : assert(ret == 0);
372 182 : }
373 :
374 182 : static void py_tevent_signalme(struct tevent_req *req)
375 : {
376 0 : struct py_tevent_cond *cond = (struct py_tevent_cond *)
377 182 : tevent_req_callback_data_void(req);
378 :
379 182 : py_tevent_cond_signal(cond);
380 182 : }
381 :
382 : #endif
383 :
384 : static int py_tevent_req_wait(struct tevent_context *ev,
385 : struct tevent_req *req);
386 :
387 1432 : static bool py_cli_state_setup_ev(struct py_cli_state *self)
388 : {
389 1432 : self->ev = tevent_context_init(NULL);
390 1432 : if (self->ev == NULL) {
391 0 : return false;
392 : }
393 :
394 1432 : samba_tevent_set_debug(self->ev, "pylibsmb_tevent");
395 :
396 1432 : self->req_wait_fn = py_tevent_req_wait;
397 :
398 1432 : return true;
399 : }
400 :
401 32603 : static int py_tevent_req_wait(struct tevent_context *ev,
402 : struct tevent_req *req)
403 : {
404 304357 : while (tevent_req_is_in_progress(req)) {
405 0 : int ret;
406 :
407 271754 : ret = tevent_loop_once(ev);
408 271754 : if (ret != 0) {
409 0 : return ret;
410 : }
411 : }
412 32603 : return 0;
413 : }
414 :
415 32785 : static bool py_tevent_req_wait_exc(struct py_cli_state *self,
416 : struct tevent_req *req)
417 : {
418 0 : int ret;
419 :
420 32785 : if (req == NULL) {
421 0 : PyErr_NoMemory();
422 0 : return false;
423 : }
424 32785 : ret = self->req_wait_fn(self->ev, req);
425 32785 : if (ret != 0) {
426 0 : TALLOC_FREE(req);
427 0 : errno = ret;
428 0 : PyErr_SetFromErrno(PyExc_RuntimeError);
429 0 : return false;
430 : }
431 32785 : return true;
432 : }
433 :
434 1434 : static PyObject *py_cli_state_new(PyTypeObject *type, PyObject *args,
435 : PyObject *kwds)
436 : {
437 0 : struct py_cli_state *self;
438 :
439 1434 : self = (struct py_cli_state *)type->tp_alloc(type, 0);
440 1434 : if (self == NULL) {
441 0 : return NULL;
442 : }
443 1434 : self->cli = NULL;
444 1434 : self->ev = NULL;
445 1434 : self->thread_state = NULL;
446 1434 : self->oplock_waiter = NULL;
447 1434 : self->oplock_cond = NULL;
448 1434 : self->oplock_breaks = NULL;
449 1434 : return (PyObject *)self;
450 : }
451 :
452 4 : static struct smb2_negotiate_contexts *py_cli_get_negotiate_contexts(
453 : TALLOC_CTX *mem_ctx, PyObject *list)
454 : {
455 4 : struct smb2_negotiate_contexts *ctxs = NULL;
456 0 : Py_ssize_t i, len;
457 0 : int ret;
458 :
459 4 : ret = PyList_Check(list);
460 4 : if (!ret) {
461 0 : goto fail;
462 : }
463 :
464 4 : len = PyList_Size(list);
465 4 : if (len == 0) {
466 0 : goto fail;
467 : }
468 :
469 4 : ctxs = talloc_zero(mem_ctx, struct smb2_negotiate_contexts);
470 4 : if (ctxs == NULL) {
471 0 : goto fail;
472 : }
473 :
474 8 : for (i=0; i<len; i++) {
475 0 : NTSTATUS status;
476 :
477 4 : PyObject *t = PyList_GetItem(list, i);
478 0 : Py_ssize_t tlen;
479 :
480 4 : PyObject *ptype = NULL;
481 0 : long type;
482 :
483 4 : PyObject *pdata = NULL;
484 4 : DATA_BLOB data = { .data = NULL, };
485 :
486 4 : if (t == NULL) {
487 0 : goto fail;
488 : }
489 :
490 4 : ret = PyTuple_Check(t);
491 4 : if (!ret) {
492 0 : goto fail;
493 : }
494 :
495 4 : tlen = PyTuple_Size(t);
496 4 : if (tlen != 2) {
497 0 : goto fail;
498 : }
499 :
500 4 : ptype = PyTuple_GetItem(t, 0);
501 4 : if (ptype == NULL) {
502 0 : goto fail;
503 : }
504 4 : type = PyLong_AsLong(ptype);
505 4 : if ((type < 0) || (type > UINT16_MAX)) {
506 0 : goto fail;
507 : }
508 :
509 4 : pdata = PyTuple_GetItem(t, 1);
510 :
511 4 : ret = PyBytes_Check(pdata);
512 4 : if (!ret) {
513 0 : goto fail;
514 : }
515 :
516 4 : data.data = (uint8_t *)PyBytes_AsString(pdata);
517 4 : data.length = PyBytes_Size(pdata);
518 :
519 4 : status = smb2_negotiate_context_add(
520 4 : ctxs, ctxs, type, data.data, data.length);
521 4 : if (!NT_STATUS_IS_OK(status)) {
522 0 : goto fail;
523 : }
524 : }
525 4 : return ctxs;
526 :
527 0 : fail:
528 0 : TALLOC_FREE(ctxs);
529 0 : return NULL;
530 : }
531 :
532 : static void py_cli_got_oplock_break(struct tevent_req *req);
533 :
534 1434 : static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
535 : PyObject *kwds)
536 : {
537 0 : NTSTATUS status;
538 0 : char *host, *share;
539 1434 : PyObject *creds = NULL;
540 0 : struct cli_credentials *cli_creds;
541 1434 : PyObject *py_lp = Py_None;
542 1434 : PyObject *py_multi_threaded = Py_False;
543 1434 : bool multi_threaded = false;
544 1434 : PyObject *py_force_smb1 = Py_False;
545 1434 : bool force_smb1 = false;
546 1434 : PyObject *py_ipc = Py_False;
547 1434 : PyObject *py_posix = Py_False;
548 1434 : PyObject *py_negotiate_contexts = NULL;
549 1434 : struct smb2_negotiate_contexts *negotiate_contexts = NULL;
550 1434 : bool use_ipc = false;
551 1434 : bool request_posix = false;
552 0 : struct tevent_req *req;
553 0 : bool ret;
554 1434 : int flags = 0;
555 :
556 0 : static const char *kwlist[] = {
557 : "host", "share", "lp", "creds",
558 : "multi_threaded", "force_smb1",
559 : "ipc",
560 : "posix",
561 : "negotiate_contexts",
562 : NULL
563 : };
564 :
565 1434 : PyTypeObject *py_type_Credentials = get_pytype(
566 : "samba.credentials", "Credentials");
567 1434 : if (py_type_Credentials == NULL) {
568 0 : return -1;
569 : }
570 :
571 1434 : ret = ParseTupleAndKeywords(
572 : args, kwds, "ssO|O!OOOOO", kwlist,
573 : &host, &share, &py_lp,
574 : py_type_Credentials, &creds,
575 : &py_multi_threaded,
576 : &py_force_smb1,
577 : &py_ipc,
578 : &py_posix,
579 : &py_negotiate_contexts);
580 :
581 1146 : Py_DECREF(py_type_Credentials);
582 :
583 1434 : if (!ret) {
584 0 : return -1;
585 : }
586 :
587 1434 : multi_threaded = PyObject_IsTrue(py_multi_threaded);
588 1434 : force_smb1 = PyObject_IsTrue(py_force_smb1);
589 :
590 1434 : if (force_smb1) {
591 : /*
592 : * As most of the cli_*_send() function
593 : * don't support SMB2 (it's only plugged
594 : * into the sync wrapper functions currently)
595 : * we have a way to force SMB1.
596 : */
597 22 : flags = CLI_FULL_CONNECTION_FORCE_SMB1;
598 : }
599 :
600 1434 : use_ipc = PyObject_IsTrue(py_ipc);
601 1434 : if (use_ipc) {
602 39 : flags |= CLI_FULL_CONNECTION_IPC;
603 : }
604 :
605 1434 : request_posix = PyObject_IsTrue(py_posix);
606 1434 : if (request_posix) {
607 22 : flags |= CLI_FULL_CONNECTION_REQUEST_POSIX;
608 : }
609 :
610 1434 : if (py_negotiate_contexts != NULL) {
611 4 : negotiate_contexts = py_cli_get_negotiate_contexts(
612 : talloc_tos(), py_negotiate_contexts);
613 4 : if (negotiate_contexts == NULL) {
614 0 : return -1;
615 : }
616 : }
617 :
618 1434 : if (multi_threaded) {
619 : #ifdef HAVE_PTHREAD
620 2 : ret = py_cli_state_setup_mt_ev(self);
621 2 : if (!ret) {
622 0 : return -1;
623 : }
624 : #else
625 : PyErr_SetString(PyExc_RuntimeError,
626 : "No PTHREAD support available");
627 : return -1;
628 : #endif
629 : } else {
630 1432 : ret = py_cli_state_setup_ev(self);
631 1432 : if (!ret) {
632 0 : return -1;
633 : }
634 : }
635 :
636 1434 : if (creds == NULL) {
637 0 : cli_creds = cli_credentials_init_anon(NULL);
638 : } else {
639 1434 : cli_creds = PyCredentials_AsCliCredentials(creds);
640 : }
641 :
642 1434 : req = cli_full_connection_creds_send(
643 : NULL, self->ev, "myname", host, NULL, 0, share, "?????",
644 : cli_creds, flags,
645 : negotiate_contexts);
646 1434 : if (!py_tevent_req_wait_exc(self, req)) {
647 0 : return -1;
648 : }
649 1434 : status = cli_full_connection_creds_recv(req, &self->cli);
650 1434 : TALLOC_FREE(req);
651 :
652 1434 : if (!NT_STATUS_IS_OK(status)) {
653 30 : PyErr_SetNTSTATUS(status);
654 30 : return -1;
655 : }
656 :
657 : /*
658 : * Oplocks require a multi threaded connection
659 : */
660 1404 : if (self->thread_state == NULL) {
661 1402 : return 0;
662 : }
663 :
664 4 : self->oplock_waiter = cli_smb_oplock_break_waiter_send(
665 2 : self->ev, self->ev, self->cli);
666 2 : if (self->oplock_waiter == NULL) {
667 0 : PyErr_NoMemory();
668 0 : return -1;
669 : }
670 2 : tevent_req_set_callback(self->oplock_waiter, py_cli_got_oplock_break,
671 : self);
672 2 : return 0;
673 : }
674 :
675 0 : static void py_cli_got_oplock_break(struct tevent_req *req)
676 : {
677 0 : struct py_cli_state *self = (struct py_cli_state *)
678 0 : tevent_req_callback_data_void(req);
679 0 : struct py_cli_oplock_break b;
680 0 : struct py_cli_oplock_break *tmp;
681 0 : size_t num_breaks;
682 0 : NTSTATUS status;
683 :
684 0 : status = cli_smb_oplock_break_waiter_recv(req, &b.fnum, &b.level);
685 0 : TALLOC_FREE(req);
686 0 : self->oplock_waiter = NULL;
687 :
688 0 : if (!NT_STATUS_IS_OK(status)) {
689 0 : return;
690 : }
691 :
692 0 : num_breaks = talloc_array_length(self->oplock_breaks);
693 0 : tmp = talloc_realloc(self->ev, self->oplock_breaks,
694 : struct py_cli_oplock_break, num_breaks+1);
695 0 : if (tmp == NULL) {
696 0 : return;
697 : }
698 0 : self->oplock_breaks = tmp;
699 0 : self->oplock_breaks[num_breaks] = b;
700 :
701 0 : if (self->oplock_cond != NULL) {
702 0 : py_tevent_cond_signal(self->oplock_cond);
703 : }
704 :
705 0 : self->oplock_waiter = cli_smb_oplock_break_waiter_send(
706 0 : self->ev, self->ev, self->cli);
707 0 : if (self->oplock_waiter == NULL) {
708 0 : return;
709 : }
710 0 : tevent_req_set_callback(self->oplock_waiter, py_cli_got_oplock_break,
711 : self);
712 : }
713 :
714 0 : static PyObject *py_cli_get_oplock_break(struct py_cli_state *self,
715 : PyObject *args)
716 : {
717 0 : size_t num_oplock_breaks;
718 :
719 0 : if (!PyArg_ParseTuple(args, "")) {
720 0 : return NULL;
721 : }
722 :
723 0 : if (self->thread_state == NULL) {
724 0 : PyErr_SetString(PyExc_RuntimeError,
725 : "get_oplock_break() only possible on "
726 : "a multi_threaded connection");
727 0 : return NULL;
728 : }
729 :
730 0 : if (self->oplock_cond != NULL) {
731 0 : errno = EBUSY;
732 0 : PyErr_SetFromErrno(PyExc_RuntimeError);
733 0 : return NULL;
734 : }
735 :
736 0 : num_oplock_breaks = talloc_array_length(self->oplock_breaks);
737 :
738 0 : if (num_oplock_breaks == 0) {
739 0 : struct py_tevent_cond cond;
740 0 : int ret;
741 :
742 0 : self->oplock_cond = &cond;
743 0 : ret = py_tevent_cond_wait(&cond);
744 0 : self->oplock_cond = NULL;
745 :
746 0 : if (ret != 0) {
747 0 : errno = ret;
748 0 : PyErr_SetFromErrno(PyExc_RuntimeError);
749 0 : return NULL;
750 : }
751 : }
752 :
753 0 : num_oplock_breaks = talloc_array_length(self->oplock_breaks);
754 0 : if (num_oplock_breaks > 0) {
755 0 : PyObject *result;
756 :
757 0 : result = Py_BuildValue(
758 : "{s:i,s:i}",
759 0 : "fnum", self->oplock_breaks[0].fnum,
760 0 : "level", self->oplock_breaks[0].level);
761 :
762 0 : memmove(&self->oplock_breaks[0], &self->oplock_breaks[1],
763 : sizeof(self->oplock_breaks[0]) *
764 0 : (num_oplock_breaks - 1));
765 0 : self->oplock_breaks = talloc_realloc(
766 : NULL, self->oplock_breaks, struct py_cli_oplock_break,
767 : num_oplock_breaks - 1);
768 :
769 0 : return result;
770 : }
771 0 : Py_RETURN_NONE;
772 : }
773 :
774 1434 : static void py_cli_state_dealloc(struct py_cli_state *self)
775 : {
776 1434 : TALLOC_FREE(self->thread_state);
777 1434 : TALLOC_FREE(self->oplock_waiter);
778 1434 : TALLOC_FREE(self->ev);
779 :
780 1434 : if (self->cli != NULL) {
781 1404 : cli_shutdown(self->cli);
782 1404 : self->cli = NULL;
783 : }
784 1434 : Py_TYPE(self)->tp_free((PyObject *)self);
785 1434 : }
786 :
787 495 : static PyObject *py_cli_settimeout(struct py_cli_state *self, PyObject *args)
788 : {
789 495 : unsigned int nmsecs = 0;
790 495 : unsigned int omsecs = 0;
791 :
792 495 : if (!PyArg_ParseTuple(args, "I", &nmsecs)) {
793 0 : return NULL;
794 : }
795 :
796 495 : omsecs = cli_set_timeout(self->cli, nmsecs);
797 :
798 495 : return PyLong_FromLong(omsecs);
799 : }
800 :
801 48 : static PyObject *py_cli_echo(struct py_cli_state *self,
802 : PyObject *Py_UNUSED(ignored))
803 : {
804 48 : DATA_BLOB data = data_blob_string_const("keepalive");
805 48 : struct tevent_req *req = NULL;
806 0 : NTSTATUS status;
807 :
808 48 : req = cli_echo_send(NULL, self->ev, self->cli, 1, data);
809 48 : if (!py_tevent_req_wait_exc(self, req)) {
810 0 : return NULL;
811 : }
812 48 : status = cli_echo_recv(req);
813 48 : TALLOC_FREE(req);
814 48 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
815 :
816 48 : Py_RETURN_NONE;
817 : }
818 :
819 945 : static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
820 : PyObject *kwds)
821 : {
822 0 : char *fname;
823 945 : unsigned CreateFlags = 0;
824 945 : unsigned DesiredAccess = FILE_GENERIC_READ;
825 945 : unsigned FileAttributes = 0;
826 945 : unsigned ShareAccess = 0;
827 945 : unsigned CreateDisposition = FILE_OPEN;
828 945 : unsigned CreateOptions = 0;
829 945 : unsigned ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
830 945 : unsigned SecurityFlags = 0;
831 0 : uint16_t fnum;
832 0 : struct tevent_req *req;
833 0 : NTSTATUS status;
834 :
835 0 : static const char *kwlist[] = {
836 : "Name", "CreateFlags", "DesiredAccess", "FileAttributes",
837 : "ShareAccess", "CreateDisposition", "CreateOptions",
838 : "ImpersonationLevel", "SecurityFlags", NULL };
839 :
840 945 : if (!ParseTupleAndKeywords(
841 : args, kwds, "s|IIIIIIII", kwlist,
842 : &fname, &CreateFlags, &DesiredAccess, &FileAttributes,
843 : &ShareAccess, &CreateDisposition, &CreateOptions,
844 : &ImpersonationLevel, &SecurityFlags)) {
845 0 : return NULL;
846 : }
847 :
848 945 : req = cli_ntcreate_send(NULL, self->ev, self->cli, fname, CreateFlags,
849 : DesiredAccess, FileAttributes, ShareAccess,
850 : CreateDisposition, CreateOptions,
851 : ImpersonationLevel, SecurityFlags);
852 945 : if (!py_tevent_req_wait_exc(self, req)) {
853 0 : return NULL;
854 : }
855 945 : status = cli_ntcreate_recv(req, &fnum, NULL);
856 945 : TALLOC_FREE(req);
857 :
858 945 : if (!NT_STATUS_IS_OK(status)) {
859 0 : PyErr_SetNTSTATUS(status);
860 0 : return NULL;
861 : }
862 945 : return Py_BuildValue("I", (unsigned)fnum);
863 : }
864 :
865 2130 : static struct smb2_create_blobs *py_cli_get_create_contexts(
866 : TALLOC_CTX *mem_ctx, PyObject *list)
867 : {
868 2130 : struct smb2_create_blobs *ctxs = NULL;
869 0 : Py_ssize_t i, len;
870 0 : int ret;
871 :
872 2130 : ret = PyList_Check(list);
873 2130 : if (!ret) {
874 0 : goto fail;
875 : }
876 :
877 2130 : len = PyList_Size(list);
878 2130 : if (len == 0) {
879 0 : goto fail;
880 : }
881 :
882 2130 : ctxs = talloc_zero(mem_ctx, struct smb2_create_blobs);
883 2130 : if (ctxs == NULL) {
884 0 : goto fail;
885 : }
886 :
887 4260 : for (i=0; i<len; i++) {
888 0 : NTSTATUS status;
889 :
890 2130 : PyObject *t = NULL;
891 0 : Py_ssize_t tlen;
892 :
893 2130 : PyObject *pname = NULL;
894 2130 : char *name = NULL;
895 :
896 2130 : PyObject *pdata = NULL;
897 2130 : DATA_BLOB data = { .data = NULL, };
898 :
899 2130 : t = PyList_GetItem(list, i);
900 2130 : if (t == NULL) {
901 0 : goto fail;
902 : }
903 :
904 2130 : ret = PyTuple_Check(t);
905 2130 : if (!ret) {
906 0 : goto fail;
907 : }
908 :
909 2130 : tlen = PyTuple_Size(t);
910 2130 : if (tlen != 2) {
911 0 : goto fail;
912 : }
913 :
914 2130 : pname = PyTuple_GetItem(t, 0);
915 2130 : if (pname == NULL) {
916 0 : goto fail;
917 : }
918 2130 : ret = PyBytes_Check(pname);
919 2130 : if (!ret) {
920 0 : goto fail;
921 : }
922 2130 : name = PyBytes_AsString(pname);
923 :
924 2130 : pdata = PyTuple_GetItem(t, 1);
925 2130 : if (pdata == NULL) {
926 0 : goto fail;
927 : }
928 2130 : ret = PyBytes_Check(pdata);
929 2130 : if (!ret) {
930 0 : goto fail;
931 : }
932 2130 : data = (DATA_BLOB) {
933 2130 : .data = (uint8_t *)PyBytes_AsString(pdata),
934 2130 : .length = PyBytes_Size(pdata),
935 : };
936 2130 : status = smb2_create_blob_add(ctxs, ctxs, name, data);
937 2130 : if (!NT_STATUS_IS_OK(status)) {
938 0 : goto fail;
939 : }
940 : }
941 2130 : return ctxs;
942 :
943 0 : fail:
944 0 : TALLOC_FREE(ctxs);
945 0 : return NULL;
946 : }
947 :
948 2126 : static PyObject *py_cli_create_contexts(const struct smb2_create_blobs *blobs)
949 : {
950 2126 : PyObject *py_blobs = NULL;
951 0 : uint32_t i;
952 :
953 2126 : if (blobs == NULL) {
954 0 : Py_RETURN_NONE;
955 : }
956 :
957 2126 : py_blobs = PyList_New(blobs->num_blobs);
958 2126 : if (py_blobs == NULL) {
959 0 : return NULL;
960 : }
961 :
962 4252 : for (i=0; i<blobs->num_blobs; i++) {
963 2126 : struct smb2_create_blob *blob = &blobs->blobs[i];
964 2126 : PyObject *py_blob = NULL;
965 0 : int ret;
966 :
967 2126 : py_blob = Py_BuildValue(
968 : "(yy#)",
969 : blob->tag,
970 : blob->data.data,
971 2126 : (int)blob->data.length);
972 2126 : if (py_blob == NULL) {
973 0 : goto fail;
974 : }
975 :
976 2126 : ret = PyList_SetItem(py_blobs, i, py_blob);
977 2126 : if (ret == -1) {
978 0 : Py_XDECREF(py_blob);
979 0 : goto fail;
980 : }
981 : }
982 2126 : return py_blobs;
983 :
984 0 : fail:
985 0 : Py_XDECREF(py_blobs);
986 0 : return NULL;
987 : }
988 :
989 2126 : static PyObject *py_cli_create_returns(const struct smb_create_returns *r)
990 : {
991 2126 : PyObject *v = NULL;
992 :
993 2126 : v = Py_BuildValue(
994 : "{sLsLsLsLsLsLsLsLsLsL}",
995 : "oplock_level",
996 2126 : (unsigned long long)r->oplock_level,
997 : "flags",
998 2126 : (unsigned long long)r->flags,
999 : "create_action",
1000 2126 : (unsigned long long)r->create_action,
1001 : "creation_time",
1002 2126 : (unsigned long long)r->creation_time,
1003 : "last_access_time",
1004 2126 : (unsigned long long)r->last_access_time,
1005 : "last_write_time",
1006 2126 : (unsigned long long)r->last_write_time,
1007 : "change_time",
1008 2126 : (unsigned long long)r->change_time,
1009 : "allocation_size",
1010 2126 : (unsigned long long)r->allocation_size,
1011 : "end_of_file",
1012 2126 : (unsigned long long)r->end_of_file,
1013 : "file_attributes",
1014 2126 : (unsigned long long)r->file_attributes);
1015 2126 : return v;
1016 : }
1017 :
1018 0 : static PyObject *py_cli_symlink_error(const struct symlink_reparse_struct *s)
1019 : {
1020 0 : char *subst_utf8 = NULL, *print_utf8 = NULL;
1021 0 : size_t subst_utf8_len, print_utf8_len;
1022 0 : PyObject *v = NULL;
1023 0 : bool ok = true;
1024 :
1025 : /*
1026 : * Python wants utf-8, regardless of our unix charset (which
1027 : * most likely is utf-8 these days, but you never know).
1028 : */
1029 :
1030 0 : ok = convert_string_talloc(
1031 : talloc_tos(),
1032 : CH_UNIX,
1033 : CH_UTF8,
1034 0 : s->substitute_name,
1035 0 : strlen(s->substitute_name),
1036 : &subst_utf8,
1037 : &subst_utf8_len);
1038 0 : if (!ok) {
1039 0 : goto fail;
1040 : }
1041 :
1042 0 : ok = convert_string_talloc(
1043 : talloc_tos(),
1044 : CH_UNIX,
1045 : CH_UTF8,
1046 0 : s->print_name,
1047 0 : strlen(s->print_name),
1048 : &print_utf8,
1049 : &print_utf8_len);
1050 0 : if (!ok) {
1051 0 : goto fail;
1052 : }
1053 :
1054 0 : v = Py_BuildValue(
1055 : "{sLsssssL}",
1056 : "unparsed_path_length",
1057 0 : (unsigned long long)s->unparsed_path_length,
1058 : "substitute_name",
1059 : subst_utf8,
1060 : "print_name",
1061 : print_utf8,
1062 : "flags",
1063 0 : (unsigned long long)s->flags);
1064 :
1065 0 : fail:
1066 0 : TALLOC_FREE(subst_utf8);
1067 0 : TALLOC_FREE(print_utf8);
1068 0 : return v;
1069 : }
1070 :
1071 2138 : static PyObject *py_cli_create_ex(
1072 : struct py_cli_state *self, PyObject *args, PyObject *kwds)
1073 : {
1074 2138 : char *fname = NULL;
1075 2138 : unsigned CreateFlags = 0;
1076 2138 : unsigned DesiredAccess = FILE_GENERIC_READ;
1077 2138 : unsigned FileAttributes = 0;
1078 2138 : unsigned ShareAccess = 0;
1079 2138 : unsigned CreateDisposition = FILE_OPEN;
1080 2138 : unsigned CreateOptions = 0;
1081 2138 : unsigned ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
1082 2138 : unsigned SecurityFlags = 0;
1083 2138 : PyObject *py_create_contexts_in = NULL;
1084 2138 : PyObject *py_create_contexts_out = NULL;
1085 2138 : struct smb2_create_blobs *create_contexts_in = NULL;
1086 2138 : struct smb2_create_blobs create_contexts_out = { .num_blobs = 0 };
1087 2138 : struct smb_create_returns cr = { .create_action = 0, };
1088 2138 : struct symlink_reparse_struct *symlink = NULL;
1089 2138 : PyObject *py_cr = NULL;
1090 0 : uint16_t fnum;
1091 0 : struct tevent_req *req;
1092 0 : NTSTATUS status;
1093 0 : int ret;
1094 0 : bool ok;
1095 2138 : PyObject *v = NULL;
1096 :
1097 0 : static const char *kwlist[] = {
1098 : "Name",
1099 : "CreateFlags",
1100 : "DesiredAccess",
1101 : "FileAttributes",
1102 : "ShareAccess",
1103 : "CreateDisposition",
1104 : "CreateOptions",
1105 : "ImpersonationLevel",
1106 : "SecurityFlags",
1107 : "CreateContexts",
1108 : NULL };
1109 :
1110 2138 : ret = ParseTupleAndKeywords(
1111 : args,
1112 : kwds,
1113 : "s|IIIIIIIIO",
1114 : kwlist,
1115 : &fname,
1116 : &CreateFlags,
1117 : &DesiredAccess,
1118 : &FileAttributes,
1119 : &ShareAccess,
1120 : &CreateDisposition,
1121 : &CreateOptions,
1122 : &ImpersonationLevel,
1123 : &SecurityFlags,
1124 : &py_create_contexts_in);
1125 2138 : if (!ret) {
1126 0 : return NULL;
1127 : }
1128 :
1129 2138 : if (py_create_contexts_in != NULL) {
1130 2130 : create_contexts_in = py_cli_get_create_contexts(
1131 : NULL, py_create_contexts_in);
1132 2130 : if (create_contexts_in == NULL) {
1133 0 : errno = EINVAL;
1134 0 : PyErr_SetFromErrno(PyExc_RuntimeError);
1135 0 : return NULL;
1136 : }
1137 : }
1138 :
1139 2138 : if (smbXcli_conn_protocol(self->cli->conn) >= PROTOCOL_SMB2_02) {
1140 2138 : struct cli_smb2_create_flags cflags = {
1141 2138 : .batch_oplock = (CreateFlags & REQUEST_BATCH_OPLOCK),
1142 2138 : .exclusive_oplock = (CreateFlags & REQUEST_OPLOCK),
1143 : };
1144 :
1145 2138 : req = cli_smb2_create_fnum_send(
1146 : NULL,
1147 : self->ev,
1148 : self->cli,
1149 : fname,
1150 : cflags,
1151 : ImpersonationLevel,
1152 : DesiredAccess,
1153 : FileAttributes,
1154 : ShareAccess,
1155 : CreateDisposition,
1156 : CreateOptions,
1157 : create_contexts_in);
1158 : } else {
1159 0 : req = cli_ntcreate_send(
1160 : NULL,
1161 : self->ev,
1162 : self->cli,
1163 : fname,
1164 : CreateFlags,
1165 : DesiredAccess,
1166 : FileAttributes,
1167 : ShareAccess,
1168 : CreateDisposition,
1169 : CreateOptions,
1170 : ImpersonationLevel,
1171 : SecurityFlags);
1172 : }
1173 :
1174 2138 : TALLOC_FREE(create_contexts_in);
1175 :
1176 2138 : ok = py_tevent_req_wait_exc(self, req);
1177 2138 : if (!ok) {
1178 0 : return NULL;
1179 : }
1180 :
1181 2138 : if (smbXcli_conn_protocol(self->cli->conn) >= PROTOCOL_SMB2_02) {
1182 2138 : status = cli_smb2_create_fnum_recv(
1183 : req,
1184 : &fnum,
1185 : &cr,
1186 : NULL,
1187 : &create_contexts_out,
1188 : &symlink);
1189 : } else {
1190 0 : status = cli_ntcreate_recv(req, &fnum, &cr);
1191 : }
1192 :
1193 2138 : TALLOC_FREE(req);
1194 :
1195 2138 : if (!NT_STATUS_IS_OK(status)) {
1196 12 : goto fail;
1197 : }
1198 :
1199 2126 : SMB_ASSERT(symlink == NULL);
1200 :
1201 2126 : py_create_contexts_out = py_cli_create_contexts(&create_contexts_out);
1202 2126 : TALLOC_FREE(create_contexts_out.blobs);
1203 2126 : if (py_create_contexts_out == NULL) {
1204 0 : goto nomem;
1205 : }
1206 :
1207 2126 : py_cr = py_cli_create_returns(&cr);
1208 2126 : if (py_cr == NULL) {
1209 0 : goto nomem;
1210 : }
1211 :
1212 2126 : v = Py_BuildValue("(IOO)",
1213 : (unsigned)fnum,
1214 : py_cr,
1215 : py_create_contexts_out);
1216 2126 : return v;
1217 0 : nomem:
1218 0 : status = NT_STATUS_NO_MEMORY;
1219 12 : fail:
1220 12 : Py_XDECREF(py_create_contexts_out);
1221 12 : Py_XDECREF(py_cr);
1222 12 : Py_XDECREF(v);
1223 :
1224 12 : if (NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK) &&
1225 0 : (symlink != NULL)) {
1226 0 : PyErr_SetObject(
1227 : PyObject_GetAttrString(
1228 : PyImport_ImportModule("samba"),
1229 : "NTSTATUSError"),
1230 : Py_BuildValue(
1231 : "I,s,O",
1232 : NT_STATUS_V(status),
1233 : get_friendly_nt_error_msg(status),
1234 : py_cli_symlink_error(symlink)));
1235 : } else {
1236 12 : PyErr_SetNTSTATUS(status);
1237 : }
1238 12 : return NULL;
1239 : }
1240 :
1241 3069 : static PyObject *py_cli_close(struct py_cli_state *self, PyObject *args)
1242 : {
1243 0 : struct tevent_req *req;
1244 0 : int fnum;
1245 3069 : int flags = 0;
1246 0 : NTSTATUS status;
1247 :
1248 3069 : if (!PyArg_ParseTuple(args, "i|i", &fnum, &flags)) {
1249 0 : return NULL;
1250 : }
1251 :
1252 3069 : req = cli_close_send(NULL, self->ev, self->cli, fnum, flags);
1253 3069 : if (!py_tevent_req_wait_exc(self, req)) {
1254 0 : return NULL;
1255 : }
1256 3069 : status = cli_close_recv(req);
1257 3069 : TALLOC_FREE(req);
1258 :
1259 3069 : if (!NT_STATUS_IS_OK(status)) {
1260 0 : PyErr_SetNTSTATUS(status);
1261 0 : return NULL;
1262 : }
1263 3069 : Py_RETURN_NONE;
1264 : }
1265 :
1266 18 : static PyObject *py_cli_rename(
1267 : struct py_cli_state *self, PyObject *args, PyObject *kwds)
1268 : {
1269 18 : char *fname_src = NULL, *fname_dst = NULL;
1270 18 : int replace = false;
1271 18 : struct tevent_req *req = NULL;
1272 0 : NTSTATUS status;
1273 0 : bool ok;
1274 :
1275 0 : static const char *kwlist[] = { "src", "dst", "replace", NULL };
1276 :
1277 18 : ok = ParseTupleAndKeywords(
1278 : args, kwds, "ss|p", kwlist, &fname_src, &fname_dst, &replace);
1279 18 : if (!ok) {
1280 0 : return NULL;
1281 : }
1282 :
1283 18 : req = cli_rename_send(
1284 : NULL, self->ev, self->cli, fname_src, fname_dst, replace);
1285 18 : if (!py_tevent_req_wait_exc(self, req)) {
1286 0 : return NULL;
1287 : }
1288 18 : status = cli_rename_recv(req);
1289 18 : TALLOC_FREE(req);
1290 :
1291 18 : if (!NT_STATUS_IS_OK(status)) {
1292 2 : PyErr_SetNTSTATUS(status);
1293 2 : return NULL;
1294 : }
1295 16 : Py_RETURN_NONE;
1296 : }
1297 :
1298 :
1299 : struct push_state {
1300 : char *data;
1301 : off_t nread;
1302 : off_t total_data;
1303 : };
1304 :
1305 : /*
1306 : * cli_push() helper to write a chunk of data to a remote file
1307 : */
1308 2126 : static size_t push_data(uint8_t *buf, size_t n, void *priv)
1309 : {
1310 2126 : struct push_state *state = (struct push_state *)priv;
1311 2126 : char *curr_ptr = NULL;
1312 0 : off_t remaining;
1313 0 : size_t copied_bytes;
1314 :
1315 2126 : if (state->nread >= state->total_data) {
1316 1100 : return 0;
1317 : }
1318 :
1319 1026 : curr_ptr = state->data + state->nread;
1320 1026 : remaining = state->total_data - state->nread;
1321 1026 : copied_bytes = MIN(remaining, n);
1322 :
1323 1026 : memcpy(buf, curr_ptr, copied_bytes);
1324 1026 : state->nread += copied_bytes;
1325 1026 : return copied_bytes;
1326 : }
1327 :
1328 : /*
1329 : * Writes a file with the contents specified
1330 : */
1331 1100 : static PyObject *py_smb_savefile(struct py_cli_state *self, PyObject *args)
1332 : {
1333 0 : uint16_t fnum;
1334 1100 : const char *filename = NULL;
1335 1100 : char *data = NULL;
1336 1100 : Py_ssize_t size = 0;
1337 0 : NTSTATUS status;
1338 1100 : struct tevent_req *req = NULL;
1339 0 : struct push_state state;
1340 :
1341 1100 : if (!PyArg_ParseTuple(args, "s"PYARG_BYTES_LEN":savefile", &filename,
1342 : &data, &size)) {
1343 0 : return NULL;
1344 : }
1345 :
1346 : /* create a new file handle for writing to */
1347 1100 : req = cli_ntcreate_send(NULL, self->ev, self->cli, filename, 0,
1348 : FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
1349 : FILE_SHARE_READ|FILE_SHARE_WRITE,
1350 : FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE,
1351 : SMB2_IMPERSONATION_IMPERSONATION, 0);
1352 1100 : if (!py_tevent_req_wait_exc(self, req)) {
1353 0 : return NULL;
1354 : }
1355 1100 : status = cli_ntcreate_recv(req, &fnum, NULL);
1356 1100 : TALLOC_FREE(req);
1357 1100 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
1358 :
1359 : /* write the new file contents */
1360 1100 : state.data = data;
1361 1100 : state.nread = 0;
1362 1100 : state.total_data = size;
1363 :
1364 1100 : req = cli_push_send(NULL, self->ev, self->cli, fnum, 0, 0, 0,
1365 : push_data, &state);
1366 1100 : if (!py_tevent_req_wait_exc(self, req)) {
1367 0 : return NULL;
1368 : }
1369 1100 : status = cli_push_recv(req);
1370 1100 : TALLOC_FREE(req);
1371 1100 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
1372 :
1373 : /* close the file handle */
1374 1100 : req = cli_close_send(NULL, self->ev, self->cli, fnum, 0);
1375 1100 : if (!py_tevent_req_wait_exc(self, req)) {
1376 0 : return NULL;
1377 : }
1378 1100 : status = cli_close_recv(req);
1379 1100 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
1380 :
1381 1100 : Py_RETURN_NONE;
1382 : }
1383 :
1384 1004 : static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args,
1385 : PyObject *kwds)
1386 : {
1387 0 : int fnum;
1388 1004 : unsigned mode = 0;
1389 0 : char *buf;
1390 0 : Py_ssize_t buflen;
1391 0 : unsigned long long offset;
1392 0 : struct tevent_req *req;
1393 0 : NTSTATUS status;
1394 0 : size_t written;
1395 :
1396 0 : static const char *kwlist[] = {
1397 : "fnum", "buffer", "offset", "mode", NULL };
1398 :
1399 1004 : if (!ParseTupleAndKeywords(
1400 : args, kwds, "i" PYARG_BYTES_LEN "K|I", kwlist,
1401 : &fnum, &buf, &buflen, &offset, &mode)) {
1402 0 : return NULL;
1403 : }
1404 :
1405 1004 : req = cli_write_send(NULL, self->ev, self->cli, fnum, mode,
1406 : (uint8_t *)buf, offset, buflen);
1407 1004 : if (!py_tevent_req_wait_exc(self, req)) {
1408 0 : return NULL;
1409 : }
1410 1004 : status = cli_write_recv(req, &written);
1411 1004 : TALLOC_FREE(req);
1412 :
1413 1004 : if (!NT_STATUS_IS_OK(status)) {
1414 0 : PyErr_SetNTSTATUS(status);
1415 0 : return NULL;
1416 : }
1417 1004 : return Py_BuildValue("K", (unsigned long long)written);
1418 : }
1419 :
1420 : /*
1421 : * Returns the size of the given file
1422 : */
1423 1322 : static NTSTATUS py_smb_filesize(struct py_cli_state *self, uint16_t fnum,
1424 : off_t *size)
1425 : {
1426 0 : NTSTATUS status;
1427 1322 : struct tevent_req *req = NULL;
1428 :
1429 1322 : req = cli_qfileinfo_basic_send(NULL, self->ev, self->cli, fnum);
1430 1322 : if (!py_tevent_req_wait_exc(self, req)) {
1431 0 : return NT_STATUS_INTERNAL_ERROR;
1432 : }
1433 1322 : status = cli_qfileinfo_basic_recv(
1434 : req, NULL, size, NULL, NULL, NULL, NULL, NULL);
1435 1322 : TALLOC_FREE(req);
1436 1322 : return status;
1437 : }
1438 :
1439 : /*
1440 : * Loads the specified file's contents and returns it
1441 : */
1442 1478 : static PyObject *py_smb_loadfile(struct py_cli_state *self, PyObject *args)
1443 : {
1444 0 : NTSTATUS status;
1445 1478 : const char *filename = NULL;
1446 1478 : struct tevent_req *req = NULL;
1447 0 : uint16_t fnum;
1448 0 : off_t size;
1449 1478 : char *buf = NULL;
1450 1478 : off_t nread = 0;
1451 1478 : PyObject *result = NULL;
1452 :
1453 1478 : if (!PyArg_ParseTuple(args, "s:loadfile", &filename)) {
1454 0 : return NULL;
1455 : }
1456 :
1457 : /* get a read file handle */
1458 1478 : req = cli_ntcreate_send(NULL, self->ev, self->cli, filename, 0,
1459 : FILE_READ_DATA | FILE_READ_ATTRIBUTES,
1460 : FILE_ATTRIBUTE_NORMAL,
1461 : FILE_SHARE_READ, FILE_OPEN, 0,
1462 : SMB2_IMPERSONATION_IMPERSONATION, 0);
1463 1478 : if (!py_tevent_req_wait_exc(self, req)) {
1464 0 : return NULL;
1465 : }
1466 1478 : status = cli_ntcreate_recv(req, &fnum, NULL);
1467 1478 : TALLOC_FREE(req);
1468 1478 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
1469 :
1470 : /* get a buffer to hold the file contents */
1471 1322 : status = py_smb_filesize(self, fnum, &size);
1472 1322 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
1473 :
1474 1322 : result = PyBytes_FromStringAndSize(NULL, size);
1475 1322 : if (result == NULL) {
1476 0 : return NULL;
1477 : }
1478 :
1479 : /* read the file contents */
1480 1322 : buf = PyBytes_AS_STRING(result);
1481 1322 : req = cli_pull_send(NULL, self->ev, self->cli, fnum, 0, size,
1482 : size, cli_read_sink, &buf);
1483 1322 : if (!py_tevent_req_wait_exc(self, req)) {
1484 0 : Py_XDECREF(result);
1485 0 : return NULL;
1486 : }
1487 1322 : status = cli_pull_recv(req, &nread);
1488 1322 : TALLOC_FREE(req);
1489 1322 : if (!NT_STATUS_IS_OK(status)) {
1490 0 : Py_XDECREF(result);
1491 0 : PyErr_SetNTSTATUS(status);
1492 0 : return NULL;
1493 : }
1494 :
1495 : /* close the file handle */
1496 1322 : req = cli_close_send(NULL, self->ev, self->cli, fnum, 0);
1497 1322 : if (!py_tevent_req_wait_exc(self, req)) {
1498 0 : Py_XDECREF(result);
1499 0 : return NULL;
1500 : }
1501 1322 : status = cli_close_recv(req);
1502 1322 : TALLOC_FREE(req);
1503 1322 : if (!NT_STATUS_IS_OK(status)) {
1504 0 : Py_XDECREF(result);
1505 0 : PyErr_SetNTSTATUS(status);
1506 0 : return NULL;
1507 : }
1508 :
1509 : /* sanity-check we read the expected number of bytes */
1510 1322 : if (nread > size) {
1511 0 : Py_XDECREF(result);
1512 0 : PyErr_Format(PyExc_IOError,
1513 : "read invalid - got %zu requested %zu",
1514 : nread, size);
1515 0 : return NULL;
1516 : }
1517 :
1518 1322 : if (nread < size) {
1519 0 : if (_PyBytes_Resize(&result, nread) < 0) {
1520 0 : return NULL;
1521 : }
1522 : }
1523 :
1524 1322 : return result;
1525 : }
1526 :
1527 495 : static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args,
1528 : PyObject *kwds)
1529 : {
1530 0 : int fnum;
1531 0 : unsigned long long offset;
1532 0 : unsigned size;
1533 0 : struct tevent_req *req;
1534 0 : NTSTATUS status;
1535 0 : char *buf;
1536 0 : size_t received;
1537 0 : PyObject *result;
1538 :
1539 0 : static const char *kwlist[] = {
1540 : "fnum", "offset", "size", NULL };
1541 :
1542 495 : if (!ParseTupleAndKeywords(
1543 : args, kwds, "iKI", kwlist, &fnum, &offset,
1544 : &size)) {
1545 0 : return NULL;
1546 : }
1547 :
1548 495 : result = PyBytes_FromStringAndSize(NULL, size);
1549 495 : if (result == NULL) {
1550 0 : return NULL;
1551 : }
1552 495 : buf = PyBytes_AS_STRING(result);
1553 :
1554 495 : req = cli_read_send(NULL, self->ev, self->cli, fnum,
1555 : buf, offset, size);
1556 495 : if (!py_tevent_req_wait_exc(self, req)) {
1557 0 : Py_XDECREF(result);
1558 0 : return NULL;
1559 : }
1560 495 : status = cli_read_recv(req, &received);
1561 495 : TALLOC_FREE(req);
1562 :
1563 495 : if (!NT_STATUS_IS_OK(status)) {
1564 3 : Py_XDECREF(result);
1565 3 : PyErr_SetNTSTATUS(status);
1566 3 : return NULL;
1567 : }
1568 :
1569 492 : if (received > size) {
1570 0 : Py_XDECREF(result);
1571 0 : PyErr_Format(PyExc_IOError,
1572 : "read invalid - got %zu requested %u",
1573 : received, size);
1574 0 : return NULL;
1575 : }
1576 :
1577 492 : if (received < size) {
1578 492 : if (_PyBytes_Resize(&result, received) < 0) {
1579 0 : return NULL;
1580 : }
1581 : }
1582 :
1583 492 : return result;
1584 : }
1585 :
1586 0 : static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args,
1587 : PyObject *kwds)
1588 : {
1589 0 : int fnum;
1590 0 : unsigned long long size;
1591 0 : struct tevent_req *req;
1592 0 : NTSTATUS status;
1593 :
1594 0 : static const char *kwlist[] = {
1595 : "fnum", "size", NULL };
1596 :
1597 0 : if (!ParseTupleAndKeywords(
1598 : args, kwds, "IK", kwlist, &fnum, &size)) {
1599 0 : return NULL;
1600 : }
1601 :
1602 0 : req = cli_ftruncate_send(NULL, self->ev, self->cli, fnum, size);
1603 0 : if (!py_tevent_req_wait_exc(self, req)) {
1604 0 : return NULL;
1605 : }
1606 0 : status = cli_ftruncate_recv(req);
1607 0 : TALLOC_FREE(req);
1608 :
1609 0 : if (!NT_STATUS_IS_OK(status)) {
1610 0 : PyErr_SetNTSTATUS(status);
1611 0 : return NULL;
1612 : }
1613 0 : Py_RETURN_NONE;
1614 : }
1615 :
1616 1144 : static PyObject *py_cli_delete_on_close(struct py_cli_state *self,
1617 : PyObject *args,
1618 : PyObject *kwds)
1619 : {
1620 0 : unsigned fnum, flag;
1621 0 : struct tevent_req *req;
1622 0 : NTSTATUS status;
1623 :
1624 0 : static const char *kwlist[] = {
1625 : "fnum", "flag", NULL };
1626 :
1627 1144 : if (!ParseTupleAndKeywords(
1628 : args, kwds, "II", kwlist, &fnum, &flag)) {
1629 0 : return NULL;
1630 : }
1631 :
1632 1144 : req = cli_nt_delete_on_close_send(NULL, self->ev, self->cli, fnum,
1633 : flag);
1634 1144 : if (!py_tevent_req_wait_exc(self, req)) {
1635 0 : return NULL;
1636 : }
1637 1144 : status = cli_nt_delete_on_close_recv(req);
1638 1144 : TALLOC_FREE(req);
1639 :
1640 1144 : if (!NT_STATUS_IS_OK(status)) {
1641 0 : PyErr_SetNTSTATUS(status);
1642 0 : return NULL;
1643 : }
1644 1144 : Py_RETURN_NONE;
1645 : }
1646 :
1647 : struct py_cli_notify_state {
1648 : PyObject_HEAD
1649 : struct py_cli_state *py_cli_state;
1650 : struct tevent_req *req;
1651 : };
1652 :
1653 42 : static void py_cli_notify_state_dealloc(struct py_cli_notify_state *self)
1654 : {
1655 42 : TALLOC_FREE(self->req);
1656 42 : Py_CLEAR(self->py_cli_state);
1657 42 : Py_TYPE(self)->tp_free(self);
1658 42 : }
1659 :
1660 : static PyTypeObject py_cli_notify_state_type;
1661 :
1662 42 : static PyObject *py_cli_notify(struct py_cli_state *self,
1663 : PyObject *args,
1664 : PyObject *kwds)
1665 : {
1666 0 : static const char *kwlist[] = {
1667 : "fnum",
1668 : "buffer_size",
1669 : "completion_filter",
1670 : "recursive",
1671 : NULL
1672 : };
1673 42 : unsigned fnum = 0;
1674 42 : unsigned buffer_size = 0;
1675 42 : unsigned completion_filter = 0;
1676 42 : PyObject *py_recursive = Py_False;
1677 42 : bool recursive = false;
1678 42 : struct tevent_req *req = NULL;
1679 42 : struct tevent_queue *send_queue = NULL;
1680 42 : struct tevent_req *flush_req = NULL;
1681 0 : bool ok;
1682 42 : struct py_cli_notify_state *py_notify_state = NULL;
1683 0 : struct timeval endtime;
1684 :
1685 42 : ok = ParseTupleAndKeywords(args,
1686 : kwds,
1687 : "IIIO",
1688 : kwlist,
1689 : &fnum,
1690 : &buffer_size,
1691 : &completion_filter,
1692 : &py_recursive);
1693 42 : if (!ok) {
1694 0 : return NULL;
1695 : }
1696 :
1697 42 : recursive = PyObject_IsTrue(py_recursive);
1698 :
1699 42 : req = cli_notify_send(NULL,
1700 : self->ev,
1701 : self->cli,
1702 : fnum,
1703 : buffer_size,
1704 : completion_filter,
1705 : recursive);
1706 42 : if (req == NULL) {
1707 0 : PyErr_NoMemory();
1708 0 : return NULL;
1709 : }
1710 :
1711 : /*
1712 : * Just wait for the request being submitted to
1713 : * the kernel/socket/wire.
1714 : */
1715 42 : send_queue = smbXcli_conn_send_queue(self->cli->conn);
1716 42 : flush_req = tevent_queue_wait_send(req,
1717 : self->ev,
1718 : send_queue);
1719 42 : endtime = timeval_current_ofs_msec(self->cli->timeout);
1720 42 : ok = tevent_req_set_endtime(flush_req,
1721 : self->ev,
1722 : endtime);
1723 42 : if (!ok) {
1724 0 : TALLOC_FREE(req);
1725 0 : PyErr_NoMemory();
1726 0 : return NULL;
1727 : }
1728 42 : ok = py_tevent_req_wait_exc(self, flush_req);
1729 42 : if (!ok) {
1730 0 : TALLOC_FREE(req);
1731 0 : return NULL;
1732 : }
1733 42 : TALLOC_FREE(flush_req);
1734 :
1735 0 : py_notify_state = (struct py_cli_notify_state *)
1736 42 : py_cli_notify_state_type.tp_alloc(&py_cli_notify_state_type, 0);
1737 42 : if (py_notify_state == NULL) {
1738 0 : TALLOC_FREE(req);
1739 0 : PyErr_NoMemory();
1740 0 : return NULL;
1741 : }
1742 21 : Py_INCREF(self);
1743 42 : py_notify_state->py_cli_state = self;
1744 42 : py_notify_state->req = req;
1745 :
1746 42 : return (PyObject *)py_notify_state;
1747 : }
1748 :
1749 98 : static PyObject *py_cli_notify_get_changes(struct py_cli_notify_state *self,
1750 : PyObject *args,
1751 : PyObject *kwds)
1752 : {
1753 98 : struct py_cli_state *py_cli_state = self->py_cli_state;
1754 98 : struct tevent_req *req = self->req;
1755 0 : uint32_t i;
1756 98 : uint32_t num_changes = 0;
1757 98 : struct notify_change *changes = NULL;
1758 98 : PyObject *result = NULL;
1759 0 : NTSTATUS status;
1760 0 : bool ok;
1761 0 : static const char *kwlist[] = {
1762 : "wait",
1763 : NULL
1764 : };
1765 98 : PyObject *py_wait = Py_False;
1766 98 : bool wait = false;
1767 0 : bool pending;
1768 :
1769 98 : ok = ParseTupleAndKeywords(args,
1770 : kwds,
1771 : "O",
1772 : kwlist,
1773 : &py_wait);
1774 98 : if (!ok) {
1775 0 : return NULL;
1776 : }
1777 :
1778 98 : wait = PyObject_IsTrue(py_wait);
1779 :
1780 98 : if (req == NULL) {
1781 0 : PyErr_SetString(PyExc_RuntimeError,
1782 : "TODO req == NULL "
1783 : "- missing change notify request?");
1784 0 : return NULL;
1785 : }
1786 :
1787 98 : pending = tevent_req_is_in_progress(req);
1788 98 : if (pending && !wait) {
1789 56 : Py_RETURN_NONE;
1790 : }
1791 :
1792 42 : if (pending) {
1793 0 : struct timeval endtime;
1794 :
1795 30 : endtime = timeval_current_ofs_msec(py_cli_state->cli->timeout);
1796 30 : ok = tevent_req_set_endtime(req,
1797 : py_cli_state->ev,
1798 : endtime);
1799 30 : if (!ok) {
1800 0 : TALLOC_FREE(req);
1801 0 : PyErr_NoMemory();
1802 0 : return NULL;
1803 : }
1804 : }
1805 :
1806 42 : ok = py_tevent_req_wait_exc(py_cli_state, req);
1807 42 : self->req = NULL;
1808 42 : Py_CLEAR(self->py_cli_state);
1809 42 : if (!ok) {
1810 0 : return NULL;
1811 : }
1812 :
1813 42 : status = cli_notify_recv(req, req, &num_changes, &changes);
1814 42 : if (!NT_STATUS_IS_OK(status)) {
1815 12 : TALLOC_FREE(req);
1816 12 : PyErr_SetNTSTATUS(status);
1817 12 : return NULL;
1818 : }
1819 :
1820 30 : result = Py_BuildValue("[]");
1821 30 : if (result == NULL) {
1822 0 : TALLOC_FREE(req);
1823 0 : return NULL;
1824 : }
1825 :
1826 60 : for (i = 0; i < num_changes; i++) {
1827 30 : PyObject *change = NULL;
1828 0 : int ret;
1829 :
1830 30 : change = Py_BuildValue("{s:s,s:I}",
1831 30 : "name", changes[i].name,
1832 30 : "action", changes[i].action);
1833 30 : if (change == NULL) {
1834 0 : Py_XDECREF(result);
1835 0 : TALLOC_FREE(req);
1836 0 : return NULL;
1837 : }
1838 :
1839 30 : ret = PyList_Append(result, change);
1840 15 : Py_DECREF(change);
1841 30 : if (ret == -1) {
1842 0 : Py_XDECREF(result);
1843 0 : TALLOC_FREE(req);
1844 0 : return NULL;
1845 : }
1846 : }
1847 :
1848 30 : TALLOC_FREE(req);
1849 30 : return result;
1850 : }
1851 :
1852 : static PyMethodDef py_cli_notify_state_methods[] = {
1853 : {
1854 : .ml_name = "get_changes",
1855 : .ml_meth = (PyCFunction)py_cli_notify_get_changes,
1856 : .ml_flags = METH_VARARGS|METH_KEYWORDS,
1857 : .ml_doc = "Wait for change notifications: \n"
1858 : "N.get_changes(wait=BOOLEAN) -> "
1859 : "change notifications as a dictionary\n"
1860 : "\t\tList contents of a directory. The keys are, \n"
1861 : "\t\t\tname: name of changed object\n"
1862 : "\t\t\taction: type of the change\n"
1863 : "None is returned if there's no response yet and "
1864 : "wait=False is passed"
1865 : },
1866 : {
1867 : .ml_name = NULL
1868 : }
1869 : };
1870 :
1871 : static PyTypeObject py_cli_notify_state_type = {
1872 : PyVarObject_HEAD_INIT(NULL, 0)
1873 : .tp_name = "libsmb_samba_cwrapper.Notify",
1874 : .tp_basicsize = sizeof(struct py_cli_notify_state),
1875 : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1876 : .tp_doc = "notify request",
1877 : .tp_dealloc = (destructor)py_cli_notify_state_dealloc,
1878 : .tp_methods = py_cli_notify_state_methods,
1879 : };
1880 :
1881 : /*
1882 : * Helper to add posix directory listing entries to an overall Python list
1883 : */
1884 1449 : static NTSTATUS list_posix_helper(struct file_info *finfo,
1885 : const char *mask, void *state)
1886 : {
1887 1449 : PyObject *result = (PyObject *)state;
1888 1449 : PyObject *file = NULL;
1889 0 : int ret;
1890 :
1891 : /*
1892 : * Build a dictionary representing the file info.
1893 : */
1894 1449 : file = Py_BuildValue("{s:s,s:I,"
1895 : "s:K,s:K,"
1896 : "s:l,s:l,s:l,s:l,"
1897 : "s:i,s:K,s:i,s:i,s:I,"
1898 : "s:s,s:s}",
1899 : "name", finfo->name,
1900 : "attrib", finfo->attr,
1901 :
1902 : "size", finfo->size,
1903 : "allocaction_size", finfo->allocated_size,
1904 :
1905 : "btime",
1906 : convert_timespec_to_time_t(finfo->btime_ts),
1907 : "atime",
1908 : convert_timespec_to_time_t(finfo->atime_ts),
1909 : "mtime",
1910 : convert_timespec_to_time_t(finfo->mtime_ts),
1911 : "ctime",
1912 : convert_timespec_to_time_t(finfo->ctime_ts),
1913 :
1914 : "perms", finfo->st_ex_mode,
1915 : "ino", finfo->ino,
1916 : "dev", finfo->st_ex_dev,
1917 : "nlink", finfo->st_ex_nlink,
1918 : "reparse_tag", finfo->reparse_tag,
1919 :
1920 : "owner_sid",
1921 1449 : dom_sid_string(finfo, &finfo->owner_sid),
1922 : "group_sid",
1923 1449 : dom_sid_string(finfo, &finfo->group_sid));
1924 1449 : if (file == NULL) {
1925 0 : return NT_STATUS_NO_MEMORY;
1926 : }
1927 :
1928 1449 : ret = PyList_Append(result, file);
1929 1449 : Py_CLEAR(file);
1930 1449 : if (ret == -1) {
1931 0 : return NT_STATUS_INTERNAL_ERROR;
1932 : }
1933 :
1934 1449 : return NT_STATUS_OK;
1935 : }
1936 :
1937 : /*
1938 : * Helper to add directory listing entries to an overall Python list
1939 : */
1940 11418 : static NTSTATUS list_helper(struct file_info *finfo,
1941 : const char *mask, void *state)
1942 : {
1943 11418 : PyObject *result = (PyObject *)state;
1944 11418 : PyObject *file = NULL;
1945 11418 : PyObject *size = NULL;
1946 0 : int ret;
1947 :
1948 : /* suppress '.' and '..' in the results we return */
1949 11418 : if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
1950 6888 : return NT_STATUS_OK;
1951 : }
1952 4530 : size = PyLong_FromUnsignedLongLong(finfo->size);
1953 : /*
1954 : * Build a dictionary representing the file info.
1955 : * Note: Windows does not always return short_name (so it may be None)
1956 : */
1957 4530 : file = Py_BuildValue("{s:s,s:i,s:s,s:O,s:l}",
1958 : "name", finfo->name,
1959 4530 : "attrib", (int)finfo->attr,
1960 : "short_name", finfo->short_name,
1961 : "size", size,
1962 : "mtime",
1963 : convert_timespec_to_time_t(finfo->mtime_ts));
1964 :
1965 4530 : Py_CLEAR(size);
1966 :
1967 4530 : if (file == NULL) {
1968 0 : return NT_STATUS_NO_MEMORY;
1969 : }
1970 :
1971 4530 : if (finfo->attr & FILE_ATTRIBUTE_REPARSE_POINT) {
1972 0 : unsigned long tag = finfo->reparse_tag;
1973 :
1974 0 : ret = PyDict_SetItemString(
1975 : file,
1976 : "reparse_tag",
1977 : PyLong_FromUnsignedLong(tag));
1978 0 : if (ret == -1) {
1979 0 : return NT_STATUS_INTERNAL_ERROR;
1980 : }
1981 : }
1982 :
1983 4530 : ret = PyList_Append(result, file);
1984 4530 : Py_CLEAR(file);
1985 4530 : if (ret == -1) {
1986 0 : return NT_STATUS_INTERNAL_ERROR;
1987 : }
1988 :
1989 4530 : return NT_STATUS_OK;
1990 : }
1991 :
1992 : struct do_listing_state {
1993 : const char *mask;
1994 : NTSTATUS (*callback_fn)(
1995 : struct file_info *finfo,
1996 : const char *mask,
1997 : void *private_data);
1998 : void *private_data;
1999 : NTSTATUS status;
2000 : };
2001 :
2002 19795 : static void do_listing_cb(struct tevent_req *subreq)
2003 : {
2004 19795 : struct do_listing_state *state = tevent_req_callback_data_void(subreq);
2005 19795 : struct file_info *finfo = NULL;
2006 :
2007 19795 : state->status = cli_list_recv(subreq, NULL, &finfo);
2008 19795 : if (!NT_STATUS_IS_OK(state->status)) {
2009 6928 : return;
2010 : }
2011 12867 : state->callback_fn(finfo, state->mask, state->private_data);
2012 12867 : TALLOC_FREE(finfo);
2013 : }
2014 :
2015 3465 : static NTSTATUS do_listing(struct py_cli_state *self,
2016 : const char *base_dir, const char *user_mask,
2017 : uint16_t attribute,
2018 : unsigned int info_level,
2019 : NTSTATUS (*callback_fn)(struct file_info *,
2020 : const char *, void *),
2021 : void *priv)
2022 : {
2023 3465 : char *mask = NULL;
2024 3465 : struct do_listing_state state = {
2025 : .mask = mask,
2026 : .callback_fn = callback_fn,
2027 : .private_data = priv,
2028 : };
2029 3465 : struct tevent_req *req = NULL;
2030 0 : NTSTATUS status;
2031 :
2032 3465 : if (user_mask == NULL) {
2033 3447 : mask = talloc_asprintf(NULL, "%s\\*", base_dir);
2034 : } else {
2035 18 : mask = talloc_asprintf(NULL, "%s\\%s", base_dir, user_mask);
2036 : }
2037 :
2038 3465 : if (mask == NULL) {
2039 0 : return NT_STATUS_NO_MEMORY;
2040 : }
2041 3465 : dos_format(mask);
2042 :
2043 3465 : req = cli_list_send(NULL, self->ev, self->cli, mask, attribute,
2044 : info_level);
2045 3465 : if (req == NULL) {
2046 0 : status = NT_STATUS_NO_MEMORY;
2047 0 : goto done;
2048 : }
2049 3465 : tevent_req_set_callback(req, do_listing_cb, &state);
2050 :
2051 3465 : if (!py_tevent_req_wait_exc(self, req)) {
2052 0 : return NT_STATUS_INTERNAL_ERROR;
2053 : }
2054 3465 : TALLOC_FREE(req);
2055 :
2056 3465 : status = state.status;
2057 3465 : if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_FILES)) {
2058 3465 : status = NT_STATUS_OK;
2059 : }
2060 :
2061 3465 : done:
2062 3465 : TALLOC_FREE(mask);
2063 3465 : return status;
2064 : }
2065 :
2066 3465 : static PyObject *py_cli_list(struct py_cli_state *self,
2067 : PyObject *args,
2068 : PyObject *kwds)
2069 : {
2070 0 : char *base_dir;
2071 3465 : char *user_mask = NULL;
2072 3465 : unsigned int attribute = LIST_ATTRIBUTE_MASK;
2073 3465 : unsigned int info_level = 0;
2074 0 : NTSTATUS status;
2075 3465 : enum protocol_types proto = smbXcli_conn_protocol(self->cli->conn);
2076 3465 : PyObject *result = NULL;
2077 3465 : const char *kwlist[] = { "directory", "mask", "attribs",
2078 : "info_level", NULL };
2079 3465 : NTSTATUS (*callback_fn)(struct file_info *, const char *, void *) =
2080 : &list_helper;
2081 :
2082 3465 : if (!ParseTupleAndKeywords(args, kwds, "z|sII:list", kwlist,
2083 : &base_dir, &user_mask, &attribute,
2084 : &info_level)) {
2085 0 : return NULL;
2086 : }
2087 :
2088 3465 : result = Py_BuildValue("[]");
2089 3465 : if (result == NULL) {
2090 0 : return NULL;
2091 : }
2092 :
2093 3465 : if (!info_level) {
2094 3459 : if (proto >= PROTOCOL_SMB2_02) {
2095 3459 : info_level = SMB2_FIND_ID_BOTH_DIRECTORY_INFO;
2096 : } else {
2097 0 : info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
2098 : }
2099 : }
2100 :
2101 3465 : if (info_level == SMB2_FIND_POSIX_INFORMATION) {
2102 6 : callback_fn = &list_posix_helper;
2103 : }
2104 3465 : status = do_listing(self, base_dir, user_mask, attribute,
2105 : info_level, callback_fn, result);
2106 :
2107 3465 : if (!NT_STATUS_IS_OK(status)) {
2108 0 : Py_XDECREF(result);
2109 0 : PyErr_SetNTSTATUS(status);
2110 0 : return NULL;
2111 : }
2112 :
2113 3465 : return result;
2114 : }
2115 :
2116 812 : static PyObject *py_smb_unlink(struct py_cli_state *self, PyObject *args)
2117 : {
2118 0 : NTSTATUS status;
2119 812 : const char *filename = NULL;
2120 812 : struct tevent_req *req = NULL;
2121 812 : const uint32_t attrs = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2122 :
2123 812 : if (!PyArg_ParseTuple(args, "s:unlink", &filename)) {
2124 0 : return NULL;
2125 : }
2126 :
2127 812 : req = cli_unlink_send(NULL, self->ev, self->cli, filename, attrs);
2128 812 : if (!py_tevent_req_wait_exc(self, req)) {
2129 0 : return NULL;
2130 : }
2131 812 : status = cli_unlink_recv(req);
2132 812 : TALLOC_FREE(req);
2133 812 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
2134 :
2135 785 : Py_RETURN_NONE;
2136 : }
2137 :
2138 1571 : static PyObject *py_smb_rmdir(struct py_cli_state *self, PyObject *args)
2139 : {
2140 0 : NTSTATUS status;
2141 1571 : struct tevent_req *req = NULL;
2142 1571 : const char *dirname = NULL;
2143 :
2144 1571 : if (!PyArg_ParseTuple(args, "s:rmdir", &dirname)) {
2145 0 : return NULL;
2146 : }
2147 :
2148 1571 : req = cli_rmdir_send(NULL, self->ev, self->cli, dirname);
2149 1571 : if (!py_tevent_req_wait_exc(self, req)) {
2150 0 : return NULL;
2151 : }
2152 1571 : status = cli_rmdir_recv(req);
2153 1571 : TALLOC_FREE(req);
2154 1571 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
2155 :
2156 1571 : Py_RETURN_NONE;
2157 : }
2158 :
2159 : /*
2160 : * Create a directory
2161 : */
2162 1470 : static PyObject *py_smb_mkdir(struct py_cli_state *self, PyObject *args)
2163 : {
2164 0 : NTSTATUS status;
2165 1470 : const char *dirname = NULL;
2166 1470 : struct tevent_req *req = NULL;
2167 :
2168 1470 : if (!PyArg_ParseTuple(args, "s:mkdir", &dirname)) {
2169 0 : return NULL;
2170 : }
2171 :
2172 1470 : req = cli_mkdir_send(NULL, self->ev, self->cli, dirname);
2173 1470 : if (!py_tevent_req_wait_exc(self, req)) {
2174 0 : return NULL;
2175 : }
2176 1470 : status = cli_mkdir_recv(req);
2177 1470 : TALLOC_FREE(req);
2178 1470 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
2179 :
2180 1386 : Py_RETURN_NONE;
2181 : }
2182 :
2183 : /*
2184 : * Does a whoami call
2185 : */
2186 12 : static PyObject *py_smb_posix_whoami(struct py_cli_state *self,
2187 : PyObject *Py_UNUSED(ignored))
2188 : {
2189 12 : TALLOC_CTX *frame = talloc_stackframe();
2190 0 : NTSTATUS status;
2191 12 : struct tevent_req *req = NULL;
2192 0 : uint64_t uid;
2193 0 : uint64_t gid;
2194 0 : uint32_t num_gids;
2195 12 : uint64_t *gids = NULL;
2196 0 : uint32_t num_sids;
2197 12 : struct dom_sid *sids = NULL;
2198 0 : bool guest;
2199 12 : PyObject *py_gids = NULL;
2200 12 : PyObject *py_sids = NULL;
2201 12 : PyObject *py_guest = NULL;
2202 12 : PyObject *py_ret = NULL;
2203 0 : Py_ssize_t i;
2204 :
2205 12 : req = cli_posix_whoami_send(frame, self->ev, self->cli);
2206 12 : if (!py_tevent_req_wait_exc(self, req)) {
2207 0 : goto fail;
2208 : }
2209 12 : status = cli_posix_whoami_recv(req,
2210 : frame,
2211 : &uid,
2212 : &gid,
2213 : &num_gids,
2214 : &gids,
2215 : &num_sids,
2216 : &sids,
2217 : &guest);
2218 12 : if (!NT_STATUS_IS_OK(status)) {
2219 0 : PyErr_SetNTSTATUS(status);
2220 0 : goto fail;
2221 : }
2222 0 : if (num_gids > PY_SSIZE_T_MAX) {
2223 : PyErr_SetString(PyExc_OverflowError, "posix_whoami: Too many GIDs");
2224 : goto fail;
2225 : }
2226 0 : if (num_sids > PY_SSIZE_T_MAX) {
2227 : PyErr_SetString(PyExc_OverflowError, "posix_whoami: Too many SIDs");
2228 : goto fail;
2229 : }
2230 :
2231 12 : py_gids = PyList_New(num_gids);
2232 12 : if (!py_gids) {
2233 0 : goto fail;
2234 : }
2235 84 : for (i = 0; i < num_gids; ++i) {
2236 0 : int ret;
2237 72 : PyObject *py_item = PyLong_FromUnsignedLongLong(gids[i]);
2238 72 : if (!py_item) {
2239 0 : goto fail2;
2240 : }
2241 :
2242 72 : ret = PyList_SetItem(py_gids, i, py_item);
2243 72 : if (ret) {
2244 0 : goto fail2;
2245 : }
2246 : }
2247 12 : py_sids = PyList_New(num_sids);
2248 12 : if (!py_sids) {
2249 0 : goto fail2;
2250 : }
2251 140 : for (i = 0; i < num_sids; ++i) {
2252 0 : int ret;
2253 0 : struct dom_sid *sid;
2254 0 : PyObject *py_item;
2255 :
2256 128 : sid = dom_sid_dup(frame, &sids[i]);
2257 128 : if (!sid) {
2258 0 : PyErr_NoMemory();
2259 0 : goto fail3;
2260 : }
2261 :
2262 128 : py_item = pytalloc_steal(dom_sid_Type, sid);
2263 128 : if (!py_item) {
2264 0 : PyErr_NoMemory();
2265 0 : goto fail3;
2266 : }
2267 :
2268 128 : ret = PyList_SetItem(py_sids, i, py_item);
2269 128 : if (ret) {
2270 0 : goto fail3;
2271 : }
2272 : }
2273 :
2274 12 : py_guest = guest ? Py_True : Py_False;
2275 :
2276 12 : py_ret = Py_BuildValue("KKNNO",
2277 : uid,
2278 : gid,
2279 : py_gids,
2280 : py_sids,
2281 : py_guest);
2282 12 : if (!py_ret) {
2283 0 : goto fail3;
2284 : }
2285 :
2286 12 : TALLOC_FREE(frame);
2287 12 : return py_ret;
2288 :
2289 0 : fail3:
2290 0 : Py_CLEAR(py_sids);
2291 :
2292 0 : fail2:
2293 0 : Py_CLEAR(py_gids);
2294 :
2295 0 : fail:
2296 0 : TALLOC_FREE(frame);
2297 0 : return NULL;
2298 : }
2299 :
2300 : /*
2301 : * Checks existence of a directory
2302 : */
2303 5486 : static bool check_dir_path(struct py_cli_state *self, const char *path)
2304 : {
2305 0 : NTSTATUS status;
2306 5486 : struct tevent_req *req = NULL;
2307 :
2308 5486 : req = cli_chkpath_send(NULL, self->ev, self->cli, path);
2309 5486 : if (!py_tevent_req_wait_exc(self, req)) {
2310 0 : return false;
2311 : }
2312 5486 : status = cli_chkpath_recv(req);
2313 5486 : TALLOC_FREE(req);
2314 :
2315 5486 : return NT_STATUS_IS_OK(status);
2316 : }
2317 :
2318 5486 : static PyObject *py_smb_chkpath(struct py_cli_state *self, PyObject *args)
2319 : {
2320 5486 : const char *path = NULL;
2321 0 : bool dir_exists;
2322 :
2323 5486 : if (!PyArg_ParseTuple(args, "s:chkpath", &path)) {
2324 0 : return NULL;
2325 : }
2326 :
2327 5486 : dir_exists = check_dir_path(self, path);
2328 5486 : return PyBool_FromLong(dir_exists);
2329 : }
2330 :
2331 32 : static PyObject *py_smb_have_posix(struct py_cli_state *self,
2332 : PyObject *Py_UNUSED(ignored))
2333 : {
2334 32 : bool posix = smbXcli_conn_have_posix(self->cli->conn);
2335 :
2336 32 : if (posix) {
2337 30 : Py_RETURN_TRUE;
2338 : }
2339 2 : Py_RETURN_FALSE;
2340 : }
2341 :
2342 10 : static PyObject *py_smb_protocol(struct py_cli_state *self,
2343 : PyObject *Py_UNUSED(ignored))
2344 : {
2345 10 : enum protocol_types proto = smbXcli_conn_protocol(self->cli->conn);
2346 10 : PyObject *result = PyLong_FromLong(proto);
2347 10 : return result;
2348 : }
2349 :
2350 354 : static PyObject *py_smb_get_sd(struct py_cli_state *self, PyObject *args)
2351 : {
2352 0 : int fnum;
2353 0 : unsigned sinfo;
2354 354 : struct tevent_req *req = NULL;
2355 354 : struct security_descriptor *sd = NULL;
2356 0 : NTSTATUS status;
2357 :
2358 354 : if (!PyArg_ParseTuple(args, "iI:get_acl", &fnum, &sinfo)) {
2359 0 : return NULL;
2360 : }
2361 :
2362 354 : req = cli_query_security_descriptor_send(
2363 : NULL, self->ev, self->cli, fnum, sinfo);
2364 354 : if (!py_tevent_req_wait_exc(self, req)) {
2365 0 : return NULL;
2366 : }
2367 354 : status = cli_query_security_descriptor_recv(req, NULL, &sd);
2368 354 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
2369 :
2370 354 : return py_return_ndr_struct(
2371 : "samba.dcerpc.security", "descriptor", sd, sd);
2372 : }
2373 :
2374 454 : static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args)
2375 : {
2376 454 : PyObject *py_sd = NULL;
2377 454 : struct tevent_req *req = NULL;
2378 454 : struct security_descriptor *sd = NULL;
2379 0 : uint16_t fnum;
2380 0 : unsigned int sinfo;
2381 0 : NTSTATUS status;
2382 :
2383 454 : if (!PyArg_ParseTuple(args, "iOI:set_sd", &fnum, &py_sd, &sinfo)) {
2384 0 : return NULL;
2385 : }
2386 :
2387 454 : sd = pytalloc_get_type(py_sd, struct security_descriptor);
2388 454 : if (!sd) {
2389 0 : PyErr_Format(PyExc_TypeError,
2390 : "Expected dcerpc.security.descriptor as argument, got %s",
2391 : pytalloc_get_name(py_sd));
2392 0 : return NULL;
2393 : }
2394 :
2395 454 : req = cli_set_security_descriptor_send(
2396 : NULL, self->ev, self->cli, fnum, sinfo, sd);
2397 454 : if (!py_tevent_req_wait_exc(self, req)) {
2398 0 : return NULL;
2399 : }
2400 :
2401 454 : status = cli_set_security_descriptor_recv(req);
2402 454 : PyErr_NTSTATUS_NOT_OK_RAISE(status);
2403 :
2404 454 : Py_RETURN_NONE;
2405 : }
2406 :
2407 12 : static PyObject *py_smb_smb1_posix(
2408 : struct py_cli_state *self, PyObject *Py_UNUSED(ignored))
2409 : {
2410 0 : NTSTATUS status;
2411 12 : struct tevent_req *req = NULL;
2412 0 : uint16_t major, minor;
2413 0 : uint32_t caplow, caphigh;
2414 12 : PyObject *result = NULL;
2415 :
2416 12 : req = cli_unix_extensions_version_send(NULL, self->ev, self->cli);
2417 12 : if (!py_tevent_req_wait_exc(self, req)) {
2418 0 : return NULL;
2419 : }
2420 12 : status = cli_unix_extensions_version_recv(
2421 : req, &major, &minor, &caplow, &caphigh);
2422 12 : TALLOC_FREE(req);
2423 12 : if (!NT_STATUS_IS_OK(status)) {
2424 0 : PyErr_SetNTSTATUS(status);
2425 0 : return NULL;
2426 : }
2427 :
2428 12 : req = cli_set_unix_extensions_capabilities_send(
2429 : NULL, self->ev, self->cli, major, minor, caplow, caphigh);
2430 12 : if (!py_tevent_req_wait_exc(self, req)) {
2431 0 : return NULL;
2432 : }
2433 12 : status = cli_set_unix_extensions_capabilities_recv(req);
2434 12 : TALLOC_FREE(req);
2435 12 : if (!NT_STATUS_IS_OK(status)) {
2436 0 : PyErr_SetNTSTATUS(status);
2437 0 : return NULL;
2438 : }
2439 :
2440 12 : result = Py_BuildValue(
2441 : "[IIII]",
2442 : (unsigned)minor,
2443 : (unsigned)major,
2444 : (unsigned)caplow,
2445 : (unsigned)caphigh);
2446 12 : return result;
2447 : }
2448 :
2449 0 : static PyObject *py_smb_smb1_readlink(
2450 : struct py_cli_state *self, PyObject *args)
2451 : {
2452 0 : NTSTATUS status;
2453 0 : const char *filename = NULL;
2454 0 : struct tevent_req *req = NULL;
2455 0 : char *target = NULL;
2456 0 : PyObject *result = NULL;
2457 :
2458 0 : if (!PyArg_ParseTuple(args, "s:smb1_readlink", &filename)) {
2459 0 : return NULL;
2460 : }
2461 :
2462 0 : req = cli_posix_readlink_send(NULL, self->ev, self->cli, filename);
2463 0 : if (!py_tevent_req_wait_exc(self, req)) {
2464 0 : return NULL;
2465 : }
2466 0 : status = cli_posix_readlink_recv(req, NULL, &target);
2467 0 : TALLOC_FREE(req);
2468 0 : if (!NT_STATUS_IS_OK(status)) {
2469 0 : PyErr_SetNTSTATUS(status);
2470 0 : return NULL;
2471 : }
2472 :
2473 0 : result = PyBytes_FromString(target);
2474 0 : TALLOC_FREE(target);
2475 0 : return result;
2476 : }
2477 :
2478 10 : static PyObject *py_smb_smb1_symlink(
2479 : struct py_cli_state *self, PyObject *args)
2480 : {
2481 0 : NTSTATUS status;
2482 10 : const char *target = NULL, *newname = NULL;
2483 10 : struct tevent_req *req = NULL;
2484 :
2485 10 : if (!PyArg_ParseTuple(args, "ss:smb1_symlink", &target, &newname)) {
2486 0 : return NULL;
2487 : }
2488 :
2489 10 : req = cli_posix_symlink_send(
2490 : NULL, self->ev, self->cli, target, newname);
2491 10 : if (!py_tevent_req_wait_exc(self, req)) {
2492 0 : return NULL;
2493 : }
2494 10 : status = cli_posix_symlink_recv(req);
2495 10 : TALLOC_FREE(req);
2496 10 : if (!NT_STATUS_IS_OK(status)) {
2497 0 : PyErr_SetNTSTATUS(status);
2498 0 : return NULL;
2499 : }
2500 :
2501 10 : Py_RETURN_NONE;
2502 : }
2503 :
2504 2 : static PyObject *py_smb_smb1_stat(
2505 : struct py_cli_state *self, PyObject *args)
2506 : {
2507 0 : NTSTATUS status;
2508 2 : const char *fname = NULL;
2509 2 : struct tevent_req *req = NULL;
2510 2 : struct stat_ex sbuf = { .st_ex_nlink = 0, };
2511 :
2512 2 : if (!PyArg_ParseTuple(args, "s:smb1_stat", &fname)) {
2513 0 : return NULL;
2514 : }
2515 :
2516 2 : req = cli_posix_stat_send(NULL, self->ev, self->cli, fname);
2517 2 : if (!py_tevent_req_wait_exc(self, req)) {
2518 0 : return NULL;
2519 : }
2520 2 : status = cli_posix_stat_recv(req, &sbuf);
2521 2 : TALLOC_FREE(req);
2522 2 : if (!NT_STATUS_IS_OK(status)) {
2523 0 : PyErr_SetNTSTATUS(status);
2524 0 : return NULL;
2525 : }
2526 :
2527 2 : return Py_BuildValue(
2528 : "{sLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsLsL}",
2529 : "dev",
2530 2 : (unsigned long long)sbuf.st_ex_dev,
2531 : "ino",
2532 2 : (unsigned long long)sbuf.st_ex_ino,
2533 : "mode",
2534 2 : (unsigned long long)sbuf.st_ex_mode,
2535 : "nlink",
2536 2 : (unsigned long long)sbuf.st_ex_nlink,
2537 : "uid",
2538 2 : (unsigned long long)sbuf.st_ex_uid,
2539 : "gid",
2540 2 : (unsigned long long)sbuf.st_ex_gid,
2541 : "rdev",
2542 2 : (unsigned long long)sbuf.st_ex_size,
2543 : "atime_sec",
2544 2 : (unsigned long long)sbuf.st_ex_atime.tv_sec,
2545 : "atime_nsec",
2546 2 : (unsigned long long)sbuf.st_ex_atime.tv_nsec,
2547 : "mtime_sec",
2548 2 : (unsigned long long)sbuf.st_ex_mtime.tv_sec,
2549 : "mtime_nsec",
2550 2 : (unsigned long long)sbuf.st_ex_mtime.tv_nsec,
2551 : "ctime_sec",
2552 2 : (unsigned long long)sbuf.st_ex_ctime.tv_sec,
2553 : "ctime_nsec",
2554 2 : (unsigned long long)sbuf.st_ex_ctime.tv_nsec,
2555 : "btime_sec",
2556 2 : (unsigned long long)sbuf.st_ex_btime.tv_sec,
2557 : "btime_nsec",
2558 2 : (unsigned long long)sbuf.st_ex_btime.tv_nsec,
2559 : "cached_dos_attributes",
2560 2 : (unsigned long long)sbuf.cached_dos_attributes,
2561 : "blksize",
2562 2 : (unsigned long long)sbuf.st_ex_blksize,
2563 : "blocks",
2564 2 : (unsigned long long)sbuf.st_ex_blocks,
2565 : "flags",
2566 2 : (unsigned long long)sbuf.st_ex_flags,
2567 : "iflags",
2568 2 : (unsigned long long)sbuf.st_ex_iflags);
2569 : }
2570 :
2571 2 : static PyObject *py_cli_mknod(
2572 : struct py_cli_state *self, PyObject *args, PyObject *kwds)
2573 : {
2574 2 : char *fname = NULL;
2575 2 : int mode = 0, major = 0, minor = 0, dev = 0;
2576 2 : struct tevent_req *req = NULL;
2577 0 : static const char *kwlist[] = {
2578 : "fname", "mode", "major", "minor", NULL,
2579 : };
2580 0 : NTSTATUS status;
2581 0 : bool ok;
2582 :
2583 2 : ok = ParseTupleAndKeywords(
2584 : args,
2585 : kwds,
2586 : "sI|II:mknod",
2587 : kwlist,
2588 : &fname,
2589 : &mode,
2590 : &major,
2591 : &minor);
2592 2 : if (!ok) {
2593 0 : return NULL;
2594 : }
2595 :
2596 : #if defined(HAVE_MAKEDEV)
2597 2 : dev = makedev(major, minor);
2598 : #endif
2599 :
2600 2 : req = cli_mknod_send(
2601 : NULL, self->ev, self->cli, fname, mode, dev);
2602 2 : if (!py_tevent_req_wait_exc(self, req)) {
2603 0 : return NULL;
2604 : }
2605 2 : status = cli_mknod_recv(req);
2606 2 : TALLOC_FREE(req);
2607 2 : if (!NT_STATUS_IS_OK(status)) {
2608 0 : PyErr_SetNTSTATUS(status);
2609 0 : return NULL;
2610 : }
2611 2 : Py_RETURN_NONE;
2612 : }
2613 :
2614 0 : static PyObject *py_cli_fsctl(
2615 : struct py_cli_state *self, PyObject *args, PyObject *kwds)
2616 : {
2617 0 : int fnum, ctl_code;
2618 0 : int max_out = 0;
2619 0 : char *buf = NULL;
2620 0 : Py_ssize_t buflen;
2621 0 : DATA_BLOB in = { .data = NULL, };
2622 0 : DATA_BLOB out = { .data = NULL, };
2623 0 : struct tevent_req *req = NULL;
2624 0 : PyObject *result = NULL;
2625 0 : static const char *kwlist[] = {
2626 : "fnum", "ctl_code", "in", "max_out", NULL,
2627 : };
2628 0 : NTSTATUS status;
2629 0 : bool ok;
2630 :
2631 0 : ok = ParseTupleAndKeywords(
2632 : args,
2633 : kwds,
2634 : "ii" PYARG_BYTES_LEN "i",
2635 : kwlist,
2636 : &fnum,
2637 : &ctl_code,
2638 : &buf,
2639 : &buflen,
2640 : &max_out);
2641 0 : if (!ok) {
2642 0 : return NULL;
2643 : }
2644 :
2645 0 : in = (DATA_BLOB) { .data = (uint8_t *)buf, .length = buflen, };
2646 :
2647 0 : req = cli_fsctl_send(
2648 : NULL, self->ev, self->cli, fnum, ctl_code, &in, max_out);
2649 :
2650 0 : if (!py_tevent_req_wait_exc(self, req)) {
2651 0 : return NULL;
2652 : }
2653 :
2654 0 : status = cli_fsctl_recv(req, NULL, &out);
2655 0 : if (!NT_STATUS_IS_OK(status)) {
2656 0 : PyErr_SetNTSTATUS(status);
2657 0 : return NULL;
2658 : }
2659 :
2660 0 : result = PyBytes_FromStringAndSize((char *)out.data, out.length);
2661 0 : data_blob_free(&out);
2662 0 : return result;
2663 : }
2664 :
2665 : static PyMethodDef py_cli_state_methods[] = {
2666 : { "settimeout", (PyCFunction)py_cli_settimeout, METH_VARARGS,
2667 : "settimeout(new_timeout_msecs) => return old_timeout_msecs" },
2668 : { "echo", (PyCFunction)py_cli_echo, METH_NOARGS,
2669 : "Ping the server connection" },
2670 : { "create", PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_create),
2671 : METH_VARARGS|METH_KEYWORDS,
2672 : "Open a file" },
2673 : { "create_ex",
2674 : PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_create_ex),
2675 : METH_VARARGS|METH_KEYWORDS,
2676 : "Open a file, SMB2 version returning create contexts" },
2677 : { "close", (PyCFunction)py_cli_close, METH_VARARGS,
2678 : "Close a file handle" },
2679 : { "write", PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_write),
2680 : METH_VARARGS|METH_KEYWORDS,
2681 : "Write to a file handle" },
2682 : { "read", PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_read),
2683 : METH_VARARGS|METH_KEYWORDS,
2684 : "Read from a file handle" },
2685 : { "truncate", PY_DISCARD_FUNC_SIG(PyCFunction,
2686 : py_cli_ftruncate),
2687 : METH_VARARGS|METH_KEYWORDS,
2688 : "Truncate a file" },
2689 : { "delete_on_close", PY_DISCARD_FUNC_SIG(PyCFunction,
2690 : py_cli_delete_on_close),
2691 : METH_VARARGS|METH_KEYWORDS,
2692 : "Set/Reset the delete on close flag" },
2693 : { "notify", PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_notify),
2694 : METH_VARARGS|METH_KEYWORDS,
2695 : "Wait for change notifications: \n"
2696 : "notify(fnum, buffer_size, completion_filter...) -> "
2697 : "libsmb_samba_internal.Notify request handle\n" },
2698 : { "list", PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_list),
2699 : METH_VARARGS|METH_KEYWORDS,
2700 : "list(directory, mask='*', attribs=DEFAULT_ATTRS) -> "
2701 : "directory contents as a dictionary\n"
2702 : "\t\tDEFAULT_ATTRS: FILE_ATTRIBUTE_SYSTEM | "
2703 : "FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE\n\n"
2704 : "\t\tList contents of a directory. The keys are, \n"
2705 : "\t\t\tname: Long name of the directory item\n"
2706 : "\t\t\tshort_name: Short name of the directory item\n"
2707 : "\t\t\tsize: File size in bytes\n"
2708 : "\t\t\tattrib: Attributes\n"
2709 : "\t\t\tmtime: Modification time\n" },
2710 : { "get_oplock_break", (PyCFunction)py_cli_get_oplock_break,
2711 : METH_VARARGS, "Wait for an oplock break" },
2712 : { "unlink", (PyCFunction)py_smb_unlink,
2713 : METH_VARARGS,
2714 : "unlink(path) -> None\n\n \t\tDelete a file." },
2715 : { "mkdir", (PyCFunction)py_smb_mkdir, METH_VARARGS,
2716 : "mkdir(path) -> None\n\n \t\tCreate a directory." },
2717 : { "posix_whoami", (PyCFunction)py_smb_posix_whoami, METH_NOARGS,
2718 : "posix_whoami() -> (uid, gid, gids, sids, guest)" },
2719 : { "rmdir", (PyCFunction)py_smb_rmdir, METH_VARARGS,
2720 : "rmdir(path) -> None\n\n \t\tDelete a directory." },
2721 : { "rename",
2722 : PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_rename),
2723 : METH_VARARGS|METH_KEYWORDS,
2724 : "rename(src,dst) -> None\n\n \t\tRename a file." },
2725 : { "chkpath", (PyCFunction)py_smb_chkpath, METH_VARARGS,
2726 : "chkpath(dir_path) -> True or False\n\n"
2727 : "\t\tReturn true if directory exists, false otherwise." },
2728 : { "savefile", (PyCFunction)py_smb_savefile, METH_VARARGS,
2729 : "savefile(path, bytes) -> None\n\n"
2730 : "\t\tWrite bytes to file." },
2731 : { "loadfile", (PyCFunction)py_smb_loadfile, METH_VARARGS,
2732 : "loadfile(path) -> file contents as a bytes object"
2733 : "\n\n\t\tRead contents of a file." },
2734 : { "get_sd", (PyCFunction)py_smb_get_sd, METH_VARARGS,
2735 : "get_sd(fnum[, security_info=0]) -> security_descriptor object\n\n"
2736 : "\t\tGet security descriptor for opened file." },
2737 : { "set_sd", (PyCFunction)py_smb_set_sd, METH_VARARGS,
2738 : "set_sd(fnum, security_descriptor[, security_info=0]) -> None\n\n"
2739 : "\t\tSet security descriptor for opened file." },
2740 : { "protocol",
2741 : (PyCFunction)py_smb_protocol,
2742 : METH_NOARGS,
2743 : "protocol() -> Number"
2744 : },
2745 : { "have_posix",
2746 : (PyCFunction)py_smb_have_posix,
2747 : METH_NOARGS,
2748 : "have_posix() -> True/False\n\n"
2749 : "\t\tReturn if the server has posix extensions"
2750 : },
2751 : { "smb1_posix",
2752 : (PyCFunction)py_smb_smb1_posix,
2753 : METH_NOARGS,
2754 : "Negotiate SMB1 posix extensions",
2755 : },
2756 : { "smb1_readlink",
2757 : (PyCFunction)py_smb_smb1_readlink,
2758 : METH_VARARGS,
2759 : "smb1_readlink(path) -> link target",
2760 : },
2761 : { "smb1_symlink",
2762 : (PyCFunction)py_smb_smb1_symlink,
2763 : METH_VARARGS,
2764 : "smb1_symlink(target, newname) -> None",
2765 : },
2766 : { "smb1_stat",
2767 : (PyCFunction)py_smb_smb1_stat,
2768 : METH_VARARGS,
2769 : "smb1_stat(path) -> stat info",
2770 : },
2771 : { "fsctl",
2772 : (PyCFunction)py_cli_fsctl,
2773 : METH_VARARGS|METH_KEYWORDS,
2774 : "fsctl(fnum, ctl_code, in_bytes, max_out) -> out_bytes",
2775 : },
2776 : { "mknod",
2777 : PY_DISCARD_FUNC_SIG(PyCFunction, py_cli_mknod),
2778 : METH_VARARGS|METH_KEYWORDS,
2779 : "mknod(path, mode | major, minor)",
2780 : },
2781 : { NULL, NULL, 0, NULL }
2782 : };
2783 :
2784 : static PyTypeObject py_cli_state_type = {
2785 : PyVarObject_HEAD_INIT(NULL, 0)
2786 : .tp_name = "libsmb_samba_cwrapper.LibsmbCConn",
2787 : .tp_basicsize = sizeof(struct py_cli_state),
2788 : .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
2789 : .tp_doc = "libsmb cwrapper connection",
2790 : .tp_new = py_cli_state_new,
2791 : .tp_init = (initproc)py_cli_state_init,
2792 : .tp_dealloc = (destructor)py_cli_state_dealloc,
2793 : .tp_methods = py_cli_state_methods,
2794 : };
2795 :
2796 : static PyMethodDef py_libsmb_methods[] = {
2797 : {0},
2798 : };
2799 :
2800 : void initlibsmb_samba_cwrapper(void);
2801 :
2802 : static struct PyModuleDef moduledef = {
2803 : PyModuleDef_HEAD_INIT,
2804 : .m_name = "libsmb_samba_cwrapper",
2805 : .m_doc = "libsmb wrapper",
2806 : .m_size = -1,
2807 : .m_methods = py_libsmb_methods,
2808 : };
2809 :
2810 1858 : MODULE_INIT_FUNC(libsmb_samba_cwrapper)
2811 : {
2812 1858 : PyObject *m = NULL;
2813 1858 : PyObject *mod = NULL;
2814 :
2815 1858 : talloc_stackframe();
2816 :
2817 1858 : if (PyType_Ready(&py_cli_state_type) < 0) {
2818 0 : return NULL;
2819 : }
2820 1858 : if (PyType_Ready(&py_cli_notify_state_type) < 0) {
2821 0 : return NULL;
2822 : }
2823 :
2824 1858 : m = PyModule_Create(&moduledef);
2825 1858 : if (m == NULL) {
2826 0 : return m;
2827 : }
2828 :
2829 : /* Import dom_sid type from dcerpc.security */
2830 1858 : mod = PyImport_ImportModule("samba.dcerpc.security");
2831 1858 : if (mod == NULL) {
2832 0 : return NULL;
2833 : }
2834 :
2835 1858 : dom_sid_Type = (PyTypeObject *)PyObject_GetAttrString(mod, "dom_sid");
2836 1858 : if (dom_sid_Type == NULL) {
2837 0 : Py_DECREF(mod);
2838 0 : return NULL;
2839 : }
2840 :
2841 1522 : Py_INCREF(&py_cli_state_type);
2842 1858 : PyModule_AddObject(m, "LibsmbCConn", (PyObject *)&py_cli_state_type);
2843 :
2844 : #define ADD_FLAGS(val) PyModule_AddObject(m, #val, PyLong_FromLong(val))
2845 :
2846 1858 : ADD_FLAGS(PROTOCOL_NONE);
2847 1858 : ADD_FLAGS(PROTOCOL_CORE);
2848 1858 : ADD_FLAGS(PROTOCOL_COREPLUS);
2849 1858 : ADD_FLAGS(PROTOCOL_LANMAN1);
2850 1858 : ADD_FLAGS(PROTOCOL_LANMAN2);
2851 1858 : ADD_FLAGS(PROTOCOL_NT1);
2852 1858 : ADD_FLAGS(PROTOCOL_SMB2_02);
2853 1858 : ADD_FLAGS(PROTOCOL_SMB2_10);
2854 1858 : ADD_FLAGS(PROTOCOL_SMB3_00);
2855 1858 : ADD_FLAGS(PROTOCOL_SMB3_02);
2856 1858 : ADD_FLAGS(PROTOCOL_SMB3_11);
2857 :
2858 1858 : ADD_FLAGS(FILE_ATTRIBUTE_READONLY);
2859 1858 : ADD_FLAGS(FILE_ATTRIBUTE_HIDDEN);
2860 1858 : ADD_FLAGS(FILE_ATTRIBUTE_SYSTEM);
2861 1858 : ADD_FLAGS(FILE_ATTRIBUTE_VOLUME);
2862 1858 : ADD_FLAGS(FILE_ATTRIBUTE_DIRECTORY);
2863 1858 : ADD_FLAGS(FILE_ATTRIBUTE_ARCHIVE);
2864 1858 : ADD_FLAGS(FILE_ATTRIBUTE_DEVICE);
2865 1858 : ADD_FLAGS(FILE_ATTRIBUTE_NORMAL);
2866 1858 : ADD_FLAGS(FILE_ATTRIBUTE_TEMPORARY);
2867 1858 : ADD_FLAGS(FILE_ATTRIBUTE_SPARSE);
2868 1858 : ADD_FLAGS(FILE_ATTRIBUTE_REPARSE_POINT);
2869 1858 : ADD_FLAGS(FILE_ATTRIBUTE_COMPRESSED);
2870 1858 : ADD_FLAGS(FILE_ATTRIBUTE_OFFLINE);
2871 1858 : ADD_FLAGS(FILE_ATTRIBUTE_NONINDEXED);
2872 1858 : ADD_FLAGS(FILE_ATTRIBUTE_ENCRYPTED);
2873 1858 : ADD_FLAGS(FILE_ATTRIBUTE_ALL_MASK);
2874 :
2875 1858 : ADD_FLAGS(FILE_DIRECTORY_FILE);
2876 1858 : ADD_FLAGS(FILE_WRITE_THROUGH);
2877 1858 : ADD_FLAGS(FILE_SEQUENTIAL_ONLY);
2878 1858 : ADD_FLAGS(FILE_NO_INTERMEDIATE_BUFFERING);
2879 1858 : ADD_FLAGS(FILE_SYNCHRONOUS_IO_ALERT);
2880 1858 : ADD_FLAGS(FILE_SYNCHRONOUS_IO_NONALERT);
2881 1858 : ADD_FLAGS(FILE_NON_DIRECTORY_FILE);
2882 1858 : ADD_FLAGS(FILE_CREATE_TREE_CONNECTION);
2883 1858 : ADD_FLAGS(FILE_COMPLETE_IF_OPLOCKED);
2884 1858 : ADD_FLAGS(FILE_NO_EA_KNOWLEDGE);
2885 1858 : ADD_FLAGS(FILE_EIGHT_DOT_THREE_ONLY);
2886 1858 : ADD_FLAGS(FILE_RANDOM_ACCESS);
2887 1858 : ADD_FLAGS(FILE_DELETE_ON_CLOSE);
2888 1858 : ADD_FLAGS(FILE_OPEN_BY_FILE_ID);
2889 1858 : ADD_FLAGS(FILE_OPEN_FOR_BACKUP_INTENT);
2890 1858 : ADD_FLAGS(FILE_NO_COMPRESSION);
2891 1858 : ADD_FLAGS(FILE_RESERVER_OPFILTER);
2892 1858 : ADD_FLAGS(FILE_OPEN_REPARSE_POINT);
2893 1858 : ADD_FLAGS(FILE_OPEN_NO_RECALL);
2894 1858 : ADD_FLAGS(FILE_OPEN_FOR_FREE_SPACE_QUERY);
2895 :
2896 1858 : ADD_FLAGS(FILE_SHARE_READ);
2897 1858 : ADD_FLAGS(FILE_SHARE_WRITE);
2898 1858 : ADD_FLAGS(FILE_SHARE_DELETE);
2899 :
2900 : /* change notify completion filter flags */
2901 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_FILE_NAME);
2902 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_DIR_NAME);
2903 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_ATTRIBUTES);
2904 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_SIZE);
2905 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_LAST_WRITE);
2906 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_LAST_ACCESS);
2907 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_CREATION);
2908 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_EA);
2909 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_SECURITY);
2910 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_STREAM_NAME);
2911 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_STREAM_SIZE);
2912 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_STREAM_WRITE);
2913 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_NAME);
2914 1858 : ADD_FLAGS(FILE_NOTIFY_CHANGE_ALL);
2915 :
2916 : /* change notify action results */
2917 1858 : ADD_FLAGS(NOTIFY_ACTION_ADDED);
2918 1858 : ADD_FLAGS(NOTIFY_ACTION_REMOVED);
2919 1858 : ADD_FLAGS(NOTIFY_ACTION_MODIFIED);
2920 1858 : ADD_FLAGS(NOTIFY_ACTION_OLD_NAME);
2921 1858 : ADD_FLAGS(NOTIFY_ACTION_NEW_NAME);
2922 1858 : ADD_FLAGS(NOTIFY_ACTION_ADDED_STREAM);
2923 1858 : ADD_FLAGS(NOTIFY_ACTION_REMOVED_STREAM);
2924 1858 : ADD_FLAGS(NOTIFY_ACTION_MODIFIED_STREAM);
2925 :
2926 : /* CreateDisposition values */
2927 1858 : ADD_FLAGS(FILE_SUPERSEDE);
2928 1858 : ADD_FLAGS(FILE_OPEN);
2929 1858 : ADD_FLAGS(FILE_CREATE);
2930 1858 : ADD_FLAGS(FILE_OPEN_IF);
2931 1858 : ADD_FLAGS(FILE_OVERWRITE);
2932 1858 : ADD_FLAGS(FILE_OVERWRITE_IF);
2933 :
2934 1858 : ADD_FLAGS(FSCTL_DFS_GET_REFERRALS);
2935 1858 : ADD_FLAGS(FSCTL_DFS_GET_REFERRALS_EX);
2936 1858 : ADD_FLAGS(FSCTL_REQUEST_OPLOCK_LEVEL_1);
2937 1858 : ADD_FLAGS(FSCTL_REQUEST_OPLOCK_LEVEL_2);
2938 1858 : ADD_FLAGS(FSCTL_REQUEST_BATCH_OPLOCK);
2939 1858 : ADD_FLAGS(FSCTL_OPLOCK_BREAK_ACKNOWLEDGE);
2940 1858 : ADD_FLAGS(FSCTL_OPBATCH_ACK_CLOSE_PENDING);
2941 1858 : ADD_FLAGS(FSCTL_OPLOCK_BREAK_NOTIFY);
2942 1858 : ADD_FLAGS(FSCTL_GET_COMPRESSION);
2943 1858 : ADD_FLAGS(FSCTL_FILESYS_GET_STATISTICS);
2944 1858 : ADD_FLAGS(FSCTL_GET_NTFS_VOLUME_DATA);
2945 1858 : ADD_FLAGS(FSCTL_IS_VOLUME_DIRTY);
2946 1858 : ADD_FLAGS(FSCTL_FIND_FILES_BY_SID);
2947 1858 : ADD_FLAGS(FSCTL_SET_OBJECT_ID);
2948 1858 : ADD_FLAGS(FSCTL_GET_OBJECT_ID);
2949 1858 : ADD_FLAGS(FSCTL_DELETE_OBJECT_ID);
2950 1858 : ADD_FLAGS(FSCTL_SET_REPARSE_POINT);
2951 1858 : ADD_FLAGS(FSCTL_GET_REPARSE_POINT);
2952 1858 : ADD_FLAGS(FSCTL_DELETE_REPARSE_POINT);
2953 1858 : ADD_FLAGS(FSCTL_SET_OBJECT_ID_EXTENDED);
2954 1858 : ADD_FLAGS(FSCTL_CREATE_OR_GET_OBJECT_ID);
2955 1858 : ADD_FLAGS(FSCTL_SET_SPARSE);
2956 1858 : ADD_FLAGS(FSCTL_SET_ZERO_DATA);
2957 1858 : ADD_FLAGS(FSCTL_SET_ZERO_ON_DEALLOCATION);
2958 1858 : ADD_FLAGS(FSCTL_READ_FILE_USN_DATA);
2959 1858 : ADD_FLAGS(FSCTL_WRITE_USN_CLOSE_RECORD);
2960 1858 : ADD_FLAGS(FSCTL_QUERY_ALLOCATED_RANGES);
2961 1858 : ADD_FLAGS(FSCTL_QUERY_ON_DISK_VOLUME_INFO);
2962 1858 : ADD_FLAGS(FSCTL_QUERY_SPARING_INFO);
2963 1858 : ADD_FLAGS(FSCTL_FILE_LEVEL_TRIM);
2964 1858 : ADD_FLAGS(FSCTL_OFFLOAD_READ);
2965 1858 : ADD_FLAGS(FSCTL_OFFLOAD_WRITE);
2966 1858 : ADD_FLAGS(FSCTL_SET_INTEGRITY_INFORMATION);
2967 1858 : ADD_FLAGS(FSCTL_DUP_EXTENTS_TO_FILE);
2968 1858 : ADD_FLAGS(FSCTL_DUPLICATE_EXTENTS_TO_FILE_EX);
2969 1858 : ADD_FLAGS(FSCTL_STORAGE_QOS_CONTROL);
2970 1858 : ADD_FLAGS(FSCTL_SVHDX_SYNC_TUNNEL_REQUEST);
2971 1858 : ADD_FLAGS(FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT);
2972 1858 : ADD_FLAGS(FSCTL_PIPE_PEEK);
2973 1858 : ADD_FLAGS(FSCTL_NAMED_PIPE_READ_WRITE);
2974 1858 : ADD_FLAGS(FSCTL_PIPE_TRANSCEIVE);
2975 1858 : ADD_FLAGS(FSCTL_PIPE_WAIT);
2976 1858 : ADD_FLAGS(FSCTL_GET_SHADOW_COPY_DATA);
2977 1858 : ADD_FLAGS(FSCTL_SRV_ENUM_SNAPS);
2978 1858 : ADD_FLAGS(FSCTL_SRV_REQUEST_RESUME_KEY);
2979 1858 : ADD_FLAGS(FSCTL_SRV_COPYCHUNK);
2980 1858 : ADD_FLAGS(FSCTL_SRV_COPYCHUNK_WRITE);
2981 1858 : ADD_FLAGS(FSCTL_SRV_READ_HASH);
2982 1858 : ADD_FLAGS(FSCTL_LMR_REQ_RESILIENCY);
2983 1858 : ADD_FLAGS(FSCTL_LMR_SET_LINK_TRACKING_INFORMATION);
2984 1858 : ADD_FLAGS(FSCTL_QUERY_NETWORK_INTERFACE_INFO);
2985 :
2986 1858 : ADD_FLAGS(SYMLINK_ERROR_TAG);
2987 1858 : ADD_FLAGS(SYMLINK_FLAG_RELATIVE);
2988 1858 : ADD_FLAGS(SYMLINK_ADMIN);
2989 1858 : ADD_FLAGS(SYMLINK_UNTRUSTED);
2990 1858 : ADD_FLAGS(SYMLINK_TRUST_UNKNOWN);
2991 1858 : ADD_FLAGS(SYMLINK_TRUST_MASK);
2992 :
2993 1858 : ADD_FLAGS(IO_REPARSE_TAG_RESERVED_ZERO);
2994 1858 : ADD_FLAGS(IO_REPARSE_TAG_SYMLINK);
2995 1858 : ADD_FLAGS(IO_REPARSE_TAG_MOUNT_POINT);
2996 1858 : ADD_FLAGS(IO_REPARSE_TAG_HSM);
2997 1858 : ADD_FLAGS(IO_REPARSE_TAG_SIS);
2998 1858 : ADD_FLAGS(IO_REPARSE_TAG_DFS);
2999 1858 : ADD_FLAGS(IO_REPARSE_TAG_NFS);
3000 :
3001 : #define ADD_STRING(val) PyModule_AddObject(m, #val, PyBytes_FromString(val))
3002 :
3003 1858 : ADD_STRING(SMB2_CREATE_TAG_EXTA);
3004 1858 : ADD_STRING(SMB2_CREATE_TAG_MXAC);
3005 1858 : ADD_STRING(SMB2_CREATE_TAG_SECD);
3006 1858 : ADD_STRING(SMB2_CREATE_TAG_DHNQ);
3007 1858 : ADD_STRING(SMB2_CREATE_TAG_DHNC);
3008 1858 : ADD_STRING(SMB2_CREATE_TAG_ALSI);
3009 1858 : ADD_STRING(SMB2_CREATE_TAG_TWRP);
3010 1858 : ADD_STRING(SMB2_CREATE_TAG_QFID);
3011 1858 : ADD_STRING(SMB2_CREATE_TAG_RQLS);
3012 1858 : ADD_STRING(SMB2_CREATE_TAG_DH2Q);
3013 1858 : ADD_STRING(SMB2_CREATE_TAG_DH2C);
3014 1858 : ADD_STRING(SMB2_CREATE_TAG_AAPL);
3015 1858 : ADD_STRING(SMB2_CREATE_TAG_APP_INSTANCE_ID);
3016 1858 : ADD_STRING(SVHDX_OPEN_DEVICE_CONTEXT);
3017 1858 : ADD_STRING(SMB2_CREATE_TAG_POSIX);
3018 1858 : ADD_FLAGS(SMB2_FIND_POSIX_INFORMATION);
3019 1858 : ADD_FLAGS(FILE_SUPERSEDE);
3020 1858 : ADD_FLAGS(FILE_OPEN);
3021 1858 : ADD_FLAGS(FILE_CREATE);
3022 1858 : ADD_FLAGS(FILE_OPEN_IF);
3023 1858 : ADD_FLAGS(FILE_OVERWRITE);
3024 1858 : ADD_FLAGS(FILE_OVERWRITE_IF);
3025 1858 : ADD_FLAGS(FILE_DIRECTORY_FILE);
3026 :
3027 1858 : ADD_FLAGS(SMB2_CLOSE_FLAGS_FULL_INFORMATION);
3028 :
3029 1858 : return m;
3030 : }
|