ldb_kv: Use ldb_msg_add_steal_value() in msg_add_distinguished_name()
[Samba.git] / source3 / libsmb / clifsinfo.c
blob1c140ebbd59035611c22c2b1210cfe2bc8e7c36b
1 /*
2 Unix SMB/CIFS implementation.
3 FS info functions
4 Copyright (C) Stefan (metze) Metzmacher 2003
5 Copyright (C) Jeremy Allison 2007
6 Copyright (C) Andrew Bartlett 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "trans2.h"
27 #include "auth_generic.h"
28 #include "auth/gensec/gensec.h"
29 #include "../libcli/smb/smbXcli_base.h"
30 #include "auth/credentials/credentials.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "libcli/security/dom_sid.h"
34 /****************************************************************************
35 Get UNIX extensions version info.
36 ****************************************************************************/
38 struct cli_unix_extensions_version_state {
39 struct cli_state *cli;
40 uint16_t setup[1];
41 uint8_t param[2];
42 uint16_t major, minor;
43 uint32_t caplow, caphigh;
46 static void cli_unix_extensions_version_done(struct tevent_req *subreq);
48 struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx,
49 struct tevent_context *ev,
50 struct cli_state *cli)
52 struct tevent_req *req, *subreq;
53 struct cli_unix_extensions_version_state *state;
55 req = tevent_req_create(mem_ctx, &state,
56 struct cli_unix_extensions_version_state);
57 if (req == NULL) {
58 return NULL;
60 state->cli = cli;
61 SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
62 SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO);
64 subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
65 NULL, 0, 0, 0,
66 state->setup, 1, 0,
67 state->param, 2, 0,
68 NULL, 0, 560);
69 if (tevent_req_nomem(subreq, req)) {
70 return tevent_req_post(req, ev);
72 tevent_req_set_callback(subreq, cli_unix_extensions_version_done, req);
73 return req;
76 static void cli_unix_extensions_version_done(struct tevent_req *subreq)
78 struct tevent_req *req = tevent_req_callback_data(
79 subreq, struct tevent_req);
80 struct cli_unix_extensions_version_state *state = tevent_req_data(
81 req, struct cli_unix_extensions_version_state);
82 uint8_t *data;
83 uint32_t num_data;
84 NTSTATUS status;
86 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
87 NULL, 0, NULL, &data, 12, &num_data);
88 TALLOC_FREE(subreq);
89 if (!NT_STATUS_IS_OK(status)) {
90 tevent_req_nterror(req, status);
91 return;
94 state->major = SVAL(data, 0);
95 state->minor = SVAL(data, 2);
96 state->caplow = IVAL(data, 4);
97 state->caphigh = IVAL(data, 8);
98 TALLOC_FREE(data);
99 tevent_req_done(req);
102 NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req,
103 uint16_t *pmajor, uint16_t *pminor,
104 uint32_t *pcaplow,
105 uint32_t *pcaphigh)
107 struct cli_unix_extensions_version_state *state = tevent_req_data(
108 req, struct cli_unix_extensions_version_state);
109 NTSTATUS status;
111 if (tevent_req_is_nterror(req, &status)) {
112 return status;
114 *pmajor = state->major;
115 *pminor = state->minor;
116 *pcaplow = state->caplow;
117 *pcaphigh = state->caphigh;
118 state->cli->server_posix_capabilities = *pcaplow;
119 return NT_STATUS_OK;
122 NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16_t *pmajor,
123 uint16_t *pminor, uint32_t *pcaplow,
124 uint32_t *pcaphigh)
126 TALLOC_CTX *frame = talloc_stackframe();
127 struct tevent_context *ev;
128 struct tevent_req *req;
129 NTSTATUS status = NT_STATUS_OK;
131 if (smbXcli_conn_has_async_calls(cli->conn)) {
133 * Can't use sync call while an async call is in flight
135 status = NT_STATUS_INVALID_PARAMETER;
136 goto fail;
139 ev = samba_tevent_context_init(frame);
140 if (ev == NULL) {
141 status = NT_STATUS_NO_MEMORY;
142 goto fail;
145 req = cli_unix_extensions_version_send(frame, ev, cli);
146 if (req == NULL) {
147 status = NT_STATUS_NO_MEMORY;
148 goto fail;
151 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
152 goto fail;
155 status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow,
156 pcaphigh);
157 fail:
158 TALLOC_FREE(frame);
159 return status;
162 /****************************************************************************
163 Set UNIX extensions capabilities.
164 ****************************************************************************/
166 struct cli_set_unix_extensions_capabilities_state {
167 struct cli_state *cli;
168 uint16_t setup[1];
169 uint8_t param[4];
170 uint8_t data[12];
173 static void cli_set_unix_extensions_capabilities_done(
174 struct tevent_req *subreq);
176 struct tevent_req *cli_set_unix_extensions_capabilities_send(
177 TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli,
178 uint16_t major, uint16_t minor, uint32_t caplow, uint32_t caphigh)
180 struct tevent_req *req, *subreq;
181 struct cli_set_unix_extensions_capabilities_state *state;
183 req = tevent_req_create(
184 mem_ctx, &state,
185 struct cli_set_unix_extensions_capabilities_state);
186 if (req == NULL) {
187 return NULL;
190 state->cli = cli;
191 SSVAL(state->setup+0, 0, TRANSACT2_SETFSINFO);
193 SSVAL(state->param, 0, 0);
194 SSVAL(state->param, 2, SMB_SET_CIFS_UNIX_INFO);
196 SSVAL(state->data, 0, major);
197 SSVAL(state->data, 2, minor);
198 SIVAL(state->data, 4, caplow);
199 SIVAL(state->data, 8, caphigh);
201 subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
202 NULL, 0, 0, 0,
203 state->setup, 1, 0,
204 state->param, 4, 0,
205 state->data, 12, 560);
206 if (tevent_req_nomem(subreq, req)) {
207 return tevent_req_post(req, ev);
209 tevent_req_set_callback(
210 subreq, cli_set_unix_extensions_capabilities_done, req);
211 return req;
214 static void cli_set_unix_extensions_capabilities_done(
215 struct tevent_req *subreq)
217 struct tevent_req *req = tevent_req_callback_data(
218 subreq, struct tevent_req);
219 struct cli_set_unix_extensions_capabilities_state *state = tevent_req_data(
220 req, struct cli_set_unix_extensions_capabilities_state);
222 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
223 NULL, 0, NULL, NULL, 0, NULL);
224 if (NT_STATUS_IS_OK(status)) {
225 state->cli->requested_posix_capabilities = IVAL(state->data, 4);
227 tevent_req_simple_finish_ntstatus(subreq, status);
230 NTSTATUS cli_set_unix_extensions_capabilities_recv(struct tevent_req *req)
232 return tevent_req_simple_recv_ntstatus(req);
235 NTSTATUS cli_set_unix_extensions_capabilities(struct cli_state *cli,
236 uint16_t major, uint16_t minor,
237 uint32_t caplow, uint32_t caphigh)
239 struct tevent_context *ev;
240 struct tevent_req *req;
241 NTSTATUS status = NT_STATUS_NO_MEMORY;
243 if (smbXcli_conn_has_async_calls(cli->conn)) {
244 return NT_STATUS_INVALID_PARAMETER;
246 ev = samba_tevent_context_init(talloc_tos());
247 if (ev == NULL) {
248 goto fail;
250 req = cli_set_unix_extensions_capabilities_send(
251 ev, ev, cli, major, minor, caplow, caphigh);
252 if (req == NULL) {
253 goto fail;
255 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
256 goto fail;
258 status = cli_set_unix_extensions_capabilities_recv(req);
259 fail:
260 TALLOC_FREE(ev);
261 return status;
264 struct cli_get_fs_attr_info_state {
265 uint16_t setup[1];
266 uint8_t param[2];
267 uint32_t fs_attr;
270 static void cli_get_fs_attr_info_done(struct tevent_req *subreq);
272 struct tevent_req *cli_get_fs_attr_info_send(TALLOC_CTX *mem_ctx,
273 struct tevent_context *ev,
274 struct cli_state *cli)
276 struct tevent_req *subreq, *req;
277 struct cli_get_fs_attr_info_state *state;
279 req = tevent_req_create(mem_ctx, &state,
280 struct cli_get_fs_attr_info_state);
281 if (req == NULL) {
282 return NULL;
284 SSVAL(state->setup+0, 0, TRANSACT2_QFSINFO);
285 SSVAL(state->param+0, 0, SMB_QUERY_FS_ATTRIBUTE_INFO);
287 subreq = cli_trans_send(state, ev, cli, 0, SMBtrans2,
288 NULL, 0, 0, 0,
289 state->setup, 1, 0,
290 state->param, 2, 0,
291 NULL, 0, 560);
292 if (tevent_req_nomem(subreq, req)) {
293 return tevent_req_post(req, ev);
295 tevent_req_set_callback(subreq, cli_get_fs_attr_info_done, req);
296 return req;
299 static void cli_get_fs_attr_info_done(struct tevent_req *subreq)
301 struct tevent_req *req = tevent_req_callback_data(
302 subreq, struct tevent_req);
303 struct cli_get_fs_attr_info_state *state = tevent_req_data(
304 req, struct cli_get_fs_attr_info_state);
305 uint8_t *data;
306 uint32_t num_data;
307 NTSTATUS status;
309 status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL, 0, NULL,
310 NULL, 0, NULL, &data, 12, &num_data);
311 TALLOC_FREE(subreq);
312 if (!NT_STATUS_IS_OK(status)) {
313 tevent_req_nterror(req, status);
314 return;
316 state->fs_attr = IVAL(data, 0);
317 TALLOC_FREE(data);
318 tevent_req_done(req);
321 NTSTATUS cli_get_fs_attr_info_recv(struct tevent_req *req, uint32_t *fs_attr)
323 struct cli_get_fs_attr_info_state *state = tevent_req_data(
324 req, struct cli_get_fs_attr_info_state);
325 NTSTATUS status;
327 if (tevent_req_is_nterror(req, &status)) {
328 return status;
330 *fs_attr = state->fs_attr;
331 return NT_STATUS_OK;
334 NTSTATUS cli_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr)
336 struct tevent_context *ev;
337 struct tevent_req *req;
338 NTSTATUS status = NT_STATUS_NO_MEMORY;
340 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
341 return cli_smb2_get_fs_attr_info(cli, fs_attr);
344 if (smbXcli_conn_has_async_calls(cli->conn)) {
345 return NT_STATUS_INVALID_PARAMETER;
347 ev = samba_tevent_context_init(talloc_tos());
348 if (ev == NULL) {
349 goto fail;
351 req = cli_get_fs_attr_info_send(ev, ev, cli);
352 if (req == NULL) {
353 goto fail;
355 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
356 goto fail;
358 status = cli_get_fs_attr_info_recv(req, fs_attr);
359 fail:
360 TALLOC_FREE(ev);
361 return status;
364 NTSTATUS cli_get_fs_volume_info(struct cli_state *cli,
365 TALLOC_CTX *mem_ctx,
366 char **_volume_name,
367 uint32_t *pserial_number,
368 time_t *pdate)
370 NTSTATUS status;
371 uint16_t recv_flags2;
372 uint16_t setup[1];
373 uint8_t param[2];
374 uint8_t *rdata;
375 uint32_t rdata_count;
376 unsigned int nlen;
377 char *volume_name = NULL;
379 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
380 return cli_smb2_get_fs_volume_info(cli,
381 mem_ctx,
382 _volume_name,
383 pserial_number,
384 pdate);
387 SSVAL(setup, 0, TRANSACT2_QFSINFO);
388 SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
390 status = cli_trans(talloc_tos(), cli, SMBtrans2,
391 NULL, 0, 0, 0,
392 setup, 1, 0,
393 param, 2, 0,
394 NULL, 0, 560,
395 &recv_flags2,
396 NULL, 0, NULL,
397 NULL, 0, NULL,
398 &rdata, 18, &rdata_count);
399 if (!NT_STATUS_IS_OK(status)) {
400 return status;
403 if (pdate) {
404 struct timespec ts;
405 ts = interpret_long_date((char *)rdata);
406 *pdate = ts.tv_sec;
408 if (pserial_number) {
409 *pserial_number = IVAL(rdata,8);
411 nlen = IVAL(rdata,12);
412 if (nlen > (rdata_count - 18)) {
413 TALLOC_FREE(rdata);
414 return NT_STATUS_INVALID_NETWORK_RESPONSE;
417 clistr_pull_talloc(mem_ctx,
418 (const char *)rdata,
419 recv_flags2,
420 &volume_name,
421 rdata + 18,
422 nlen, STR_UNICODE);
423 if (volume_name == NULL) {
424 status = map_nt_error_from_unix(errno);
425 TALLOC_FREE(rdata);
426 return status;
429 /* todo: but not yet needed
430 * return the other stuff
433 *_volume_name = volume_name;
434 TALLOC_FREE(rdata);
435 return NT_STATUS_OK;
438 NTSTATUS cli_get_fs_full_size_info(struct cli_state *cli,
439 uint64_t *total_allocation_units,
440 uint64_t *caller_allocation_units,
441 uint64_t *actual_allocation_units,
442 uint64_t *sectors_per_allocation_unit,
443 uint64_t *bytes_per_sector)
445 uint16_t setup[1];
446 uint8_t param[2];
447 uint8_t *rdata = NULL;
448 uint32_t rdata_count;
449 NTSTATUS status;
451 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
452 return cli_smb2_get_fs_full_size_info(cli,
453 total_allocation_units,
454 caller_allocation_units,
455 actual_allocation_units,
456 sectors_per_allocation_unit,
457 bytes_per_sector);
460 SSVAL(setup, 0, TRANSACT2_QFSINFO);
461 SSVAL(param, 0, SMB_FS_FULL_SIZE_INFORMATION);
463 status = cli_trans(talloc_tos(), cli, SMBtrans2,
464 NULL, 0, 0, 0,
465 setup, 1, 0, /* setup */
466 param, 2, 0, /* param */
467 NULL, 0, 560, /* data */
468 NULL,
469 NULL, 0, NULL, /* rsetup */
470 NULL, 0, NULL, /* rparam */
471 &rdata, 32, &rdata_count); /* rdata */
472 if (!NT_STATUS_IS_OK(status)) {
473 goto fail;
476 if (total_allocation_units) {
477 *total_allocation_units = BIG_UINT(rdata, 0);
479 if (caller_allocation_units) {
480 *caller_allocation_units = BIG_UINT(rdata,8);
482 if (actual_allocation_units) {
483 *actual_allocation_units = BIG_UINT(rdata,16);
485 if (sectors_per_allocation_unit) {
486 *sectors_per_allocation_unit = IVAL(rdata,24);
488 if (bytes_per_sector) {
489 *bytes_per_sector = IVAL(rdata,28);
492 fail:
493 TALLOC_FREE(rdata);
494 return status;
497 NTSTATUS cli_get_posix_fs_info(struct cli_state *cli,
498 uint32_t *optimal_transfer_size,
499 uint32_t *block_size,
500 uint64_t *total_blocks,
501 uint64_t *blocks_available,
502 uint64_t *user_blocks_available,
503 uint64_t *total_file_nodes,
504 uint64_t *free_file_nodes,
505 uint64_t *fs_identifier)
507 uint16_t setup[1];
508 uint8_t param[2];
509 uint8_t *rdata = NULL;
510 uint32_t rdata_count;
511 NTSTATUS status;
513 SSVAL(setup, 0, TRANSACT2_QFSINFO);
514 SSVAL(param,0,SMB_QUERY_POSIX_FS_INFO);
516 status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, 0, 0, 0,
517 setup, 1, 0,
518 param, 2, 0,
519 NULL, 0, 560,
520 NULL,
521 NULL, 0, NULL, /* rsetup */
522 NULL, 0, NULL, /* rparam */
523 &rdata, 56, &rdata_count);
524 if (!NT_STATUS_IS_OK(status)) {
525 return status;
528 if (optimal_transfer_size) {
529 *optimal_transfer_size = IVAL(rdata, 0);
531 if (block_size) {
532 *block_size = IVAL(rdata,4);
534 if (total_blocks) {
535 *total_blocks = BIG_UINT(rdata,8);
537 if (blocks_available) {
538 *blocks_available = BIG_UINT(rdata,16);
540 if (user_blocks_available) {
541 *user_blocks_available = BIG_UINT(rdata,24);
543 if (total_file_nodes) {
544 *total_file_nodes = BIG_UINT(rdata,32);
546 if (free_file_nodes) {
547 *free_file_nodes = BIG_UINT(rdata,40);
549 if (fs_identifier) {
550 *fs_identifier = BIG_UINT(rdata,48);
552 return NT_STATUS_OK;
555 /****************************************************************************
556 Do a UNIX extensions SMB_QUERY_POSIX_WHOAMI call.
557 ****************************************************************************/
559 struct posix_whoami_state {
560 uint16_t setup[1];
561 uint8_t param[2];
562 uint32_t max_rdata;
563 bool guest;
564 uint64_t uid;
565 uint64_t gid;
566 uint32_t num_gids;
567 uint64_t *gids;
568 uint32_t num_sids;
569 struct dom_sid *sids;
572 static void cli_posix_whoami_done(struct tevent_req *subreq);
574 struct tevent_req *cli_posix_whoami_send(TALLOC_CTX *mem_ctx,
575 struct tevent_context *ev,
576 struct cli_state *cli)
578 struct tevent_req *req = NULL, *subreq = NULL;
579 struct posix_whoami_state *state = NULL;
581 req = tevent_req_create(mem_ctx, &state, struct posix_whoami_state);
582 if (req == NULL) {
583 return NULL;
586 /* Setup setup word. */
587 SSVAL(state->setup, 0, TRANSACT2_QFSINFO);
588 SSVAL(state->param, 0, SMB_QUERY_POSIX_WHOAMI);
590 state->max_rdata = 62*1024;
592 subreq = cli_trans_send(state, /* mem ctx. */
593 ev, /* event ctx. */
594 cli, /* cli_state. */
595 0, /* additional_flags2 */
596 SMBtrans2, /* cmd. */
597 NULL, /* pipe name. */
598 -1, /* fid. */
599 0, /* function. */
600 0, /* flags. */
601 state->setup, /* setup. */
602 1, /* num setup uint16_t words. */
603 0, /* max returned setup. */
604 state->param, /* param. */
605 2, /* num param. */
606 0, /* max returned param. */
607 NULL, /* data. */
608 0, /* num data. */
609 state->max_rdata); /* max returned data. */
611 if (tevent_req_nomem(subreq, req)) {
612 return tevent_req_post(req, ev);
614 tevent_req_set_callback(subreq, cli_posix_whoami_done, req);
615 return req;
618 static void cli_posix_whoami_done(struct tevent_req *subreq)
620 struct tevent_req *req = tevent_req_callback_data(
621 subreq, struct tevent_req);
622 struct posix_whoami_state *state = tevent_req_data(
623 req, struct posix_whoami_state);
624 uint8_t *rdata = NULL;
625 uint8_t *p = NULL;
626 uint32_t num_rdata = 0;
627 uint32_t i;
628 NTSTATUS status;
630 status = cli_trans_recv(subreq,
631 state,
632 NULL,
633 NULL,
635 NULL,
636 NULL,
638 NULL,
639 &rdata,
641 &num_rdata);
642 TALLOC_FREE(subreq);
643 if (tevent_req_nterror(req, status)) {
644 return;
648 * Not strictly needed - cli_trans_recv()
649 * will ensure at least 40 bytes here. Added
650 * as more of a reminder to be careful when
651 * parsing network packets in C.
654 if (num_rdata < 40 || rdata + num_rdata < rdata) {
655 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
656 return;
659 state->guest = (IVAL(rdata, 0) & SMB_WHOAMI_GUEST);
660 state->uid = BVAL(rdata, 8);
661 state->gid = BVAL(rdata, 16);
662 state->num_gids = IVAL(rdata, 24);
663 state->num_sids = IVAL(rdata, 28);
665 state->gids = talloc_array(state, uint64_t, state->num_gids);
666 if (tevent_req_nomem(state->gids, req)) {
667 return;
669 state->sids = talloc_array(state, struct dom_sid, state->num_sids);
670 if (tevent_req_nomem(state->sids, req)) {
671 return;
674 p = rdata + 40;
676 for (i = 0; i < state->num_gids; i++) {
677 if (p + 8 > rdata + num_rdata) {
678 tevent_req_nterror(req,
679 NT_STATUS_INVALID_NETWORK_RESPONSE);
680 return;
682 state->gids[i] = BVAL(p, 0);
683 p += 8;
686 num_rdata -= (p - rdata);
688 for (i = 0; i < state->num_sids; i++) {
689 ssize_t sid_size = sid_parse(p, num_rdata, &state->sids[i]);
691 if ((sid_size == -1) || (sid_size > num_rdata)) {
692 tevent_req_nterror(req,
693 NT_STATUS_INVALID_NETWORK_RESPONSE);
694 return;
697 p += sid_size;
698 num_rdata -= sid_size;
700 tevent_req_done(req);
703 NTSTATUS cli_posix_whoami_recv(struct tevent_req *req,
704 TALLOC_CTX *mem_ctx,
705 uint64_t *puid,
706 uint64_t *pgid,
707 uint32_t *pnum_gids,
708 uint64_t **pgids,
709 uint32_t *pnum_sids,
710 struct dom_sid **psids,
711 bool *pguest)
713 NTSTATUS status;
714 struct posix_whoami_state *state = tevent_req_data(
715 req, struct posix_whoami_state);
717 if (tevent_req_is_nterror(req, &status)) {
718 return status;
721 if (puid) {
722 *puid = state->uid;
724 if (pgid) {
725 *pgid = state->gid;
727 if (pnum_gids) {
728 *pnum_gids = state->num_gids;
730 if (pgids) {
731 *pgids = talloc_move(mem_ctx, &state->gids);
733 if (pnum_sids) {
734 *pnum_sids = state->num_sids;
736 if (psids) {
737 *psids = talloc_move(mem_ctx, &state->sids);
739 if (pguest) {
740 *pguest = state->guest;
742 return NT_STATUS_OK;
745 NTSTATUS cli_posix_whoami(struct cli_state *cli,
746 TALLOC_CTX *mem_ctx,
747 uint64_t *puid,
748 uint64_t *pgid,
749 uint32_t *num_gids,
750 uint64_t **gids,
751 uint32_t *num_sids,
752 struct dom_sid **sids,
753 bool *pguest)
755 TALLOC_CTX *frame = talloc_stackframe();
756 struct tevent_context *ev = NULL;
757 struct tevent_req *req = NULL;
758 NTSTATUS status = NT_STATUS_OK;
760 if (smbXcli_conn_has_async_calls(cli->conn)) {
762 * Can't use sync call while an async call is in flight
764 status = NT_STATUS_INVALID_PARAMETER;
765 goto fail;
768 ev = samba_tevent_context_init(frame);
769 if (ev == NULL) {
770 status = NT_STATUS_NO_MEMORY;
771 goto fail;
774 req = cli_posix_whoami_send(frame,
776 cli);
777 if (req == NULL) {
778 status = NT_STATUS_NO_MEMORY;
779 goto fail;
782 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
783 goto fail;
786 status = cli_posix_whoami_recv(req,
787 mem_ctx,
788 puid,
789 pgid,
790 num_gids,
791 gids,
792 num_sids,
793 sids,
794 pguest);
796 fail:
797 TALLOC_FREE(frame);
798 return status;