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 #if _SAMBA_BUILD_ == 4
28 #include "libcli/raw/smb.h"
31 static const struct tstream_context_ops tstream_npa_ops
;
34 struct tstream_context
*unix_stream
;
41 struct tstream_npa_connect_state
{
43 struct tevent_context
*ev
;
46 const char *unix_path
;
47 struct tsocket_address
*unix_laddr
;
48 struct tsocket_address
*unix_raddr
;
49 struct tstream_context
*unix_stream
;
51 struct named_pipe_auth_req auth_req
;
52 DATA_BLOB auth_req_blob
;
53 struct iovec auth_req_iov
;
55 struct named_pipe_auth_rep auth_rep
;
56 DATA_BLOB auth_rep_blob
;
59 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
);
61 struct tevent_req
*tstream_npa_connect_send(TALLOC_CTX
*mem_ctx
,
62 struct tevent_context
*ev
,
63 const char *directory
,
65 const struct tsocket_address
*client
,
66 const char *client_name_in
,
67 const struct tsocket_address
*server
,
68 const char *server_name
,
69 const struct auth_session_info_transport
*session_info
)
71 struct tevent_req
*req
;
72 struct tstream_npa_connect_state
*state
;
73 struct tevent_req
*subreq
;
75 enum ndr_err_code ndr_err
;
76 char *lower_case_npipe
;
77 struct named_pipe_auth_req_info4
*info4
;
79 req
= tevent_req_create(mem_ctx
, &state
,
80 struct tstream_npa_connect_state
);
85 state
->caller
.ev
= ev
;
87 lower_case_npipe
= strlower_talloc(state
, npipe
);
88 if (tevent_req_nomem(lower_case_npipe
, req
)) {
92 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
95 talloc_free(lower_case_npipe
);
96 if (tevent_req_nomem(state
->unix_path
, req
)) {
100 ret
= tsocket_address_unix_from_path(state
,
104 tevent_req_error(req
, errno
);
108 ret
= tsocket_address_unix_from_path(state
,
112 tevent_req_error(req
, errno
);
116 ZERO_STRUCT(state
->auth_req
);
119 tevent_req_error(req
, EINVAL
);
123 state
->auth_req
.level
= 4;
124 info4
= &state
->auth_req
.info
.info4
;
126 info4
->client_name
= client_name_in
;
127 info4
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
128 if (!info4
->client_addr
) {
129 /* errno might be EINVAL */
130 tevent_req_error(req
, errno
);
133 info4
->client_port
= tsocket_address_inet_port(client
);
134 if (!info4
->client_name
) {
135 info4
->client_name
= info4
->client_addr
;
138 info4
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
139 if (!info4
->server_addr
) {
140 /* errno might be EINVAL */
141 tevent_req_error(req
, errno
);
144 info4
->server_port
= tsocket_address_inet_port(server
);
145 if (!info4
->server_name
) {
146 info4
->server_name
= info4
->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
*client
;
1081 struct tsocket_address
*server
;
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
.server_addr
== NULL
) {
1295 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1296 DEBUG(2, ("Missing server address\n"));
1299 if (i4
.client_addr
== NULL
) {
1300 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1301 DEBUG(2, ("Missing client address\n"));
1305 state
->server_name
= discard_const_p(char,
1306 talloc_move(state
, &i4
.server_name
));
1307 ret
= tsocket_address_inet_from_strings(state
, "ip",
1312 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1313 i4
.server_addr
, i4
.server_port
,
1315 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1319 state
->client_name
= discard_const_p(char,
1320 talloc_move(state
, &i4
.client_name
));
1321 ret
= tsocket_address_inet_from_strings(state
, "ip",
1326 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1327 i4
.client_addr
, i4
.client_port
,
1329 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1333 state
->session_info
= talloc_move(state
, &i4
.session_info
);
1335 /* create the output */
1336 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1337 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1338 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1339 DEBUG(2, ("Error encoding structure: %s",
1340 ndr_map_error2string(ndr_err
)));
1341 tevent_req_error(req
, EIO
);
1345 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1346 dump_data(11, out
.data
, out
.length
);
1349 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1352 state
->accept_status
= pipe_reply
.status
;
1354 state
->out_iov
.iov_base
= (char *) out
.data
;
1355 state
->out_iov
.iov_len
= out
.length
;
1357 subreq
= tstream_writev_send(state
, state
->ev
,
1359 &state
->out_iov
, 1);
1360 if (tevent_req_nomem(subreq
, req
)) {
1361 DEBUG(0, ("no memory for tstream_writev_send"));
1365 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1368 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1370 struct tevent_req
*req
=
1371 tevent_req_callback_data(subreq
, struct tevent_req
);
1375 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1376 TALLOC_FREE(subreq
);
1378 tevent_req_error(req
, sys_errno
);
1382 tevent_req_done(req
);
1385 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1387 TALLOC_CTX
*mem_ctx
,
1388 struct tstream_context
**stream
,
1389 struct tsocket_address
**client
,
1390 char **_client_name
,
1391 struct tsocket_address
**server
,
1393 struct auth_session_info_transport
**session_info
,
1394 const char *location
)
1396 struct tstream_npa_accept_state
*state
=
1397 tevent_req_data(req
, struct tstream_npa_accept_state
);
1398 struct tstream_npa
*npas
;
1401 ret
= tsocket_simple_int_recv(req
, perrno
);
1403 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1404 strerror(*perrno
)));
1405 tevent_req_received(req
);
1409 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1410 #if defined(EPROTONOSUPPORT)
1411 *perrno
= EPROTONOSUPPORT
;
1412 #elif defined(EPROTO)
1417 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1418 nt_errstr(state
->accept_status
),
1419 strerror(*perrno
)));
1420 tevent_req_received(req
);
1424 *stream
= tstream_context_create(mem_ctx
,
1431 tevent_req_received(req
);
1435 npas
->unix_stream
= state
->plain
;
1436 npas
->file_type
= state
->file_type
;
1438 *client
= talloc_move(mem_ctx
, &state
->client
);
1439 *_client_name
= talloc_move(mem_ctx
, &state
->client_name
);
1440 *server
= talloc_move(mem_ctx
, &state
->server
);
1441 *server_name
= talloc_move(mem_ctx
, &state
->server_name
);
1442 *session_info
= talloc_move(mem_ctx
, &state
->session_info
);
1444 tevent_req_received(req
);