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_info5
*info5
;
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
= 5;
123 info5
= &state
->auth_req
.info
.info5
;
125 info5
->transport
= transport
;
126 SMB_ASSERT(info5
->transport
== transport
); /* Assert no overflow */
128 info5
->remote_client_name
= remote_client_name_in
;
129 info5
->remote_client_addr
= tsocket_address_inet_addr_string(remote_client_addr
,
131 if (!info5
->remote_client_addr
) {
132 /* errno might be EINVAL */
133 tevent_req_error(req
, errno
);
136 info5
->remote_client_port
= tsocket_address_inet_port(remote_client_addr
);
137 if (!info5
->remote_client_name
) {
138 info5
->remote_client_name
= info5
->remote_client_addr
;
141 info5
->local_server_name
= local_server_name_in
;
142 info5
->local_server_addr
= tsocket_address_inet_addr_string(local_server_addr
,
144 if (!info5
->local_server_addr
) {
145 /* errno might be EINVAL */
146 tevent_req_error(req
, errno
);
149 info5
->local_server_port
= tsocket_address_inet_port(local_server_addr
);
150 if (!info5
->local_server_name
) {
151 info5
->local_server_name
= info5
->local_server_addr
;
154 info5
->session_info
= discard_const_p(struct auth_session_info_transport
, session_info
);
157 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
160 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
161 state
, &state
->auth_req
,
162 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
163 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
164 tevent_req_error(req
, EINVAL
);
168 state
->auth_req_iov
.iov_base
= (char *) state
->auth_req_blob
.data
;
169 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
171 subreq
= tstream_unix_connect_send(state
,
175 if (tevent_req_nomem(subreq
, req
)) {
178 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
183 tevent_req_post(req
, ev
);
187 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
189 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
191 struct tevent_req
*req
=
192 tevent_req_callback_data(subreq
,
194 struct tstream_npa_connect_state
*state
=
196 struct tstream_npa_connect_state
);
200 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
201 state
, &state
->unix_stream
);
204 tevent_req_error(req
, sys_errno
);
208 subreq
= tstream_writev_send(state
,
211 &state
->auth_req_iov
, 1);
212 if (tevent_req_nomem(subreq
, req
)) {
215 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
218 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
220 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
222 struct tevent_req
*req
=
223 tevent_req_callback_data(subreq
,
225 struct tstream_npa_connect_state
*state
=
227 struct tstream_npa_connect_state
);
231 ret
= tstream_writev_recv(subreq
, &sys_errno
);
234 tevent_req_error(req
, sys_errno
);
238 subreq
= tstream_u32_read_send(
239 state
, state
->caller
.ev
, 0x00FFFFFF, state
->unix_stream
);
240 if (tevent_req_nomem(subreq
, req
)) {
243 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
246 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
248 struct tevent_req
*req
=
249 tevent_req_callback_data(subreq
,
251 struct tstream_npa_connect_state
*state
=
253 struct tstream_npa_connect_state
);
256 enum ndr_err_code ndr_err
;
258 err
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
260 if (tevent_req_error(req
, err
)) {
264 DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in
.length
);
265 dump_data(11, in
.data
, in
.length
);
267 ndr_err
= ndr_pull_struct_blob_all(
271 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
273 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
274 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
275 ndr_map_error2string(ndr_err
)));
276 tevent_req_error(req
, EIO
);
281 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
284 if (state
->auth_rep
.length
< 16) {
285 DEBUG(0, ("req invalid length: %u < 16\n",
286 state
->auth_rep
.length
));
287 tevent_req_error(req
, EIO
);
291 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
292 DEBUG(0, ("req invalid magic: %s != %s\n",
293 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
294 tevent_req_error(req
, EIO
);
298 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
299 DEBUG(0, ("req failed: %s\n",
300 nt_errstr(state
->auth_rep
.status
)));
301 tevent_req_error(req
, EACCES
);
305 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
306 DEBUG(0, ("req invalid level: %u != %u\n",
307 state
->auth_rep
.level
, state
->auth_req
.level
));
308 tevent_req_error(req
, EIO
);
312 tevent_req_done(req
);
315 int _tstream_npa_connect_recv(struct tevent_req
*req
,
318 struct tstream_context
**_stream
,
319 uint16_t *_file_type
,
320 uint16_t *_device_state
,
321 uint64_t *_allocation_size
,
322 const char *location
)
324 struct tstream_npa_connect_state
*state
=
326 struct tstream_npa_connect_state
);
327 struct tstream_context
*stream
;
328 struct tstream_npa
*npas
;
329 uint16_t device_state
= 0;
330 uint64_t allocation_size
= 0;
332 if (tevent_req_is_unix_error(req
, perrno
)) {
333 tevent_req_received(req
);
337 stream
= tstream_context_create(mem_ctx
,
344 tevent_req_received(req
);
349 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
350 switch (state
->auth_rep
.level
) {
352 npas
->file_type
= state
->auth_rep
.info
.info5
.file_type
;
353 device_state
= state
->auth_rep
.info
.info5
.device_state
;
354 allocation_size
= state
->auth_rep
.info
.info5
.allocation_size
;
359 *_file_type
= npas
->file_type
;
360 *_device_state
= device_state
;
361 *_allocation_size
= allocation_size
;
362 tevent_req_received(req
);
366 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
368 struct tstream_npa
*npas
= tstream_context_data(stream
,
372 if (!npas
->unix_stream
) {
377 switch (npas
->file_type
) {
378 case FILE_TYPE_BYTE_MODE_PIPE
:
379 ret
= tstream_pending_bytes(npas
->unix_stream
);
382 case FILE_TYPE_MESSAGE_MODE_PIPE
:
383 ret
= npas
->pending
.iov_len
;
393 struct tstream_npa_readv_state
{
394 struct tstream_context
*stream
;
396 struct iovec
*vector
;
399 /* the header for message mode */
406 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
407 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
410 struct iovec
**_vector
,
412 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
414 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
415 struct tevent_context
*ev
,
416 struct tstream_context
*stream
,
417 struct iovec
*vector
,
420 struct tevent_req
*req
;
421 struct tstream_npa_readv_state
*state
;
422 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
423 struct tevent_req
*subreq
;
428 req
= tevent_req_create(mem_ctx
, &state
,
429 struct tstream_npa_readv_state
);
434 state
->stream
= stream
;
437 if (!npas
->unix_stream
) {
438 tevent_req_error(req
, ENOTCONN
);
442 switch (npas
->file_type
) {
443 case FILE_TYPE_BYTE_MODE_PIPE
:
444 state
->vector
= vector
;
445 state
->count
= count
;
447 subreq
= tstream_readv_send(state
,
452 if (tevent_req_nomem(subreq
,req
)) {
455 tevent_req_set_callback(subreq
,
456 tstream_npa_readv_byte_mode_handler
,
461 case FILE_TYPE_MESSAGE_MODE_PIPE
:
463 * we make a copy of the vector and prepend a header
466 state
->vector
= talloc_array(state
, struct iovec
, count
);
467 if (tevent_req_nomem(state
->vector
, req
)) {
470 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
471 state
->count
= count
;
474 * copy the pending buffer first
477 left
= npas
->pending
.iov_len
;
478 pbase
= (uint8_t *)npas
->pending
.iov_base
;
480 while (left
> 0 && state
->count
> 0) {
482 base
= (uint8_t *)state
->vector
[0].iov_base
;
483 if (left
< state
->vector
[0].iov_len
) {
484 memcpy(base
, pbase
+ ofs
, left
);
487 state
->vector
[0].iov_base
= (char *) base
;
488 state
->vector
[0].iov_len
-= left
;
493 ZERO_STRUCT(npas
->pending
);
496 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
498 ofs
+= state
->vector
[0].iov_len
;
499 left
-= state
->vector
[0].iov_len
;
505 ZERO_STRUCT(npas
->pending
);
511 memmove(pbase
, pbase
+ ofs
, left
);
512 npas
->pending
.iov_base
= (char *) pbase
;
513 npas
->pending
.iov_len
= left
;
515 * this cannot fail and even if it
516 * fails we can handle it
518 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
520 npas
->pending
.iov_base
= (char *) pbase
;
527 if (state
->count
== 0) {
528 tevent_req_done(req
);
532 ZERO_STRUCT(state
->hdr
);
533 state
->wait_for_hdr
= false;
535 subreq
= tstream_readv_pdu_send(state
,
538 tstream_npa_readv_next_vector
,
540 if (tevent_req_nomem(subreq
, req
)) {
543 tevent_req_set_callback(subreq
,
544 tstream_npa_readv_msg_mode_handler
,
550 /* this can't happen */
551 tevent_req_error(req
, EINVAL
);
555 tevent_req_post(req
, ev
);
559 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
561 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
563 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
564 struct tstream_npa_readv_state
);
568 ret
= tstream_readv_recv(subreq
, &sys_errno
);
571 tevent_req_error(req
, sys_errno
);
577 tevent_req_done(req
);
580 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
583 struct iovec
**_vector
,
586 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
587 struct tstream_npa_readv_state
);
588 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
590 struct iovec
*vector
;
595 if (state
->count
== 0) {
601 if (!state
->wait_for_hdr
) {
602 /* we need to get a message header */
603 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
607 ZERO_STRUCT(state
->hdr
);
608 vector
[0].iov_base
= (char *) state
->hdr
;
609 vector
[0].iov_len
= sizeof(state
->hdr
);
613 state
->wait_for_hdr
= true;
620 /* and now fill the callers buffers and maybe the pending buffer */
621 state
->wait_for_hdr
= false;
623 msg_len
= SVAL(state
->hdr
, 0);
630 state
->wait_for_hdr
= false;
632 /* +1 because we may need to fill the pending buffer */
633 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
640 while (left
> 0 && state
->count
> 0) {
641 if (left
< state
->vector
[0].iov_len
) {
643 base
= (uint8_t *)state
->vector
[0].iov_base
;
644 vector
[count
].iov_base
= (char *) base
;
645 vector
[count
].iov_len
= left
;
648 state
->vector
[0].iov_base
= (char *) base
;
649 state
->vector
[0].iov_len
-= left
;
652 vector
[count
] = state
->vector
[0];
654 left
-= state
->vector
[0].iov_len
;
661 * if the message is longer than the buffers the caller
662 * requested, we need to consume the rest of the message
663 * into the pending buffer, where the next readv can
666 npas
->pending
.iov_base
= talloc_array(npas
, char, left
);
667 if (!npas
->pending
.iov_base
) {
670 npas
->pending
.iov_len
= left
;
672 vector
[count
] = npas
->pending
;
676 state
->ret
+= (msg_len
- left
);
683 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
685 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
690 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
693 tevent_req_error(req
, sys_errno
);
698 * we do not set state->ret here as ret includes the header size.
699 * we set it in tstream_npa_readv_pdu_next_vector()
702 tevent_req_done(req
);
705 static int tstream_npa_readv_recv(struct tevent_req
*req
,
708 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
709 struct tstream_npa_readv_state
);
712 ret
= tsocket_simple_int_recv(req
, perrno
);
717 tevent_req_received(req
);
721 struct tstream_npa_writev_state
{
722 const struct iovec
*vector
;
725 /* the header for message mode */
732 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
734 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
735 struct tevent_context
*ev
,
736 struct tstream_context
*stream
,
737 const struct iovec
*vector
,
740 struct tevent_req
*req
;
741 struct tstream_npa_writev_state
*state
;
742 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
743 struct tevent_req
*subreq
;
746 struct iovec
*new_vector
;
748 req
= tevent_req_create(mem_ctx
, &state
,
749 struct tstream_npa_writev_state
);
756 if (!npas
->unix_stream
) {
757 tevent_req_error(req
, ENOTCONN
);
761 switch (npas
->file_type
) {
762 case FILE_TYPE_BYTE_MODE_PIPE
:
763 state
->hdr_used
= false;
764 state
->vector
= vector
;
765 state
->count
= count
;
768 case FILE_TYPE_MESSAGE_MODE_PIPE
:
770 * we make a copy of the vector and prepend a header
773 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
774 if (tevent_req_nomem(new_vector
, req
)) {
777 new_vector
[0].iov_base
= (char *) state
->hdr
;
778 new_vector
[0].iov_len
= sizeof(state
->hdr
);
779 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
781 state
->hdr_used
= true;
782 state
->vector
= new_vector
;
783 state
->count
= count
+ 1;
786 for (i
=0; i
< count
; i
++) {
788 * overflow check already done in tstream_writev_send
790 msg_len
+= vector
[i
].iov_len
;
793 if (msg_len
> UINT16_MAX
) {
794 tevent_req_error(req
, EMSGSIZE
);
798 SSVAL(state
->hdr
, 0, msg_len
);
802 subreq
= tstream_writev_send(state
,
807 if (tevent_req_nomem(subreq
, req
)) {
810 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
815 tevent_req_post(req
, ev
);
819 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
821 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
823 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
824 struct tstream_npa_writev_state
);
828 ret
= tstream_writev_recv(subreq
, &sys_errno
);
831 tevent_req_error(req
, sys_errno
);
836 * in message mode we need to hide the length
837 * of the hdr from the caller
839 if (state
->hdr_used
) {
840 ret
-= sizeof(state
->hdr
);
845 tevent_req_done(req
);
848 static int tstream_npa_writev_recv(struct tevent_req
*req
,
851 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
852 struct tstream_npa_writev_state
);
855 ret
= tsocket_simple_int_recv(req
, perrno
);
860 tevent_req_received(req
);
864 struct tstream_npa_disconnect_state
{
865 struct tstream_context
*stream
;
868 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
870 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
871 struct tevent_context
*ev
,
872 struct tstream_context
*stream
)
874 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
875 struct tevent_req
*req
;
876 struct tstream_npa_disconnect_state
*state
;
877 struct tevent_req
*subreq
;
879 req
= tevent_req_create(mem_ctx
, &state
,
880 struct tstream_npa_disconnect_state
);
885 state
->stream
= stream
;
887 if (!npas
->unix_stream
) {
888 tevent_req_error(req
, ENOTCONN
);
892 subreq
= tstream_disconnect_send(state
,
895 if (tevent_req_nomem(subreq
, req
)) {
898 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
903 tevent_req_post(req
, ev
);
907 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
909 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
911 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
912 struct tstream_npa_disconnect_state
);
913 struct tstream_context
*stream
= state
->stream
;
914 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
918 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
921 tevent_req_error(req
, sys_errno
);
925 TALLOC_FREE(npas
->unix_stream
);
927 tevent_req_done(req
);
930 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
935 ret
= tsocket_simple_int_recv(req
, perrno
);
937 tevent_req_received(req
);
941 static const struct tstream_context_ops tstream_npa_ops
= {
944 .pending_bytes
= tstream_npa_pending_bytes
,
946 .readv_send
= tstream_npa_readv_send
,
947 .readv_recv
= tstream_npa_readv_recv
,
949 .writev_send
= tstream_npa_writev_send
,
950 .writev_recv
= tstream_npa_writev_recv
,
952 .disconnect_send
= tstream_npa_disconnect_send
,
953 .disconnect_recv
= tstream_npa_disconnect_recv
,
956 int _tstream_npa_existing_stream(TALLOC_CTX
*mem_ctx
,
957 struct tstream_context
**transport
,
959 struct tstream_context
**_stream
,
960 const char *location
)
962 struct tstream_context
*stream
;
963 struct tstream_npa
*npas
;
966 case FILE_TYPE_BYTE_MODE_PIPE
:
968 case FILE_TYPE_MESSAGE_MODE_PIPE
:
975 stream
= tstream_context_create(mem_ctx
,
984 *npas
= (struct tstream_npa
) {
985 .file_type
= file_type
,
986 .unix_stream
= talloc_move(npas
, transport
),
993 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
996 struct tstream_context
**_stream
,
997 const char *location
)
999 struct tstream_context
*transport
= NULL
;
1002 ret
= _tstream_bsd_existing_socket(
1003 mem_ctx
, fd
, &transport
, location
);
1007 return _tstream_npa_existing_stream(
1008 mem_ctx
, &transport
, file_type
, _stream
, location
);
1011 struct tstream_npa_accept_state
{
1012 struct tevent_context
*ev
;
1013 struct tstream_context
*plain
;
1015 uint16_t device_state
;
1016 uint64_t alloc_size
;
1018 struct named_pipe_auth_req
*pipe_request
;
1021 struct iovec out_iov
;
1024 NTSTATUS accept_status
;
1025 struct tsocket_address
*remote_client_addr
;
1026 struct tsocket_address
*local_server_addr
;
1029 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1030 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1032 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1033 struct tevent_context
*ev
,
1034 struct tstream_context
*plain
,
1036 uint16_t device_state
,
1037 uint64_t allocation_size
)
1039 struct tstream_npa_accept_state
*state
;
1040 struct tevent_req
*req
, *subreq
;
1042 req
= tevent_req_create(mem_ctx
, &state
,
1043 struct tstream_npa_accept_state
);
1048 switch (file_type
) {
1049 case FILE_TYPE_BYTE_MODE_PIPE
:
1051 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1054 tevent_req_error(req
, EINVAL
);
1059 state
->plain
= plain
;
1060 state
->file_type
= file_type
;
1061 state
->device_state
= device_state
;
1062 state
->alloc_size
= allocation_size
;
1064 subreq
= tstream_u32_read_send(state
, ev
, 0x00FFFFFF, plain
);
1065 if (tevent_req_nomem(subreq
, req
)) {
1069 tevent_req_set_callback(subreq
,
1070 tstream_npa_accept_existing_reply
, req
);
1075 tevent_req_post(req
, ev
);
1079 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1081 struct tevent_req
*req
=
1082 tevent_req_callback_data(subreq
, struct tevent_req
);
1083 struct tstream_npa_accept_state
*state
=
1084 tevent_req_data(req
, struct tstream_npa_accept_state
);
1085 struct named_pipe_auth_req
*pipe_request
;
1086 struct named_pipe_auth_rep pipe_reply
;
1087 struct named_pipe_auth_req_info5 i5
;
1088 enum ndr_err_code ndr_err
;
1093 err
= tstream_u32_read_recv(subreq
, state
, &in
.data
, &in
.length
);
1095 tevent_req_error(req
, err
);
1098 if (in
.length
< 8) {
1099 tevent_req_error(req
, EMSGSIZE
);
1103 if (memcmp(&in
.data
[4], NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1104 DBG_ERR("Wrong protocol\n");
1105 #if defined(EPROTONOSUPPORT)
1106 err
= EPROTONOSUPPORT
;
1107 #elif defined(EPROTO)
1112 tevent_req_error(req
, err
);
1116 DBG_DEBUG("Received packet of length %zu\n", in
.length
);
1117 dump_data(11, in
.data
, in
.length
);
1119 ZERO_STRUCT(pipe_reply
);
1120 pipe_reply
.level
= 0;
1121 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1123 * TODO: check it's a root (uid == 0) pipe
1126 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1127 if (!pipe_request
) {
1128 DEBUG(0, ("Out of memory!\n"));
1131 state
->pipe_request
= pipe_request
;
1133 /* parse the passed credentials */
1134 ndr_err
= ndr_pull_struct_blob_all(
1138 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1139 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1140 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1141 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1142 nt_errstr(pipe_reply
.status
)));
1147 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1152 if (pipe_request
->level
!= 5) {
1153 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1154 pipe_reply
.level
= 0;
1155 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1159 pipe_reply
.level
= 5;
1160 pipe_reply
.status
= NT_STATUS_OK
;
1161 pipe_reply
.info
.info5
.file_type
= state
->file_type
;
1162 pipe_reply
.info
.info5
.device_state
= state
->device_state
;
1163 pipe_reply
.info
.info5
.allocation_size
= state
->alloc_size
;
1165 i5
= pipe_request
->info
.info5
;
1166 if (i5
.local_server_addr
== NULL
) {
1167 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1168 DEBUG(2, ("Missing local server address\n"));
1171 if (i5
.remote_client_addr
== NULL
) {
1172 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1173 DEBUG(2, ("Missing remote client address\n"));
1177 ret
= tsocket_address_inet_from_strings(state
, "ip",
1178 i5
.local_server_addr
,
1179 i5
.local_server_port
,
1180 &state
->local_server_addr
);
1182 DEBUG(2, ("Invalid local server address[%s:%u] - %s\n",
1183 i5
.local_server_addr
, i5
.local_server_port
,
1185 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1189 ret
= tsocket_address_inet_from_strings(state
, "ip",
1190 i5
.remote_client_addr
,
1191 i5
.remote_client_port
,
1192 &state
->remote_client_addr
);
1194 DEBUG(2, ("Invalid remote client address[%s:%u] - %s\n",
1195 i5
.remote_client_addr
, i5
.remote_client_port
,
1197 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1202 /* create the output */
1203 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1204 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1205 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1206 DEBUG(2, ("Error encoding structure: %s",
1207 ndr_map_error2string(ndr_err
)));
1208 tevent_req_error(req
, EIO
);
1212 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1213 dump_data(11, out
.data
, out
.length
);
1216 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1219 state
->accept_status
= pipe_reply
.status
;
1221 state
->out_iov
.iov_base
= (char *) out
.data
;
1222 state
->out_iov
.iov_len
= out
.length
;
1224 subreq
= tstream_writev_send(state
, state
->ev
,
1226 &state
->out_iov
, 1);
1227 if (tevent_req_nomem(subreq
, req
)) {
1228 DEBUG(0, ("no memory for tstream_writev_send"));
1232 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1235 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1237 struct tevent_req
*req
=
1238 tevent_req_callback_data(subreq
, struct tevent_req
);
1242 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1243 TALLOC_FREE(subreq
);
1245 tevent_req_error(req
, sys_errno
);
1249 tevent_req_done(req
);
1252 static struct named_pipe_auth_req_info5
*copy_npa_info5(
1253 TALLOC_CTX
*mem_ctx
, const struct named_pipe_auth_req_info5
*src
)
1255 struct named_pipe_auth_req_info5
*dst
= NULL
;
1257 enum ndr_err_code ndr_err
;
1259 dst
= talloc_zero(mem_ctx
, struct named_pipe_auth_req_info5
);
1264 ndr_err
= ndr_push_struct_blob(
1268 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req_info5
);
1269 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1270 DBG_WARNING("ndr_push_named_pipe_auth_req_info5 failed: %s\n",
1271 ndr_errstr(ndr_err
));
1276 ndr_err
= ndr_pull_struct_blob_all(
1280 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req_info5
);
1281 TALLOC_FREE(blob
.data
);
1282 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1283 DBG_WARNING("ndr_push_named_pipe_auth_req_info5 failed: %s\n",
1284 ndr_errstr(ndr_err
));
1292 int _tstream_npa_accept_existing_recv(
1293 struct tevent_req
*req
,
1295 TALLOC_CTX
*mem_ctx
,
1296 struct tstream_context
**stream
,
1297 struct named_pipe_auth_req_info5
**info5
,
1298 enum dcerpc_transport_t
*transport
,
1299 struct tsocket_address
**remote_client_addr
,
1300 char **_remote_client_name
,
1301 struct tsocket_address
**local_server_addr
,
1302 char **local_server_name
,
1303 struct auth_session_info_transport
**session_info
,
1304 const char *location
)
1306 struct tstream_npa_accept_state
*state
=
1307 tevent_req_data(req
, struct tstream_npa_accept_state
);
1308 struct named_pipe_auth_req_info5
*i5
= &state
->pipe_request
->info
.info5
;
1309 struct tstream_npa
*npas
;
1312 ret
= tsocket_simple_int_recv(req
, perrno
);
1314 DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1315 strerror(*perrno
)));
1316 tevent_req_received(req
);
1320 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1321 #if defined(EPROTONOSUPPORT)
1322 *perrno
= EPROTONOSUPPORT
;
1323 #elif defined(EPROTO)
1328 DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1329 nt_errstr(state
->accept_status
),
1330 strerror(*perrno
)));
1331 tevent_req_received(req
);
1335 *stream
= tstream_context_create(mem_ctx
,
1342 tevent_req_received(req
);
1346 npas
->unix_stream
= state
->plain
;
1347 npas
->file_type
= state
->file_type
;
1349 if (info5
!= NULL
) {
1351 * Make a full copy of "info5" because further down we
1352 * talloc_move() away substructures from
1353 * state->pipe_request.
1355 struct named_pipe_auth_req_info5
*dst
= copy_npa_info5(
1359 tevent_req_received(req
);
1365 if (transport
!= NULL
) {
1366 *transport
= i5
->transport
;
1368 if (remote_client_addr
!= NULL
) {
1369 *remote_client_addr
= talloc_move(
1370 mem_ctx
, &state
->remote_client_addr
);
1372 if (_remote_client_name
!= NULL
) {
1373 *_remote_client_name
= discard_const_p(
1374 char, talloc_move(mem_ctx
, &i5
->remote_client_name
));
1376 if (local_server_addr
!= NULL
) {
1377 *local_server_addr
= talloc_move(
1378 mem_ctx
, &state
->local_server_addr
);
1380 if (local_server_name
!= NULL
) {
1381 *local_server_name
= discard_const_p(
1382 char, talloc_move(mem_ctx
, &i5
->local_server_name
));
1384 if (session_info
!= NULL
) {
1385 *session_info
= talloc_move(mem_ctx
, &i5
->session_info
);
1388 tevent_req_received(req
);