2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "../util/tevent_unix.h"
23 #include "../lib/tsocket/tsocket.h"
24 #include "../lib/tsocket/tsocket_internal.h"
25 #include "../librpc/gen_ndr/ndr_named_pipe_auth.h"
26 #include "../libcli/named_pipe_auth/npa_tstream.h"
27 #include "../libcli/smb/smb_constants.h"
29 static const struct tstream_context_ops tstream_npa_ops
;
32 struct tstream_context
*unix_stream
;
39 struct tstream_npa_connect_state
{
41 struct tevent_context
*ev
;
44 const char *unix_path
;
45 struct tsocket_address
*unix_laddr
;
46 struct tsocket_address
*unix_raddr
;
47 struct tstream_context
*unix_stream
;
49 struct named_pipe_auth_req auth_req
;
50 DATA_BLOB auth_req_blob
;
51 struct iovec auth_req_iov
;
53 struct named_pipe_auth_rep auth_rep
;
54 DATA_BLOB auth_rep_blob
;
57 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
);
59 struct tevent_req
*tstream_npa_connect_send(TALLOC_CTX
*mem_ctx
,
60 struct tevent_context
*ev
,
61 const char *directory
,
63 const struct tsocket_address
*client
,
64 const char *client_name_in
,
65 const struct tsocket_address
*server
,
66 const char *server_name
,
67 const struct auth_session_info_transport
*session_info
)
69 struct tevent_req
*req
;
70 struct tstream_npa_connect_state
*state
;
71 struct tevent_req
*subreq
;
73 enum ndr_err_code ndr_err
;
74 char *lower_case_npipe
;
75 struct named_pipe_auth_req_info4
*info4
;
77 req
= tevent_req_create(mem_ctx
, &state
,
78 struct tstream_npa_connect_state
);
83 state
->caller
.ev
= ev
;
85 lower_case_npipe
= strlower_talloc(state
, npipe
);
86 if (tevent_req_nomem(lower_case_npipe
, req
)) {
90 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
93 talloc_free(lower_case_npipe
);
94 if (tevent_req_nomem(state
->unix_path
, req
)) {
98 ret
= tsocket_address_unix_from_path(state
,
102 tevent_req_error(req
, errno
);
106 ret
= tsocket_address_unix_from_path(state
,
110 tevent_req_error(req
, errno
);
114 ZERO_STRUCT(state
->auth_req
);
117 tevent_req_error(req
, EINVAL
);
121 state
->auth_req
.level
= 4;
122 info4
= &state
->auth_req
.info
.info4
;
124 info4
->client_name
= client_name_in
;
125 info4
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
126 if (!info4
->client_addr
) {
127 /* errno might be EINVAL */
128 tevent_req_error(req
, errno
);
131 info4
->client_port
= tsocket_address_inet_port(client
);
132 if (!info4
->client_name
) {
133 info4
->client_name
= info4
->client_addr
;
136 info4
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
137 if (!info4
->server_addr
) {
138 /* errno might be EINVAL */
139 tevent_req_error(req
, errno
);
142 info4
->server_port
= tsocket_address_inet_port(server
);
143 if (!info4
->server_name
) {
144 info4
->server_name
= info4
->server_addr
;
147 info4
->session_info
= discard_const_p(struct auth_session_info_transport
, session_info
);
150 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
153 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
154 state
, &state
->auth_req
,
155 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
156 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
157 tevent_req_error(req
, EINVAL
);
161 state
->auth_req_iov
.iov_base
= (char *) state
->auth_req_blob
.data
;
162 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
164 subreq
= tstream_unix_connect_send(state
,
168 if (tevent_req_nomem(subreq
, req
)) {
171 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
176 tevent_req_post(req
, ev
);
180 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
182 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
184 struct tevent_req
*req
=
185 tevent_req_callback_data(subreq
,
187 struct tstream_npa_connect_state
*state
=
189 struct tstream_npa_connect_state
);
193 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
194 state
, &state
->unix_stream
);
197 tevent_req_error(req
, sys_errno
);
201 subreq
= tstream_writev_send(state
,
204 &state
->auth_req_iov
, 1);
205 if (tevent_req_nomem(subreq
, req
)) {
208 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
211 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
214 struct iovec
**_vector
,
216 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
218 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
220 struct tevent_req
*req
=
221 tevent_req_callback_data(subreq
,
223 struct tstream_npa_connect_state
*state
=
225 struct tstream_npa_connect_state
);
229 ret
= tstream_writev_recv(subreq
, &sys_errno
);
232 tevent_req_error(req
, sys_errno
);
236 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
238 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
240 tstream_npa_connect_next_vector
,
242 if (tevent_req_nomem(subreq
, req
)) {
245 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
248 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
251 struct iovec
**_vector
,
254 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
255 struct tstream_npa_connect_state
);
256 struct iovec
*vector
;
260 if (state
->auth_rep_blob
.length
== 0) {
261 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
262 if (!state
->auth_rep_blob
.data
) {
265 } else if (state
->auth_rep_blob
.length
== 4) {
270 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
272 if (msg_len
> 0x00FFFFFF) {
284 state
->auth_rep_blob
.data
= talloc_realloc(state
,
285 state
->auth_rep_blob
.data
,
287 if (!state
->auth_rep_blob
.data
) {
290 state
->auth_rep_blob
.length
= msg_len
;
297 /* we need to get a message header */
298 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
302 vector
[0].iov_base
= (char *) (state
->auth_rep_blob
.data
+ ofs
);
303 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
311 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
313 struct tevent_req
*req
=
314 tevent_req_callback_data(subreq
,
316 struct tstream_npa_connect_state
*state
=
318 struct tstream_npa_connect_state
);
321 enum ndr_err_code ndr_err
;
323 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
326 tevent_req_error(req
, sys_errno
);
330 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
331 (uint32_t)state
->auth_rep_blob
.length
));
332 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
334 ndr_err
= ndr_pull_struct_blob(
335 &state
->auth_rep_blob
, state
,
337 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
339 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
340 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
341 ndr_map_error2string(ndr_err
)));
342 tevent_req_error(req
, EIO
);
347 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
350 if (state
->auth_rep
.length
< 16) {
351 DEBUG(0, ("req invalid length: %u < 16\n",
352 state
->auth_rep
.length
));
353 tevent_req_error(req
, EIO
);
357 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
358 DEBUG(0, ("req invalid magic: %s != %s\n",
359 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
360 tevent_req_error(req
, EIO
);
364 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
365 DEBUG(0, ("req failed: %s\n",
366 nt_errstr(state
->auth_rep
.status
)));
367 tevent_req_error(req
, EACCES
);
371 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
372 DEBUG(0, ("req invalid level: %u != %u\n",
373 state
->auth_rep
.level
, state
->auth_req
.level
));
374 tevent_req_error(req
, EIO
);
378 tevent_req_done(req
);
381 int _tstream_npa_connect_recv(struct tevent_req
*req
,
384 struct tstream_context
**_stream
,
385 uint16_t *_file_type
,
386 uint16_t *_device_state
,
387 uint64_t *_allocation_size
,
388 const char *location
)
390 struct tstream_npa_connect_state
*state
=
392 struct tstream_npa_connect_state
);
393 struct tstream_context
*stream
;
394 struct tstream_npa
*npas
;
395 uint16_t device_state
= 0;
396 uint64_t allocation_size
= 0;
398 if (tevent_req_is_unix_error(req
, perrno
)) {
399 tevent_req_received(req
);
403 stream
= tstream_context_create(mem_ctx
,
410 tevent_req_received(req
);
415 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
416 switch (state
->auth_rep
.level
) {
418 npas
->file_type
= state
->auth_rep
.info
.info4
.file_type
;
419 device_state
= state
->auth_rep
.info
.info4
.device_state
;
420 allocation_size
= state
->auth_rep
.info
.info4
.allocation_size
;
425 *_file_type
= npas
->file_type
;
426 *_device_state
= device_state
;
427 *_allocation_size
= allocation_size
;
428 tevent_req_received(req
);
432 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
434 struct tstream_npa
*npas
= tstream_context_data(stream
,
438 if (!npas
->unix_stream
) {
443 switch (npas
->file_type
) {
444 case FILE_TYPE_BYTE_MODE_PIPE
:
445 ret
= tstream_pending_bytes(npas
->unix_stream
);
448 case FILE_TYPE_MESSAGE_MODE_PIPE
:
449 ret
= npas
->pending
.iov_len
;
459 struct tstream_npa_readv_state
{
460 struct tstream_context
*stream
;
462 struct iovec
*vector
;
465 /* the header for message mode */
472 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
473 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
476 struct iovec
**_vector
,
478 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
480 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
481 struct tevent_context
*ev
,
482 struct tstream_context
*stream
,
483 struct iovec
*vector
,
486 struct tevent_req
*req
;
487 struct tstream_npa_readv_state
*state
;
488 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
489 struct tevent_req
*subreq
;
494 req
= tevent_req_create(mem_ctx
, &state
,
495 struct tstream_npa_readv_state
);
500 state
->stream
= stream
;
503 if (!npas
->unix_stream
) {
504 tevent_req_error(req
, ENOTCONN
);
508 switch (npas
->file_type
) {
509 case FILE_TYPE_BYTE_MODE_PIPE
:
510 state
->vector
= vector
;
511 state
->count
= count
;
513 subreq
= tstream_readv_send(state
,
518 if (tevent_req_nomem(subreq
,req
)) {
521 tevent_req_set_callback(subreq
,
522 tstream_npa_readv_byte_mode_handler
,
527 case FILE_TYPE_MESSAGE_MODE_PIPE
:
529 * we make a copy of the vector and prepend a header
532 state
->vector
= talloc_array(state
, struct iovec
, count
);
533 if (tevent_req_nomem(state
->vector
, req
)) {
536 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
537 state
->count
= count
;
540 * copy the pending buffer first
543 left
= npas
->pending
.iov_len
;
544 pbase
= (uint8_t *)npas
->pending
.iov_base
;
546 while (left
> 0 && state
->count
> 0) {
548 base
= (uint8_t *)state
->vector
[0].iov_base
;
549 if (left
< state
->vector
[0].iov_len
) {
550 memcpy(base
, pbase
+ ofs
, left
);
553 state
->vector
[0].iov_base
= (char *) base
;
554 state
->vector
[0].iov_len
-= left
;
559 ZERO_STRUCT(npas
->pending
);
562 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
564 ofs
+= state
->vector
[0].iov_len
;
565 left
-= state
->vector
[0].iov_len
;
571 ZERO_STRUCT(npas
->pending
);
577 memmove(pbase
, pbase
+ ofs
, left
);
578 npas
->pending
.iov_base
= (char *) pbase
;
579 npas
->pending
.iov_len
= left
;
581 * this cannot fail and even if it
582 * fails we can handle it
584 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
586 npas
->pending
.iov_base
= (char *) pbase
;
593 if (state
->count
== 0) {
594 tevent_req_done(req
);
598 ZERO_STRUCT(state
->hdr
);
599 state
->wait_for_hdr
= false;
601 subreq
= tstream_readv_pdu_send(state
,
604 tstream_npa_readv_next_vector
,
606 if (tevent_req_nomem(subreq
, req
)) {
609 tevent_req_set_callback(subreq
,
610 tstream_npa_readv_msg_mode_handler
,
616 /* this can't happen */
617 tevent_req_error(req
, EINVAL
);
621 tevent_req_post(req
, ev
);
625 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
627 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
629 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
630 struct tstream_npa_readv_state
);
634 ret
= tstream_readv_recv(subreq
, &sys_errno
);
637 tevent_req_error(req
, sys_errno
);
643 tevent_req_done(req
);
646 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
649 struct iovec
**_vector
,
652 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
653 struct tstream_npa_readv_state
);
654 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
656 struct iovec
*vector
;
661 if (state
->count
== 0) {
667 if (!state
->wait_for_hdr
) {
668 /* we need to get a message header */
669 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
673 ZERO_STRUCT(state
->hdr
);
674 vector
[0].iov_base
= (char *) state
->hdr
;
675 vector
[0].iov_len
= sizeof(state
->hdr
);
679 state
->wait_for_hdr
= true;
686 /* and now fill the callers buffers and maybe the pending buffer */
687 state
->wait_for_hdr
= false;
689 msg_len
= SVAL(state
->hdr
, 0);
696 state
->wait_for_hdr
= false;
698 /* +1 because we may need to fill the pending buffer */
699 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
706 while (left
> 0 && state
->count
> 0) {
707 if (left
< state
->vector
[0].iov_len
) {
709 base
= (uint8_t *)state
->vector
[0].iov_base
;
710 vector
[count
].iov_base
= (char *) base
;
711 vector
[count
].iov_len
= left
;
714 state
->vector
[0].iov_base
= (char *) base
;
715 state
->vector
[0].iov_len
-= left
;
718 vector
[count
] = state
->vector
[0];
720 left
-= state
->vector
[0].iov_len
;
727 * if the message is longer than the buffers the caller
728 * requested, we need to consume the rest of the message
729 * into the pending buffer, where the next readv can
732 npas
->pending
.iov_base
= talloc_array(npas
, char, left
);
733 if (!npas
->pending
.iov_base
) {
736 npas
->pending
.iov_len
= left
;
738 vector
[count
] = npas
->pending
;
742 state
->ret
+= (msg_len
- left
);
749 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
751 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
756 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
759 tevent_req_error(req
, sys_errno
);
764 * we do not set state->ret here as ret includes the headr size.
765 * we set it in tstream_npa_readv_pdu_next_vector()
768 tevent_req_done(req
);
771 static int tstream_npa_readv_recv(struct tevent_req
*req
,
774 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
775 struct tstream_npa_readv_state
);
778 ret
= tsocket_simple_int_recv(req
, perrno
);
783 tevent_req_received(req
);
787 struct tstream_npa_writev_state
{
788 const struct iovec
*vector
;
791 /* the header for message mode */
798 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
800 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
801 struct tevent_context
*ev
,
802 struct tstream_context
*stream
,
803 const struct iovec
*vector
,
806 struct tevent_req
*req
;
807 struct tstream_npa_writev_state
*state
;
808 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
809 struct tevent_req
*subreq
;
812 struct iovec
*new_vector
;
814 req
= tevent_req_create(mem_ctx
, &state
,
815 struct tstream_npa_writev_state
);
822 if (!npas
->unix_stream
) {
823 tevent_req_error(req
, ENOTCONN
);
827 switch (npas
->file_type
) {
828 case FILE_TYPE_BYTE_MODE_PIPE
:
829 state
->hdr_used
= false;
830 state
->vector
= vector
;
831 state
->count
= count
;
834 case FILE_TYPE_MESSAGE_MODE_PIPE
:
836 * we make a copy of the vector and prepend a header
839 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
840 if (tevent_req_nomem(new_vector
, req
)) {
843 new_vector
[0].iov_base
= (char *) state
->hdr
;
844 new_vector
[0].iov_len
= sizeof(state
->hdr
);
845 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
847 state
->hdr_used
= true;
848 state
->vector
= new_vector
;
849 state
->count
= count
+ 1;
852 for (i
=0; i
< count
; i
++) {
853 msg_len
+= vector
[i
].iov_len
;
856 if (msg_len
> UINT16_MAX
) {
857 tevent_req_error(req
, EMSGSIZE
);
861 SSVAL(state
->hdr
, 0, msg_len
);
865 subreq
= tstream_writev_send(state
,
870 if (tevent_req_nomem(subreq
, req
)) {
873 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
878 tevent_req_post(req
, ev
);
882 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
884 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
886 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
887 struct tstream_npa_writev_state
);
891 ret
= tstream_writev_recv(subreq
, &sys_errno
);
894 tevent_req_error(req
, sys_errno
);
899 * in message mode we need to hide the length
900 * of the hdr from the caller
902 if (state
->hdr_used
) {
903 ret
-= sizeof(state
->hdr
);
908 tevent_req_done(req
);
911 static int tstream_npa_writev_recv(struct tevent_req
*req
,
914 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
915 struct tstream_npa_writev_state
);
918 ret
= tsocket_simple_int_recv(req
, perrno
);
923 tevent_req_received(req
);
927 struct tstream_npa_disconnect_state
{
928 struct tstream_context
*stream
;
931 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
933 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
934 struct tevent_context
*ev
,
935 struct tstream_context
*stream
)
937 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
938 struct tevent_req
*req
;
939 struct tstream_npa_disconnect_state
*state
;
940 struct tevent_req
*subreq
;
942 req
= tevent_req_create(mem_ctx
, &state
,
943 struct tstream_npa_disconnect_state
);
948 state
->stream
= stream
;
950 if (!npas
->unix_stream
) {
951 tevent_req_error(req
, ENOTCONN
);
955 subreq
= tstream_disconnect_send(state
,
958 if (tevent_req_nomem(subreq
, req
)) {
961 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
966 tevent_req_post(req
, ev
);
970 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
972 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
974 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
975 struct tstream_npa_disconnect_state
);
976 struct tstream_context
*stream
= state
->stream
;
977 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
981 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
984 tevent_req_error(req
, sys_errno
);
988 TALLOC_FREE(npas
->unix_stream
);
990 tevent_req_done(req
);
993 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
998 ret
= tsocket_simple_int_recv(req
, perrno
);
1000 tevent_req_received(req
);
1004 static const struct tstream_context_ops tstream_npa_ops
= {
1007 .pending_bytes
= tstream_npa_pending_bytes
,
1009 .readv_send
= tstream_npa_readv_send
,
1010 .readv_recv
= tstream_npa_readv_recv
,
1012 .writev_send
= tstream_npa_writev_send
,
1013 .writev_recv
= tstream_npa_writev_recv
,
1015 .disconnect_send
= tstream_npa_disconnect_send
,
1016 .disconnect_recv
= tstream_npa_disconnect_recv
,
1019 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1022 struct tstream_context
**_stream
,
1023 const char *location
)
1025 struct tstream_context
*stream
;
1026 struct tstream_npa
*npas
;
1029 switch (file_type
) {
1030 case FILE_TYPE_BYTE_MODE_PIPE
:
1032 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1039 stream
= tstream_context_create(mem_ctx
,
1049 npas
->file_type
= file_type
;
1051 ret
= tstream_bsd_existing_socket(stream
, fd
,
1052 &npas
->unix_stream
);
1054 int saved_errno
= errno
;
1055 talloc_free(stream
);
1056 errno
= saved_errno
;
1065 struct tstream_npa_accept_state
{
1066 struct tevent_context
*ev
;
1067 struct tstream_context
*plain
;
1069 uint16_t device_state
;
1070 uint64_t alloc_size
;
1073 struct iovec out_iov
;
1076 NTSTATUS accept_status
;
1077 struct tsocket_address
*client
;
1079 struct tsocket_address
*server
;
1081 struct auth_session_info_transport
*session_info
;
1084 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1086 TALLOC_CTX
*mem_ctx
,
1087 struct iovec
**_vector
,
1089 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1090 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1092 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1093 struct tevent_context
*ev
,
1094 struct tstream_context
*plain
,
1096 uint16_t device_state
,
1097 uint64_t allocation_size
)
1099 struct tstream_npa_accept_state
*state
;
1100 struct tevent_req
*req
, *subreq
;
1102 req
= tevent_req_create(mem_ctx
, &state
,
1103 struct tstream_npa_accept_state
);
1108 switch (file_type
) {
1109 case FILE_TYPE_BYTE_MODE_PIPE
:
1111 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1114 tevent_req_error(req
, EINVAL
);
1118 ZERO_STRUCTP(state
);
1121 state
->plain
= plain
;
1122 state
->file_type
= file_type
;
1123 state
->device_state
= device_state
;
1124 state
->alloc_size
= allocation_size
;
1127 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1128 * named_pipe_full_request provides the pdu length then.
1130 subreq
= tstream_readv_pdu_send(state
, ev
, plain
,
1131 tstream_npa_accept_next_vector
,
1133 if (tevent_req_nomem(subreq
, req
)) {
1137 tevent_req_set_callback(subreq
,
1138 tstream_npa_accept_existing_reply
, req
);
1143 tevent_req_post(req
, ev
);
1147 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1149 TALLOC_CTX
*mem_ctx
,
1150 struct iovec
**_vector
,
1153 struct tstream_npa_accept_state
*state
=
1154 talloc_get_type_abort(private_data
,
1155 struct tstream_npa_accept_state
);
1156 struct iovec
*vector
;
1160 if (state
->npa_blob
.length
== 0) {
1161 state
->npa_blob
= data_blob_talloc(state
, NULL
, 4);
1162 if (!state
->npa_blob
.data
) {
1165 } else if (state
->npa_blob
.length
== 4) {
1170 msg_len
= RIVAL(state
->npa_blob
.data
, 0);
1172 if (msg_len
> 0x00FFFFFF) {
1184 state
->npa_blob
.data
= talloc_realloc(state
,
1185 state
->npa_blob
.data
,
1187 if (!state
->npa_blob
.data
) {
1190 state
->npa_blob
.length
= msg_len
;
1192 if (memcmp(&state
->npa_blob
.data
[4],
1193 NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1194 DEBUG(0, ("Wrong protocol\n"));
1195 #if defined(EPROTONOSUPPORT)
1196 errno
= EPROTONOSUPPORT
;
1197 #elif defined(EPROTO)
1209 /* we need to get a message header */
1210 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1214 vector
[0].iov_base
= (char *) (state
->npa_blob
.data
+ ofs
);
1215 vector
[0].iov_len
= state
->npa_blob
.length
- ofs
;
1223 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1225 struct tevent_req
*req
=
1226 tevent_req_callback_data(subreq
, struct tevent_req
);
1227 struct tstream_npa_accept_state
*state
=
1228 tevent_req_data(req
, struct tstream_npa_accept_state
);
1229 struct named_pipe_auth_req
*pipe_request
;
1230 struct named_pipe_auth_rep pipe_reply
;
1231 struct named_pipe_auth_req_info4 i4
;
1232 enum ndr_err_code ndr_err
;
1237 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
1238 TALLOC_FREE(subreq
);
1240 tevent_req_error(req
, sys_errno
);
1244 DEBUG(10, ("Received packet of length %lu\n",
1245 (long)state
->npa_blob
.length
));
1246 dump_data(11, state
->npa_blob
.data
, state
->npa_blob
.length
);
1248 ZERO_STRUCT(pipe_reply
);
1249 pipe_reply
.level
= 0;
1250 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1252 * TODO: check it's a root (uid == 0) pipe
1255 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1256 if (!pipe_request
) {
1257 DEBUG(0, ("Out of memory!\n"));
1261 /* parse the passed credentials */
1262 ndr_err
= ndr_pull_struct_blob_all(
1263 &state
->npa_blob
, pipe_request
, pipe_request
,
1264 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1266 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1267 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1268 nt_errstr(pipe_reply
.status
)));
1273 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1278 if (pipe_request
->level
!= 4) {
1279 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1280 pipe_reply
.level
= 0;
1281 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1285 pipe_reply
.level
= 4;
1286 pipe_reply
.status
= NT_STATUS_OK
;
1287 pipe_reply
.info
.info4
.file_type
= state
->file_type
;
1288 pipe_reply
.info
.info4
.device_state
= state
->device_state
;
1289 pipe_reply
.info
.info4
.allocation_size
= state
->alloc_size
;
1291 i4
= pipe_request
->info
.info4
;
1292 if (i4
.server_addr
== NULL
) {
1293 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1294 DEBUG(2, ("Missing server address\n"));
1297 if (i4
.client_addr
== NULL
) {
1298 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1299 DEBUG(2, ("Missing client address\n"));
1303 state
->server_name
= discard_const_p(char,
1304 talloc_move(state
, &i4
.server_name
));
1305 ret
= tsocket_address_inet_from_strings(state
, "ip",
1310 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1311 i4
.server_addr
, i4
.server_port
,
1313 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1317 state
->client_name
= discard_const_p(char,
1318 talloc_move(state
, &i4
.client_name
));
1319 ret
= tsocket_address_inet_from_strings(state
, "ip",
1324 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1325 i4
.client_addr
, i4
.client_port
,
1327 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1331 state
->session_info
= talloc_move(state
, &i4
.session_info
);
1333 /* create the output */
1334 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1335 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1336 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1337 DEBUG(2, ("Error encoding structure: %s",
1338 ndr_map_error2string(ndr_err
)));
1339 tevent_req_error(req
, EIO
);
1343 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1344 dump_data(11, out
.data
, out
.length
);
1347 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1350 state
->accept_status
= pipe_reply
.status
;
1352 state
->out_iov
.iov_base
= (char *) out
.data
;
1353 state
->out_iov
.iov_len
= out
.length
;
1355 subreq
= tstream_writev_send(state
, state
->ev
,
1357 &state
->out_iov
, 1);
1358 if (tevent_req_nomem(subreq
, req
)) {
1359 DEBUG(0, ("no memory for tstream_writev_send"));
1363 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1366 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1368 struct tevent_req
*req
=
1369 tevent_req_callback_data(subreq
, struct tevent_req
);
1373 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1374 TALLOC_FREE(subreq
);
1376 tevent_req_error(req
, sys_errno
);
1380 tevent_req_done(req
);
1383 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1385 TALLOC_CTX
*mem_ctx
,
1386 struct tstream_context
**stream
,
1387 struct tsocket_address
**client
,
1388 char **_client_name
,
1389 struct tsocket_address
**server
,
1391 struct auth_session_info_transport
**session_info
,
1392 const char *location
)
1394 struct tstream_npa_accept_state
*state
=
1395 tevent_req_data(req
, struct tstream_npa_accept_state
);
1396 struct tstream_npa
*npas
;
1399 ret
= tsocket_simple_int_recv(req
, perrno
);
1401 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1402 strerror(*perrno
)));
1403 tevent_req_received(req
);
1407 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1408 #if defined(EPROTONOSUPPORT)
1409 *perrno
= EPROTONOSUPPORT
;
1410 #elif defined(EPROTO)
1415 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1416 nt_errstr(state
->accept_status
),
1417 strerror(*perrno
)));
1418 tevent_req_received(req
);
1422 *stream
= tstream_context_create(mem_ctx
,
1429 tevent_req_received(req
);
1433 npas
->unix_stream
= state
->plain
;
1434 npas
->file_type
= state
->file_type
;
1436 *client
= talloc_move(mem_ctx
, &state
->client
);
1437 *_client_name
= talloc_move(mem_ctx
, &state
->client_name
);
1438 *server
= talloc_move(mem_ctx
, &state
->server
);
1439 *server_name
= talloc_move(mem_ctx
, &state
->server_name
);
1440 *session_info
= talloc_move(mem_ctx
, &state
->session_info
);
1442 tevent_req_received(req
);