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
*remote_client_addr
,
64 const char *remote_client_name_in
,
65 const struct tsocket_address
*local_server_addr
,
66 const char *local_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
);
116 if (!local_server_addr
) {
117 tevent_req_error(req
, EINVAL
);
121 state
->auth_req
.level
= 4;
122 info4
= &state
->auth_req
.info
.info4
;
124 info4
->remote_client_name
= remote_client_name_in
;
125 info4
->remote_client_addr
= tsocket_address_inet_addr_string(remote_client_addr
,
127 if (!info4
->remote_client_addr
) {
128 /* errno might be EINVAL */
129 tevent_req_error(req
, errno
);
132 info4
->remote_client_port
= tsocket_address_inet_port(remote_client_addr
);
133 if (!info4
->remote_client_name
) {
134 info4
->remote_client_name
= info4
->remote_client_addr
;
137 info4
->local_server_addr
= tsocket_address_inet_addr_string(local_server_addr
,
139 if (!info4
->local_server_addr
) {
140 /* errno might be EINVAL */
141 tevent_req_error(req
, errno
);
144 info4
->local_server_port
= tsocket_address_inet_port(local_server_addr
);
145 if (!info4
->local_server_name
) {
146 info4
->local_server_name
= info4
->local_server_addr
;
149 info4
->session_info
= discard_const_p(struct auth_session_info_transport
, session_info
);
152 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
155 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
156 state
, &state
->auth_req
,
157 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
158 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
159 tevent_req_error(req
, EINVAL
);
163 state
->auth_req_iov
.iov_base
= (char *) state
->auth_req_blob
.data
;
164 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
166 subreq
= tstream_unix_connect_send(state
,
170 if (tevent_req_nomem(subreq
, req
)) {
173 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
178 tevent_req_post(req
, ev
);
182 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
184 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
186 struct tevent_req
*req
=
187 tevent_req_callback_data(subreq
,
189 struct tstream_npa_connect_state
*state
=
191 struct tstream_npa_connect_state
);
195 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
196 state
, &state
->unix_stream
);
199 tevent_req_error(req
, sys_errno
);
203 subreq
= tstream_writev_send(state
,
206 &state
->auth_req_iov
, 1);
207 if (tevent_req_nomem(subreq
, req
)) {
210 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
213 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
216 struct iovec
**_vector
,
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 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
240 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
242 tstream_npa_connect_next_vector
,
244 if (tevent_req_nomem(subreq
, req
)) {
247 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
250 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
253 struct iovec
**_vector
,
256 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
257 struct tstream_npa_connect_state
);
258 struct iovec
*vector
;
262 if (state
->auth_rep_blob
.length
== 0) {
263 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
264 if (!state
->auth_rep_blob
.data
) {
267 } else if (state
->auth_rep_blob
.length
== 4) {
272 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
274 if (msg_len
> 0x00FFFFFF) {
286 state
->auth_rep_blob
.data
= talloc_realloc(state
,
287 state
->auth_rep_blob
.data
,
289 if (!state
->auth_rep_blob
.data
) {
292 state
->auth_rep_blob
.length
= msg_len
;
299 /* we need to get a message header */
300 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
304 vector
[0].iov_base
= (char *) (state
->auth_rep_blob
.data
+ ofs
);
305 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
313 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
315 struct tevent_req
*req
=
316 tevent_req_callback_data(subreq
,
318 struct tstream_npa_connect_state
*state
=
320 struct tstream_npa_connect_state
);
323 enum ndr_err_code ndr_err
;
325 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
328 tevent_req_error(req
, sys_errno
);
332 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
333 (uint32_t)state
->auth_rep_blob
.length
));
334 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
336 ndr_err
= ndr_pull_struct_blob(
337 &state
->auth_rep_blob
, state
,
339 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
341 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
342 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
343 ndr_map_error2string(ndr_err
)));
344 tevent_req_error(req
, EIO
);
349 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
352 if (state
->auth_rep
.length
< 16) {
353 DEBUG(0, ("req invalid length: %u < 16\n",
354 state
->auth_rep
.length
));
355 tevent_req_error(req
, EIO
);
359 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
360 DEBUG(0, ("req invalid magic: %s != %s\n",
361 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
362 tevent_req_error(req
, EIO
);
366 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
367 DEBUG(0, ("req failed: %s\n",
368 nt_errstr(state
->auth_rep
.status
)));
369 tevent_req_error(req
, EACCES
);
373 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
374 DEBUG(0, ("req invalid level: %u != %u\n",
375 state
->auth_rep
.level
, state
->auth_req
.level
));
376 tevent_req_error(req
, EIO
);
380 tevent_req_done(req
);
383 int _tstream_npa_connect_recv(struct tevent_req
*req
,
386 struct tstream_context
**_stream
,
387 uint16_t *_file_type
,
388 uint16_t *_device_state
,
389 uint64_t *_allocation_size
,
390 const char *location
)
392 struct tstream_npa_connect_state
*state
=
394 struct tstream_npa_connect_state
);
395 struct tstream_context
*stream
;
396 struct tstream_npa
*npas
;
397 uint16_t device_state
= 0;
398 uint64_t allocation_size
= 0;
400 if (tevent_req_is_unix_error(req
, perrno
)) {
401 tevent_req_received(req
);
405 stream
= tstream_context_create(mem_ctx
,
412 tevent_req_received(req
);
417 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
418 switch (state
->auth_rep
.level
) {
420 npas
->file_type
= state
->auth_rep
.info
.info4
.file_type
;
421 device_state
= state
->auth_rep
.info
.info4
.device_state
;
422 allocation_size
= state
->auth_rep
.info
.info4
.allocation_size
;
427 *_file_type
= npas
->file_type
;
428 *_device_state
= device_state
;
429 *_allocation_size
= allocation_size
;
430 tevent_req_received(req
);
434 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
436 struct tstream_npa
*npas
= tstream_context_data(stream
,
440 if (!npas
->unix_stream
) {
445 switch (npas
->file_type
) {
446 case FILE_TYPE_BYTE_MODE_PIPE
:
447 ret
= tstream_pending_bytes(npas
->unix_stream
);
450 case FILE_TYPE_MESSAGE_MODE_PIPE
:
451 ret
= npas
->pending
.iov_len
;
461 struct tstream_npa_readv_state
{
462 struct tstream_context
*stream
;
464 struct iovec
*vector
;
467 /* the header for message mode */
474 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
475 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
478 struct iovec
**_vector
,
480 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
482 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
483 struct tevent_context
*ev
,
484 struct tstream_context
*stream
,
485 struct iovec
*vector
,
488 struct tevent_req
*req
;
489 struct tstream_npa_readv_state
*state
;
490 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
491 struct tevent_req
*subreq
;
496 req
= tevent_req_create(mem_ctx
, &state
,
497 struct tstream_npa_readv_state
);
502 state
->stream
= stream
;
505 if (!npas
->unix_stream
) {
506 tevent_req_error(req
, ENOTCONN
);
510 switch (npas
->file_type
) {
511 case FILE_TYPE_BYTE_MODE_PIPE
:
512 state
->vector
= vector
;
513 state
->count
= count
;
515 subreq
= tstream_readv_send(state
,
520 if (tevent_req_nomem(subreq
,req
)) {
523 tevent_req_set_callback(subreq
,
524 tstream_npa_readv_byte_mode_handler
,
529 case FILE_TYPE_MESSAGE_MODE_PIPE
:
531 * we make a copy of the vector and prepend a header
534 state
->vector
= talloc_array(state
, struct iovec
, count
);
535 if (tevent_req_nomem(state
->vector
, req
)) {
538 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
539 state
->count
= count
;
542 * copy the pending buffer first
545 left
= npas
->pending
.iov_len
;
546 pbase
= (uint8_t *)npas
->pending
.iov_base
;
548 while (left
> 0 && state
->count
> 0) {
550 base
= (uint8_t *)state
->vector
[0].iov_base
;
551 if (left
< state
->vector
[0].iov_len
) {
552 memcpy(base
, pbase
+ ofs
, left
);
555 state
->vector
[0].iov_base
= (char *) base
;
556 state
->vector
[0].iov_len
-= left
;
561 ZERO_STRUCT(npas
->pending
);
564 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
566 ofs
+= state
->vector
[0].iov_len
;
567 left
-= state
->vector
[0].iov_len
;
573 ZERO_STRUCT(npas
->pending
);
579 memmove(pbase
, pbase
+ ofs
, left
);
580 npas
->pending
.iov_base
= (char *) pbase
;
581 npas
->pending
.iov_len
= left
;
583 * this cannot fail and even if it
584 * fails we can handle it
586 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
588 npas
->pending
.iov_base
= (char *) pbase
;
595 if (state
->count
== 0) {
596 tevent_req_done(req
);
600 ZERO_STRUCT(state
->hdr
);
601 state
->wait_for_hdr
= false;
603 subreq
= tstream_readv_pdu_send(state
,
606 tstream_npa_readv_next_vector
,
608 if (tevent_req_nomem(subreq
, req
)) {
611 tevent_req_set_callback(subreq
,
612 tstream_npa_readv_msg_mode_handler
,
618 /* this can't happen */
619 tevent_req_error(req
, EINVAL
);
623 tevent_req_post(req
, ev
);
627 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
629 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
631 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
632 struct tstream_npa_readv_state
);
636 ret
= tstream_readv_recv(subreq
, &sys_errno
);
639 tevent_req_error(req
, sys_errno
);
645 tevent_req_done(req
);
648 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
651 struct iovec
**_vector
,
654 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
655 struct tstream_npa_readv_state
);
656 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
658 struct iovec
*vector
;
663 if (state
->count
== 0) {
669 if (!state
->wait_for_hdr
) {
670 /* we need to get a message header */
671 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
675 ZERO_STRUCT(state
->hdr
);
676 vector
[0].iov_base
= (char *) state
->hdr
;
677 vector
[0].iov_len
= sizeof(state
->hdr
);
681 state
->wait_for_hdr
= true;
688 /* and now fill the callers buffers and maybe the pending buffer */
689 state
->wait_for_hdr
= false;
691 msg_len
= SVAL(state
->hdr
, 0);
698 state
->wait_for_hdr
= false;
700 /* +1 because we may need to fill the pending buffer */
701 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
708 while (left
> 0 && state
->count
> 0) {
709 if (left
< state
->vector
[0].iov_len
) {
711 base
= (uint8_t *)state
->vector
[0].iov_base
;
712 vector
[count
].iov_base
= (char *) base
;
713 vector
[count
].iov_len
= left
;
716 state
->vector
[0].iov_base
= (char *) base
;
717 state
->vector
[0].iov_len
-= left
;
720 vector
[count
] = state
->vector
[0];
722 left
-= state
->vector
[0].iov_len
;
729 * if the message is longer than the buffers the caller
730 * requested, we need to consume the rest of the message
731 * into the pending buffer, where the next readv can
734 npas
->pending
.iov_base
= talloc_array(npas
, char, left
);
735 if (!npas
->pending
.iov_base
) {
738 npas
->pending
.iov_len
= left
;
740 vector
[count
] = npas
->pending
;
744 state
->ret
+= (msg_len
- left
);
751 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
753 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
758 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
761 tevent_req_error(req
, sys_errno
);
766 * we do not set state->ret here as ret includes the headr size.
767 * we set it in tstream_npa_readv_pdu_next_vector()
770 tevent_req_done(req
);
773 static int tstream_npa_readv_recv(struct tevent_req
*req
,
776 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
777 struct tstream_npa_readv_state
);
780 ret
= tsocket_simple_int_recv(req
, perrno
);
785 tevent_req_received(req
);
789 struct tstream_npa_writev_state
{
790 const struct iovec
*vector
;
793 /* the header for message mode */
800 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
802 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
803 struct tevent_context
*ev
,
804 struct tstream_context
*stream
,
805 const struct iovec
*vector
,
808 struct tevent_req
*req
;
809 struct tstream_npa_writev_state
*state
;
810 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
811 struct tevent_req
*subreq
;
814 struct iovec
*new_vector
;
816 req
= tevent_req_create(mem_ctx
, &state
,
817 struct tstream_npa_writev_state
);
824 if (!npas
->unix_stream
) {
825 tevent_req_error(req
, ENOTCONN
);
829 switch (npas
->file_type
) {
830 case FILE_TYPE_BYTE_MODE_PIPE
:
831 state
->hdr_used
= false;
832 state
->vector
= vector
;
833 state
->count
= count
;
836 case FILE_TYPE_MESSAGE_MODE_PIPE
:
838 * we make a copy of the vector and prepend a header
841 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
842 if (tevent_req_nomem(new_vector
, req
)) {
845 new_vector
[0].iov_base
= (char *) state
->hdr
;
846 new_vector
[0].iov_len
= sizeof(state
->hdr
);
847 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
849 state
->hdr_used
= true;
850 state
->vector
= new_vector
;
851 state
->count
= count
+ 1;
854 for (i
=0; i
< count
; i
++) {
855 msg_len
+= vector
[i
].iov_len
;
858 if (msg_len
> UINT16_MAX
) {
859 tevent_req_error(req
, EMSGSIZE
);
863 SSVAL(state
->hdr
, 0, msg_len
);
867 subreq
= tstream_writev_send(state
,
872 if (tevent_req_nomem(subreq
, req
)) {
875 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
880 tevent_req_post(req
, ev
);
884 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
886 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
888 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
889 struct tstream_npa_writev_state
);
893 ret
= tstream_writev_recv(subreq
, &sys_errno
);
896 tevent_req_error(req
, sys_errno
);
901 * in message mode we need to hide the length
902 * of the hdr from the caller
904 if (state
->hdr_used
) {
905 ret
-= sizeof(state
->hdr
);
910 tevent_req_done(req
);
913 static int tstream_npa_writev_recv(struct tevent_req
*req
,
916 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
917 struct tstream_npa_writev_state
);
920 ret
= tsocket_simple_int_recv(req
, perrno
);
925 tevent_req_received(req
);
929 struct tstream_npa_disconnect_state
{
930 struct tstream_context
*stream
;
933 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
935 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
936 struct tevent_context
*ev
,
937 struct tstream_context
*stream
)
939 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
940 struct tevent_req
*req
;
941 struct tstream_npa_disconnect_state
*state
;
942 struct tevent_req
*subreq
;
944 req
= tevent_req_create(mem_ctx
, &state
,
945 struct tstream_npa_disconnect_state
);
950 state
->stream
= stream
;
952 if (!npas
->unix_stream
) {
953 tevent_req_error(req
, ENOTCONN
);
957 subreq
= tstream_disconnect_send(state
,
960 if (tevent_req_nomem(subreq
, req
)) {
963 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
968 tevent_req_post(req
, ev
);
972 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
974 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
976 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
977 struct tstream_npa_disconnect_state
);
978 struct tstream_context
*stream
= state
->stream
;
979 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
983 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
986 tevent_req_error(req
, sys_errno
);
990 TALLOC_FREE(npas
->unix_stream
);
992 tevent_req_done(req
);
995 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
1000 ret
= tsocket_simple_int_recv(req
, perrno
);
1002 tevent_req_received(req
);
1006 static const struct tstream_context_ops tstream_npa_ops
= {
1009 .pending_bytes
= tstream_npa_pending_bytes
,
1011 .readv_send
= tstream_npa_readv_send
,
1012 .readv_recv
= tstream_npa_readv_recv
,
1014 .writev_send
= tstream_npa_writev_send
,
1015 .writev_recv
= tstream_npa_writev_recv
,
1017 .disconnect_send
= tstream_npa_disconnect_send
,
1018 .disconnect_recv
= tstream_npa_disconnect_recv
,
1021 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1024 struct tstream_context
**_stream
,
1025 const char *location
)
1027 struct tstream_context
*stream
;
1028 struct tstream_npa
*npas
;
1031 switch (file_type
) {
1032 case FILE_TYPE_BYTE_MODE_PIPE
:
1034 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1041 stream
= tstream_context_create(mem_ctx
,
1051 npas
->file_type
= file_type
;
1053 ret
= tstream_bsd_existing_socket(stream
, fd
,
1054 &npas
->unix_stream
);
1056 int saved_errno
= errno
;
1057 talloc_free(stream
);
1058 errno
= saved_errno
;
1067 struct tstream_npa_accept_state
{
1068 struct tevent_context
*ev
;
1069 struct tstream_context
*plain
;
1071 uint16_t device_state
;
1072 uint64_t alloc_size
;
1075 struct iovec out_iov
;
1078 NTSTATUS accept_status
;
1079 struct tsocket_address
*remote_client_addr
;
1080 char *remote_client_name
;
1081 struct tsocket_address
*local_server_addr
;
1082 char *local_server_name
;
1083 struct auth_session_info_transport
*session_info
;
1086 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1088 TALLOC_CTX
*mem_ctx
,
1089 struct iovec
**_vector
,
1091 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1092 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1094 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1095 struct tevent_context
*ev
,
1096 struct tstream_context
*plain
,
1098 uint16_t device_state
,
1099 uint64_t allocation_size
)
1101 struct tstream_npa_accept_state
*state
;
1102 struct tevent_req
*req
, *subreq
;
1104 req
= tevent_req_create(mem_ctx
, &state
,
1105 struct tstream_npa_accept_state
);
1110 switch (file_type
) {
1111 case FILE_TYPE_BYTE_MODE_PIPE
:
1113 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1116 tevent_req_error(req
, EINVAL
);
1120 ZERO_STRUCTP(state
);
1123 state
->plain
= plain
;
1124 state
->file_type
= file_type
;
1125 state
->device_state
= device_state
;
1126 state
->alloc_size
= allocation_size
;
1129 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1130 * named_pipe_full_request provides the pdu length then.
1132 subreq
= tstream_readv_pdu_send(state
, ev
, plain
,
1133 tstream_npa_accept_next_vector
,
1135 if (tevent_req_nomem(subreq
, req
)) {
1139 tevent_req_set_callback(subreq
,
1140 tstream_npa_accept_existing_reply
, req
);
1145 tevent_req_post(req
, ev
);
1149 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1151 TALLOC_CTX
*mem_ctx
,
1152 struct iovec
**_vector
,
1155 struct tstream_npa_accept_state
*state
=
1156 talloc_get_type_abort(private_data
,
1157 struct tstream_npa_accept_state
);
1158 struct iovec
*vector
;
1162 if (state
->npa_blob
.length
== 0) {
1163 state
->npa_blob
= data_blob_talloc(state
, NULL
, 4);
1164 if (!state
->npa_blob
.data
) {
1167 } else if (state
->npa_blob
.length
== 4) {
1172 msg_len
= RIVAL(state
->npa_blob
.data
, 0);
1174 if (msg_len
> 0x00FFFFFF) {
1186 state
->npa_blob
.data
= talloc_realloc(state
,
1187 state
->npa_blob
.data
,
1189 if (!state
->npa_blob
.data
) {
1192 state
->npa_blob
.length
= msg_len
;
1194 if (memcmp(&state
->npa_blob
.data
[4],
1195 NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1196 DEBUG(0, ("Wrong protocol\n"));
1197 #if defined(EPROTONOSUPPORT)
1198 errno
= EPROTONOSUPPORT
;
1199 #elif defined(EPROTO)
1211 /* we need to get a message header */
1212 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1216 vector
[0].iov_base
= (char *) (state
->npa_blob
.data
+ ofs
);
1217 vector
[0].iov_len
= state
->npa_blob
.length
- ofs
;
1225 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1227 struct tevent_req
*req
=
1228 tevent_req_callback_data(subreq
, struct tevent_req
);
1229 struct tstream_npa_accept_state
*state
=
1230 tevent_req_data(req
, struct tstream_npa_accept_state
);
1231 struct named_pipe_auth_req
*pipe_request
;
1232 struct named_pipe_auth_rep pipe_reply
;
1233 struct named_pipe_auth_req_info4 i4
;
1234 enum ndr_err_code ndr_err
;
1239 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
1240 TALLOC_FREE(subreq
);
1242 tevent_req_error(req
, sys_errno
);
1246 DEBUG(10, ("Received packet of length %lu\n",
1247 (long)state
->npa_blob
.length
));
1248 dump_data(11, state
->npa_blob
.data
, state
->npa_blob
.length
);
1250 ZERO_STRUCT(pipe_reply
);
1251 pipe_reply
.level
= 0;
1252 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1254 * TODO: check it's a root (uid == 0) pipe
1257 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1258 if (!pipe_request
) {
1259 DEBUG(0, ("Out of memory!\n"));
1263 /* parse the passed credentials */
1264 ndr_err
= ndr_pull_struct_blob_all(
1265 &state
->npa_blob
, pipe_request
, pipe_request
,
1266 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1267 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1268 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1269 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1270 nt_errstr(pipe_reply
.status
)));
1275 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1280 if (pipe_request
->level
!= 4) {
1281 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1282 pipe_reply
.level
= 0;
1283 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1287 pipe_reply
.level
= 4;
1288 pipe_reply
.status
= NT_STATUS_OK
;
1289 pipe_reply
.info
.info4
.file_type
= state
->file_type
;
1290 pipe_reply
.info
.info4
.device_state
= state
->device_state
;
1291 pipe_reply
.info
.info4
.allocation_size
= state
->alloc_size
;
1293 i4
= pipe_request
->info
.info4
;
1294 if (i4
.local_server_addr
== NULL
) {
1295 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1296 DEBUG(2, ("Missing local server address\n"));
1299 if (i4
.remote_client_addr
== NULL
) {
1300 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1301 DEBUG(2, ("Missing remote client address\n"));
1305 state
->local_server_name
= discard_const_p(char,
1307 &i4
.local_server_name
));
1308 ret
= tsocket_address_inet_from_strings(state
, "ip",
1309 i4
.local_server_addr
,
1310 i4
.local_server_port
,
1311 &state
->local_server_addr
);
1313 DEBUG(2, ("Invalid local server address[%s:%u] - %s\n",
1314 i4
.local_server_addr
, i4
.local_server_port
,
1316 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1320 state
->remote_client_name
= discard_const_p(char,
1322 &i4
.remote_client_name
));
1323 ret
= tsocket_address_inet_from_strings(state
, "ip",
1324 i4
.remote_client_addr
,
1325 i4
.remote_client_port
,
1326 &state
->remote_client_addr
);
1328 DEBUG(2, ("Invalid remote client address[%s:%u] - %s\n",
1329 i4
.remote_client_addr
, i4
.remote_client_port
,
1331 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1335 state
->session_info
= talloc_move(state
, &i4
.session_info
);
1337 /* create the output */
1338 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1339 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1340 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1341 DEBUG(2, ("Error encoding structure: %s",
1342 ndr_map_error2string(ndr_err
)));
1343 tevent_req_error(req
, EIO
);
1347 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1348 dump_data(11, out
.data
, out
.length
);
1351 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1354 state
->accept_status
= pipe_reply
.status
;
1356 state
->out_iov
.iov_base
= (char *) out
.data
;
1357 state
->out_iov
.iov_len
= out
.length
;
1359 subreq
= tstream_writev_send(state
, state
->ev
,
1361 &state
->out_iov
, 1);
1362 if (tevent_req_nomem(subreq
, req
)) {
1363 DEBUG(0, ("no memory for tstream_writev_send"));
1367 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1370 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1372 struct tevent_req
*req
=
1373 tevent_req_callback_data(subreq
, struct tevent_req
);
1377 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1378 TALLOC_FREE(subreq
);
1380 tevent_req_error(req
, sys_errno
);
1384 tevent_req_done(req
);
1387 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1389 TALLOC_CTX
*mem_ctx
,
1390 struct tstream_context
**stream
,
1391 struct tsocket_address
**remote_client_addr
,
1392 char **_remote_client_name
,
1393 struct tsocket_address
**local_server_addr
,
1394 char **local_server_name
,
1395 struct auth_session_info_transport
**session_info
,
1396 const char *location
)
1398 struct tstream_npa_accept_state
*state
=
1399 tevent_req_data(req
, struct tstream_npa_accept_state
);
1400 struct tstream_npa
*npas
;
1403 ret
= tsocket_simple_int_recv(req
, perrno
);
1405 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1406 strerror(*perrno
)));
1407 tevent_req_received(req
);
1411 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1412 #if defined(EPROTONOSUPPORT)
1413 *perrno
= EPROTONOSUPPORT
;
1414 #elif defined(EPROTO)
1419 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1420 nt_errstr(state
->accept_status
),
1421 strerror(*perrno
)));
1422 tevent_req_received(req
);
1426 *stream
= tstream_context_create(mem_ctx
,
1433 tevent_req_received(req
);
1437 npas
->unix_stream
= state
->plain
;
1438 npas
->file_type
= state
->file_type
;
1440 *remote_client_addr
= talloc_move(mem_ctx
, &state
->remote_client_addr
);
1441 *_remote_client_name
= talloc_move(mem_ctx
, &state
->remote_client_name
);
1442 *local_server_addr
= talloc_move(mem_ctx
, &state
->local_server_addr
);
1443 *local_server_name
= talloc_move(mem_ctx
, &state
->local_server_name
);
1444 *session_info
= talloc_move(mem_ctx
, &state
->session_info
);
1446 tevent_req_received(req
);
1451 /* SOCKETPAIR for internal rpc communication */
1453 /* file_type is FILE_TYPE_BYTE_MODE_PIPE or FILE_TYPE_MESSAGE_MODE_PIPE */
1454 int _tstream_npa_socketpair(uint16_t file_type
,
1455 TALLOC_CTX
*mem_ctx1
,
1456 struct tstream_context
**pstream1
,
1457 TALLOC_CTX
*mem_ctx2
,
1458 struct tstream_context
**pstream2
,
1459 const char *location
)
1461 struct tstream_context
*stream1
= NULL
;
1462 struct tstream_context
*stream2
= NULL
;
1469 rc
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
);
1476 ok
= smb_set_close_on_exec(fd1
);
1481 ok
= smb_set_close_on_exec(fd2
);
1486 rc
= set_blocking(fd1
, false);
1491 rc
= set_blocking(fd2
, false);
1496 rc
= _tstream_npa_existing_socket(mem_ctx1
,
1505 rc
= _tstream_npa_existing_socket(mem_ctx2
,
1511 int sys_errno
= errno
;
1512 talloc_free(stream1
);
1518 *pstream1
= stream1
;
1519 *pstream2
= stream2
;
1525 int sys_errno
= errno
;