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/named_pipe_auth/tstream_u32_read.h"
28 #include "../libcli/smb/smb_constants.h"
30 static const struct tstream_context_ops tstream_npa_ops
;
33 struct tstream_context
*unix_stream
;
40 struct tstream_npa_connect_state
{
42 struct tevent_context
*ev
;
45 const char *unix_path
;
46 struct tsocket_address
*unix_laddr
;
47 struct tsocket_address
*unix_raddr
;
48 struct tstream_context
*unix_stream
;
50 struct named_pipe_auth_req auth_req
;
51 DATA_BLOB auth_req_blob
;
52 struct iovec auth_req_iov
;
54 struct named_pipe_auth_rep auth_rep
;
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 enum dcerpc_transport_t transport
,
64 const struct tsocket_address
*remote_client_addr
,
65 const char *remote_client_name_in
,
66 const struct tsocket_address
*local_server_addr
,
67 const char *local_server_name_in
,
68 const struct auth_session_info_transport
*session_info
)
70 struct tevent_req
*req
;
71 struct tstream_npa_connect_state
*state
;
72 struct tevent_req
*subreq
;
74 enum ndr_err_code ndr_err
;
75 char *lower_case_npipe
;
76 struct named_pipe_auth_req_info8
*info8
;
78 req
= tevent_req_create(mem_ctx
, &state
,
79 struct tstream_npa_connect_state
);
84 state
->caller
.ev
= ev
;
86 lower_case_npipe
= strlower_talloc(state
, npipe
);
87 if (tevent_req_nomem(lower_case_npipe
, req
)) {
91 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
94 talloc_free(lower_case_npipe
);
95 if (tevent_req_nomem(state
->unix_path
, req
)) {
99 ret
= tsocket_address_unix_from_path(state
,
103 tevent_req_error(req
, errno
);
107 ret
= tsocket_address_unix_from_path(state
,
111 tevent_req_error(req
, errno
);
115 ZERO_STRUCT(state
->auth_req
);
117 if (!local_server_addr
) {
118 tevent_req_error(req
, EINVAL
);
122 state
->auth_req
.level
= 8;
123 info8
= &state
->auth_req
.info
.info8
;
125 info8
->transport
= transport
;
126 SMB_ASSERT(info8
->transport
== transport
); /* Assert no overflow */
128 info8
->remote_client_name
= remote_client_name_in
;
129 info8
->remote_client_addr
=
130 tsocket_address_inet_addr_string(remote_client_addr
, state
);
131 if (!info8
->remote_client_addr
) {
132 /* errno might be EINVAL */
133 tevent_req_error(req
, errno
);
136 info8
->remote_client_port
=
137 tsocket_address_inet_port(remote_client_addr
);
138 if (!info8
->remote_client_name
) {
139 info8
->remote_client_name
= info8
->remote_client_addr
;
142 info8
->local_server_name
= local_server_name_in
;
143 info8
->local_server_addr
=
144 tsocket_address_inet_addr_string(local_server_addr
, state
);
145 if (!info8
->local_server_addr
) {
146 /* errno might be EINVAL */
147 tevent_req_error(req
, errno
);
150 info8
->local_server_port
=
151 tsocket_address_inet_port(local_server_addr
);
152 if (!info8
->local_server_name
) {
153 info8
->local_server_name
= info8
->local_server_addr
;
156 info8
->session_info
=
157 discard_const_p(struct auth_session_info_transport
,
161 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
164 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
165 state
, &state
->auth_req
,
166 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
167 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
168 tevent_req_error(req
, EINVAL
);
172 state
->auth_req_iov
.iov_base
= (char *) state
->auth_req_blob
.data
;
173 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
175 subreq
= tstream_unix_connect_send(state
,
179 if (tevent_req_nomem(subreq
, req
)) {
182 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
187 tevent_req_post(req
, ev
);
191 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
193 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
195 struct tevent_req
*req
=
196 tevent_req_callback_data(subreq
,
198 struct tstream_npa_connect_state
*state
=
200 struct tstream_npa_connect_state
);
204 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
205 state
, &state
->unix_stream
);
208 tevent_req_error(req
, sys_errno
);
212 subreq
= tstream_writev_send(state
,
215 &state
->auth_req_iov
, 1);
216 if (tevent_req_nomem(subreq
, req
)) {
219 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
222 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
224 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
226 struct tevent_req
*req
=
227 tevent_req_callback_data(subreq
,
229 struct tstream_npa_connect_state
*state
=
231 struct tstream_npa_connect_state
);
235 ret
= tstream_writev_recv(subreq
, &sys_errno
);
238 tevent_req_error(req
, sys_errno
);
242 subreq
= tstream_u32_read_send(
243 state
, state
->caller
.ev
, 0x00FFFFFF, state
->unix_stream
);
244 if (tevent_req_nomem(subreq
, req
)) {
247 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
250 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
252 struct tevent_req
*req
=
253 tevent_req_callback_data(subreq
,
255 struct tstream_npa_connect_state
*state
=
257 struct tstream_npa_connect_state
);
260 enum ndr_err_code ndr_err
;
262 err
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
264 if (tevent_req_error(req
, err
)) {
268 DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in
.length
);
269 dump_data(11, in
.data
, in
.length
);
271 ndr_err
= ndr_pull_struct_blob_all(
275 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
277 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
278 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
279 ndr_map_error2string(ndr_err
)));
280 tevent_req_error(req
, EIO
);
285 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
288 if (state
->auth_rep
.length
< 16) {
289 DEBUG(0, ("req invalid length: %u < 16\n",
290 state
->auth_rep
.length
));
291 tevent_req_error(req
, EIO
);
295 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
296 DEBUG(0, ("req invalid magic: %s != %s\n",
297 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
298 tevent_req_error(req
, EIO
);
302 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
303 DEBUG(0, ("req failed: %s\n",
304 nt_errstr(state
->auth_rep
.status
)));
305 tevent_req_error(req
, EACCES
);
309 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
310 DEBUG(0, ("req invalid level: %u != %u\n",
311 state
->auth_rep
.level
, state
->auth_req
.level
));
312 tevent_req_error(req
, EIO
);
316 tevent_req_done(req
);
319 int _tstream_npa_connect_recv(struct tevent_req
*req
,
322 struct tstream_context
**_stream
,
323 uint16_t *_file_type
,
324 uint16_t *_device_state
,
325 uint64_t *_allocation_size
,
326 const char *location
)
328 struct tstream_npa_connect_state
*state
=
330 struct tstream_npa_connect_state
);
331 struct tstream_context
*stream
;
332 struct tstream_npa
*npas
;
333 uint16_t device_state
= 0;
334 uint64_t allocation_size
= 0;
336 if (tevent_req_is_unix_error(req
, perrno
)) {
337 tevent_req_received(req
);
341 stream
= tstream_context_create(mem_ctx
,
348 tevent_req_received(req
);
353 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
354 switch (state
->auth_rep
.level
) {
356 npas
->file_type
= state
->auth_rep
.info
.info8
.file_type
;
357 device_state
= state
->auth_rep
.info
.info8
.device_state
;
358 allocation_size
= state
->auth_rep
.info
.info8
.allocation_size
;
363 *_file_type
= npas
->file_type
;
364 *_device_state
= device_state
;
365 *_allocation_size
= allocation_size
;
366 tevent_req_received(req
);
370 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
372 struct tstream_npa
*npas
= tstream_context_data(stream
,
376 if (!npas
->unix_stream
) {
381 switch (npas
->file_type
) {
382 case FILE_TYPE_BYTE_MODE_PIPE
:
383 ret
= tstream_pending_bytes(npas
->unix_stream
);
386 case FILE_TYPE_MESSAGE_MODE_PIPE
:
387 ret
= npas
->pending
.iov_len
;
397 struct tstream_npa_readv_state
{
398 struct tstream_context
*stream
;
400 struct iovec
*vector
;
403 /* the header for message mode */
410 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
411 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
414 struct iovec
**_vector
,
416 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
418 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
419 struct tevent_context
*ev
,
420 struct tstream_context
*stream
,
421 struct iovec
*vector
,
424 struct tevent_req
*req
;
425 struct tstream_npa_readv_state
*state
;
426 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
427 struct tevent_req
*subreq
;
432 req
= tevent_req_create(mem_ctx
, &state
,
433 struct tstream_npa_readv_state
);
438 state
->stream
= stream
;
441 if (!npas
->unix_stream
) {
442 tevent_req_error(req
, ENOTCONN
);
446 switch (npas
->file_type
) {
447 case FILE_TYPE_BYTE_MODE_PIPE
:
448 state
->vector
= vector
;
449 state
->count
= count
;
451 subreq
= tstream_readv_send(state
,
456 if (tevent_req_nomem(subreq
,req
)) {
459 tevent_req_set_callback(subreq
,
460 tstream_npa_readv_byte_mode_handler
,
465 case FILE_TYPE_MESSAGE_MODE_PIPE
:
467 * we make a copy of the vector and prepend a header
470 state
->vector
= talloc_array(state
, struct iovec
, count
);
471 if (tevent_req_nomem(state
->vector
, req
)) {
474 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
475 state
->count
= count
;
478 * copy the pending buffer first
481 left
= npas
->pending
.iov_len
;
482 pbase
= (uint8_t *)npas
->pending
.iov_base
;
484 while (left
> 0 && state
->count
> 0) {
486 base
= (uint8_t *)state
->vector
[0].iov_base
;
487 if (left
< state
->vector
[0].iov_len
) {
488 memcpy(base
, pbase
+ ofs
, left
);
491 state
->vector
[0].iov_base
= (char *) base
;
492 state
->vector
[0].iov_len
-= left
;
497 ZERO_STRUCT(npas
->pending
);
500 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
502 ofs
+= state
->vector
[0].iov_len
;
503 left
-= state
->vector
[0].iov_len
;
509 ZERO_STRUCT(npas
->pending
);
515 memmove(pbase
, pbase
+ ofs
, left
);
516 npas
->pending
.iov_base
= (char *) pbase
;
517 npas
->pending
.iov_len
= left
;
519 * this cannot fail and even if it
520 * fails we can handle it
522 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
524 npas
->pending
.iov_base
= (char *) pbase
;
531 if (state
->count
== 0) {
532 tevent_req_done(req
);
536 ZERO_STRUCT(state
->hdr
);
537 state
->wait_for_hdr
= false;
539 subreq
= tstream_readv_pdu_send(state
,
542 tstream_npa_readv_next_vector
,
544 if (tevent_req_nomem(subreq
, req
)) {
547 tevent_req_set_callback(subreq
,
548 tstream_npa_readv_msg_mode_handler
,
554 /* this can't happen */
555 tevent_req_error(req
, EINVAL
);
559 tevent_req_post(req
, ev
);
563 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
565 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
567 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
568 struct tstream_npa_readv_state
);
572 ret
= tstream_readv_recv(subreq
, &sys_errno
);
575 tevent_req_error(req
, sys_errno
);
581 tevent_req_done(req
);
584 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
587 struct iovec
**_vector
,
590 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
591 struct tstream_npa_readv_state
);
592 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
594 struct iovec
*vector
;
599 if (state
->count
== 0) {
605 if (!state
->wait_for_hdr
) {
606 /* we need to get a message header */
607 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
611 ZERO_STRUCT(state
->hdr
);
612 vector
[0].iov_base
= (char *) state
->hdr
;
613 vector
[0].iov_len
= sizeof(state
->hdr
);
617 state
->wait_for_hdr
= true;
624 /* and now fill the callers buffers and maybe the pending buffer */
625 state
->wait_for_hdr
= false;
627 msg_len
= SVAL(state
->hdr
, 0);
634 state
->wait_for_hdr
= false;
636 /* +1 because we may need to fill the pending buffer */
637 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
644 while (left
> 0 && state
->count
> 0) {
645 if (left
< state
->vector
[0].iov_len
) {
647 base
= (uint8_t *)state
->vector
[0].iov_base
;
648 vector
[count
].iov_base
= (char *) base
;
649 vector
[count
].iov_len
= left
;
652 state
->vector
[0].iov_base
= (char *) base
;
653 state
->vector
[0].iov_len
-= left
;
656 vector
[count
] = state
->vector
[0];
658 left
-= state
->vector
[0].iov_len
;
665 * if the message is longer than the buffers the caller
666 * requested, we need to consume the rest of the message
667 * into the pending buffer, where the next readv can
670 npas
->pending
.iov_base
= talloc_array(npas
, char, left
);
671 if (!npas
->pending
.iov_base
) {
674 npas
->pending
.iov_len
= left
;
676 vector
[count
] = npas
->pending
;
680 state
->ret
+= (msg_len
- left
);
687 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
689 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
694 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
697 tevent_req_error(req
, sys_errno
);
702 * we do not set state->ret here as ret includes the header size.
703 * we set it in tstream_npa_readv_pdu_next_vector()
706 tevent_req_done(req
);
709 static int tstream_npa_readv_recv(struct tevent_req
*req
,
712 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
713 struct tstream_npa_readv_state
);
716 ret
= tsocket_simple_int_recv(req
, perrno
);
721 tevent_req_received(req
);
725 struct tstream_npa_writev_state
{
726 const struct iovec
*vector
;
729 /* the header for message mode */
736 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
738 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
739 struct tevent_context
*ev
,
740 struct tstream_context
*stream
,
741 const struct iovec
*vector
,
744 struct tevent_req
*req
;
745 struct tstream_npa_writev_state
*state
;
746 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
747 struct tevent_req
*subreq
;
750 struct iovec
*new_vector
;
752 req
= tevent_req_create(mem_ctx
, &state
,
753 struct tstream_npa_writev_state
);
760 if (!npas
->unix_stream
) {
761 tevent_req_error(req
, ENOTCONN
);
765 switch (npas
->file_type
) {
766 case FILE_TYPE_BYTE_MODE_PIPE
:
767 state
->hdr_used
= false;
768 state
->vector
= vector
;
769 state
->count
= count
;
772 case FILE_TYPE_MESSAGE_MODE_PIPE
:
774 * we make a copy of the vector and prepend a header
777 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
778 if (tevent_req_nomem(new_vector
, req
)) {
781 new_vector
[0].iov_base
= (char *) state
->hdr
;
782 new_vector
[0].iov_len
= sizeof(state
->hdr
);
783 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
785 state
->hdr_used
= true;
786 state
->vector
= new_vector
;
787 state
->count
= count
+ 1;
790 for (i
=0; i
< count
; i
++) {
792 * overflow check already done in tstream_writev_send
794 msg_len
+= vector
[i
].iov_len
;
797 if (msg_len
> UINT16_MAX
) {
798 tevent_req_error(req
, EMSGSIZE
);
802 SSVAL(state
->hdr
, 0, msg_len
);
806 subreq
= tstream_writev_send(state
,
811 if (tevent_req_nomem(subreq
, req
)) {
814 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
819 tevent_req_post(req
, ev
);
823 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
825 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
827 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
828 struct tstream_npa_writev_state
);
832 ret
= tstream_writev_recv(subreq
, &sys_errno
);
835 tevent_req_error(req
, sys_errno
);
840 * in message mode we need to hide the length
841 * of the hdr from the caller
843 if (state
->hdr_used
) {
844 ret
-= sizeof(state
->hdr
);
849 tevent_req_done(req
);
852 static int tstream_npa_writev_recv(struct tevent_req
*req
,
855 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
856 struct tstream_npa_writev_state
);
859 ret
= tsocket_simple_int_recv(req
, perrno
);
864 tevent_req_received(req
);
868 struct tstream_npa_disconnect_state
{
869 struct tstream_context
*stream
;
872 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
874 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
875 struct tevent_context
*ev
,
876 struct tstream_context
*stream
)
878 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
879 struct tevent_req
*req
;
880 struct tstream_npa_disconnect_state
*state
;
881 struct tevent_req
*subreq
;
883 req
= tevent_req_create(mem_ctx
, &state
,
884 struct tstream_npa_disconnect_state
);
889 state
->stream
= stream
;
891 if (!npas
->unix_stream
) {
892 tevent_req_error(req
, ENOTCONN
);
896 subreq
= tstream_disconnect_send(state
,
899 if (tevent_req_nomem(subreq
, req
)) {
902 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
907 tevent_req_post(req
, ev
);
911 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
913 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
915 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
916 struct tstream_npa_disconnect_state
);
917 struct tstream_context
*stream
= state
->stream
;
918 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
922 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
925 tevent_req_error(req
, sys_errno
);
929 TALLOC_FREE(npas
->unix_stream
);
931 tevent_req_done(req
);
934 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
939 ret
= tsocket_simple_int_recv(req
, perrno
);
941 tevent_req_received(req
);
945 static const struct tstream_context_ops tstream_npa_ops
= {
948 .pending_bytes
= tstream_npa_pending_bytes
,
950 .readv_send
= tstream_npa_readv_send
,
951 .readv_recv
= tstream_npa_readv_recv
,
953 .writev_send
= tstream_npa_writev_send
,
954 .writev_recv
= tstream_npa_writev_recv
,
956 .disconnect_send
= tstream_npa_disconnect_send
,
957 .disconnect_recv
= tstream_npa_disconnect_recv
,
960 int _tstream_npa_existing_stream(TALLOC_CTX
*mem_ctx
,
961 struct tstream_context
**transport
,
963 struct tstream_context
**_stream
,
964 const char *location
)
966 struct tstream_context
*stream
;
967 struct tstream_npa
*npas
;
970 case FILE_TYPE_BYTE_MODE_PIPE
:
972 case FILE_TYPE_MESSAGE_MODE_PIPE
:
979 stream
= tstream_context_create(mem_ctx
,
988 *npas
= (struct tstream_npa
) {
989 .file_type
= file_type
,
990 .unix_stream
= talloc_move(npas
, transport
),
997 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1000 struct tstream_context
**_stream
,
1001 const char *location
)
1003 struct tstream_context
*transport
= NULL
;
1006 ret
= _tstream_bsd_existing_socket(
1007 mem_ctx
, fd
, &transport
, location
);
1011 /* as server we want to fail early */
1012 tstream_bsd_fail_readv_first_error(transport
, true);
1013 return _tstream_npa_existing_stream(
1014 mem_ctx
, &transport
, file_type
, _stream
, location
);
1017 struct tstream_npa_accept_state
{
1018 struct tevent_context
*ev
;
1019 struct tstream_context
*plain
;
1021 uint16_t device_state
;
1022 uint64_t alloc_size
;
1024 struct named_pipe_auth_req
*pipe_request
;
1027 struct iovec out_iov
;
1030 NTSTATUS accept_status
;
1031 struct tsocket_address
*remote_client_addr
;
1032 struct tsocket_address
*local_server_addr
;
1035 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1036 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1038 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1039 struct tevent_context
*ev
,
1040 struct tstream_context
*plain
,
1042 uint16_t device_state
,
1043 uint64_t allocation_size
)
1045 struct tstream_npa_accept_state
*state
;
1046 struct tevent_req
*req
, *subreq
;
1048 req
= tevent_req_create(mem_ctx
, &state
,
1049 struct tstream_npa_accept_state
);
1054 switch (file_type
) {
1055 case FILE_TYPE_BYTE_MODE_PIPE
:
1057 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1060 tevent_req_error(req
, EINVAL
);
1065 state
->plain
= plain
;
1066 state
->file_type
= file_type
;
1067 state
->device_state
= device_state
;
1068 state
->alloc_size
= allocation_size
;
1070 subreq
= tstream_u32_read_send(state
, ev
, 0x00FFFFFF, plain
);
1071 if (tevent_req_nomem(subreq
, req
)) {
1075 tevent_req_set_callback(subreq
,
1076 tstream_npa_accept_existing_reply
, req
);
1081 tevent_req_post(req
, ev
);
1085 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1087 struct tevent_req
*req
=
1088 tevent_req_callback_data(subreq
, struct tevent_req
);
1089 struct tstream_npa_accept_state
*state
=
1090 tevent_req_data(req
, struct tstream_npa_accept_state
);
1091 struct named_pipe_auth_req
*pipe_request
;
1092 struct named_pipe_auth_rep pipe_reply
;
1093 struct named_pipe_auth_req_info8 i8
;
1094 enum ndr_err_code ndr_err
;
1099 err
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
1101 tevent_req_error(req
, err
);
1104 if (in
.length
< 8) {
1105 tevent_req_error(req
, EMSGSIZE
);
1109 if (memcmp(&in
.data
[4], NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1110 DBG_ERR("Wrong protocol\n");
1111 #if defined(EPROTONOSUPPORT)
1112 err
= EPROTONOSUPPORT
;
1113 #elif defined(EPROTO)
1118 tevent_req_error(req
, err
);
1122 DBG_DEBUG("Received packet of length %zu\n", in
.length
);
1123 dump_data(11, in
.data
, in
.length
);
1125 ZERO_STRUCT(pipe_reply
);
1126 pipe_reply
.level
= 0;
1127 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1129 * TODO: check it's a root (uid == 0) pipe
1132 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1133 if (!pipe_request
) {
1134 DEBUG(0, ("Out of memory!\n"));
1137 state
->pipe_request
= pipe_request
;
1139 /* parse the passed credentials */
1140 ndr_err
= ndr_pull_struct_blob_all(
1144 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1145 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1146 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1147 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1148 nt_errstr(pipe_reply
.status
)));
1153 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1158 if (pipe_request
->level
!= 8) {
1159 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1160 pipe_reply
.level
= 0;
1161 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1165 pipe_reply
.level
= 8;
1166 pipe_reply
.status
= NT_STATUS_OK
;
1167 pipe_reply
.info
.info8
.file_type
= state
->file_type
;
1168 pipe_reply
.info
.info8
.device_state
= state
->device_state
;
1169 pipe_reply
.info
.info8
.allocation_size
= state
->alloc_size
;
1171 i8
= pipe_request
->info
.info8
;
1172 if (i8
.local_server_addr
== NULL
) {
1173 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1174 DEBUG(2, ("Missing local server address\n"));
1177 if (i8
.remote_client_addr
== NULL
) {
1178 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1179 DEBUG(2, ("Missing remote client address\n"));
1183 ret
= tsocket_address_inet_from_strings(state
,
1185 i8
.local_server_addr
,
1186 i8
.local_server_port
,
1187 &state
->local_server_addr
);
1190 ("Invalid local server address[%s:%u] - %s\n",
1191 i8
.local_server_addr
,
1192 i8
.local_server_port
,
1194 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1198 ret
= tsocket_address_inet_from_strings(state
,
1200 i8
.remote_client_addr
,
1201 i8
.remote_client_port
,
1202 &state
->remote_client_addr
);
1205 ("Invalid remote client address[%s:%u] - %s\n",
1206 i8
.remote_client_addr
,
1207 i8
.remote_client_port
,
1209 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1214 /* create the output */
1215 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1216 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1217 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1218 DEBUG(2, ("Error encoding structure: %s\n",
1219 ndr_map_error2string(ndr_err
)));
1220 tevent_req_error(req
, EIO
);
1224 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1225 dump_data(11, out
.data
, out
.length
);
1228 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1231 state
->accept_status
= pipe_reply
.status
;
1233 state
->out_iov
.iov_base
= (char *) out
.data
;
1234 state
->out_iov
.iov_len
= out
.length
;
1236 subreq
= tstream_writev_send(state
, state
->ev
,
1238 &state
->out_iov
, 1);
1239 if (tevent_req_nomem(subreq
, req
)) {
1240 DEBUG(0, ("no memory for tstream_writev_send\n"));
1244 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1247 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1249 struct tevent_req
*req
=
1250 tevent_req_callback_data(subreq
, struct tevent_req
);
1254 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1255 TALLOC_FREE(subreq
);
1257 tevent_req_error(req
, sys_errno
);
1261 tevent_req_done(req
);
1264 static struct named_pipe_auth_req_info8
*
1265 copy_npa_info8(TALLOC_CTX
*mem_ctx
,
1266 const struct named_pipe_auth_req_info8
*src
)
1268 struct named_pipe_auth_req_info8
*dst
= NULL
;
1270 enum ndr_err_code ndr_err
;
1272 dst
= talloc_zero(mem_ctx
, struct named_pipe_auth_req_info8
);
1277 ndr_err
= ndr_push_struct_blob(
1281 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req_info8
);
1282 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1283 DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1284 ndr_errstr(ndr_err
));
1289 ndr_err
= ndr_pull_struct_blob_all(
1293 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req_info8
);
1294 TALLOC_FREE(blob
.data
);
1295 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1296 DBG_WARNING("ndr_push_named_pipe_auth_req_info8 failed: %s\n",
1297 ndr_errstr(ndr_err
));
1305 int _tstream_npa_accept_existing_recv(
1306 struct tevent_req
*req
,
1308 TALLOC_CTX
*mem_ctx
,
1309 struct tstream_context
**stream
,
1310 struct named_pipe_auth_req_info8
**info8
,
1311 enum dcerpc_transport_t
*transport
,
1312 struct tsocket_address
**remote_client_addr
,
1313 char **_remote_client_name
,
1314 struct tsocket_address
**local_server_addr
,
1315 char **local_server_name
,
1316 struct auth_session_info_transport
**session_info
,
1317 const char *location
)
1319 struct tstream_npa_accept_state
*state
=
1320 tevent_req_data(req
, struct tstream_npa_accept_state
);
1321 struct named_pipe_auth_req_info8
*i8
=
1322 &state
->pipe_request
->info
.info8
;
1323 struct tstream_npa
*npas
;
1326 ret
= tsocket_simple_int_recv(req
, perrno
);
1328 DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1329 strerror(*perrno
)));
1330 tevent_req_received(req
);
1334 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1335 #if defined(EPROTONOSUPPORT)
1336 *perrno
= EPROTONOSUPPORT
;
1337 #elif defined(EPROTO)
1342 DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1343 nt_errstr(state
->accept_status
),
1344 strerror(*perrno
)));
1345 tevent_req_received(req
);
1349 *stream
= tstream_context_create(mem_ctx
,
1356 tevent_req_received(req
);
1360 npas
->unix_stream
= state
->plain
;
1361 npas
->file_type
= state
->file_type
;
1363 if (info8
!= NULL
) {
1365 * Make a full copy of "info8" because further down we
1366 * talloc_move() away substructures from
1367 * state->pipe_request.
1369 struct named_pipe_auth_req_info8
*dst
=
1370 copy_npa_info8(mem_ctx
, i8
);
1373 tevent_req_received(req
);
1379 if (transport
!= NULL
) {
1380 *transport
= i8
->transport
;
1382 if (remote_client_addr
!= NULL
) {
1383 *remote_client_addr
= talloc_move(
1384 mem_ctx
, &state
->remote_client_addr
);
1386 if (_remote_client_name
!= NULL
) {
1387 *_remote_client_name
= discard_const_p(
1389 talloc_move(mem_ctx
, &i8
->remote_client_name
));
1391 if (local_server_addr
!= NULL
) {
1392 *local_server_addr
= talloc_move(
1393 mem_ctx
, &state
->local_server_addr
);
1395 if (local_server_name
!= NULL
) {
1396 *local_server_name
= discard_const_p(
1398 talloc_move(mem_ctx
, &i8
->local_server_name
));
1400 if (session_info
!= NULL
) {
1401 *session_info
= talloc_move(mem_ctx
, &i8
->session_info
);
1404 tevent_req_received(req
);