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/raw/smb.h"
29 static const struct tstream_context_ops tstream_npa_ops
;
32 struct tstream_context
*unix_stream
;
39 struct tstream_npa_connect_state
{
41 struct tevent_context
*ev
;
44 const char *unix_path
;
45 struct tsocket_address
*unix_laddr
;
46 struct tsocket_address
*unix_raddr
;
47 struct tstream_context
*unix_stream
;
49 struct named_pipe_auth_req auth_req
;
50 DATA_BLOB auth_req_blob
;
51 struct iovec auth_req_iov
;
53 struct named_pipe_auth_rep auth_rep
;
54 DATA_BLOB auth_rep_blob
;
57 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
);
59 struct tevent_req
*tstream_npa_connect_send(TALLOC_CTX
*mem_ctx
,
60 struct tevent_context
*ev
,
61 const char *directory
,
63 const struct tsocket_address
*client
,
64 const char *client_name_in
,
65 const struct tsocket_address
*server
,
66 const char *server_name
,
67 const struct netr_SamInfo3
*sam_info3
,
68 DATA_BLOB session_key
,
69 DATA_BLOB delegated_creds
)
71 struct tevent_req
*req
;
72 struct tstream_npa_connect_state
*state
;
73 struct tevent_req
*subreq
;
75 enum ndr_err_code ndr_err
;
77 req
= tevent_req_create(mem_ctx
, &state
,
78 struct tstream_npa_connect_state
);
83 state
->caller
.ev
= ev
;
85 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
88 if (tevent_req_nomem(state
->unix_path
, req
)) {
92 ret
= tsocket_address_unix_from_path(state
,
96 tevent_req_error(req
, errno
);
100 ret
= tsocket_address_unix_from_path(state
,
104 tevent_req_error(req
, errno
);
108 ZERO_STRUCT(state
->auth_req
);
110 struct named_pipe_auth_req_info3
*info3
;
113 tevent_req_error(req
, EINVAL
);
117 state
->auth_req
.level
= 3;
118 info3
= &state
->auth_req
.info
.info3
;
120 info3
->client_name
= client_name_in
;
121 info3
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
122 if (!info3
->client_addr
) {
123 /* errno might be EINVAL */
124 tevent_req_error(req
, errno
);
127 info3
->client_port
= tsocket_address_inet_port(client
);
128 if (!info3
->client_name
) {
129 info3
->client_name
= info3
->client_addr
;
132 info3
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
133 if (!info3
->server_addr
) {
134 /* errno might be EINVAL */
135 tevent_req_error(req
, errno
);
138 info3
->server_port
= tsocket_address_inet_port(server
);
139 if (!info3
->server_name
) {
140 info3
->server_name
= info3
->server_addr
;
143 info3
->sam_info3
= discard_const_p(struct netr_SamInfo3
, sam_info3
);
144 info3
->session_key_length
= session_key
.length
;
145 info3
->session_key
= session_key
.data
;
146 info3
->gssapi_delegated_creds_length
= delegated_creds
.length
;
147 info3
->gssapi_delegated_creds
= delegated_creds
.data
;
149 } else if (sam_info3
) {
150 state
->auth_req
.level
= 1;
151 state
->auth_req
.info
.info1
= *sam_info3
;
153 state
->auth_req
.level
= 0;
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
= 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 int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
221 struct iovec
**_vector
,
223 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
225 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
227 struct tevent_req
*req
=
228 tevent_req_callback_data(subreq
,
230 struct tstream_npa_connect_state
*state
=
232 struct tstream_npa_connect_state
);
236 ret
= tstream_writev_recv(subreq
, &sys_errno
);
239 tevent_req_error(req
, sys_errno
);
243 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
245 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
247 tstream_npa_connect_next_vector
,
249 if (tevent_req_nomem(subreq
, req
)) {
252 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
255 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
258 struct iovec
**_vector
,
261 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
262 struct tstream_npa_connect_state
);
263 struct iovec
*vector
;
267 if (state
->auth_rep_blob
.length
== 0) {
268 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
269 if (!state
->auth_rep_blob
.data
) {
272 } else if (state
->auth_rep_blob
.length
== 4) {
277 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
279 if (msg_len
> 0x00FFFFFF) {
291 state
->auth_rep_blob
.data
= talloc_realloc(state
,
292 state
->auth_rep_blob
.data
,
294 if (!state
->auth_rep_blob
.data
) {
297 state
->auth_rep_blob
.length
= msg_len
;
304 /* we need to get a message header */
305 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
309 vector
[0].iov_base
= state
->auth_rep_blob
.data
+ ofs
;
310 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
318 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
320 struct tevent_req
*req
=
321 tevent_req_callback_data(subreq
,
323 struct tstream_npa_connect_state
*state
=
325 struct tstream_npa_connect_state
);
328 enum ndr_err_code ndr_err
;
330 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
333 tevent_req_error(req
, sys_errno
);
337 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
338 (uint32_t)state
->auth_rep_blob
.length
));
339 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
341 ndr_err
= ndr_pull_struct_blob(
342 &state
->auth_rep_blob
, state
,
344 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
346 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
347 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
348 ndr_map_error2string(ndr_err
)));
349 tevent_req_error(req
, EIO
);
354 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
357 if (state
->auth_rep
.length
< 16) {
358 DEBUG(0, ("req invalid length: %u < 16\n",
359 state
->auth_rep
.length
));
360 tevent_req_error(req
, EIO
);
364 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
365 DEBUG(0, ("req invalid magic: %s != %s\n",
366 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
367 tevent_req_error(req
, EIO
);
371 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
372 DEBUG(0, ("req failed: %s\n",
373 nt_errstr(state
->auth_rep
.status
)));
374 tevent_req_error(req
, EACCES
);
378 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
379 DEBUG(0, ("req invalid level: %u != %u\n",
380 state
->auth_rep
.level
, state
->auth_req
.level
));
381 tevent_req_error(req
, EIO
);
385 tevent_req_done(req
);
388 int _tstream_npa_connect_recv(struct tevent_req
*req
,
391 struct tstream_context
**_stream
,
392 uint16_t *_file_type
,
393 uint16_t *_device_state
,
394 uint64_t *_allocation_size
,
395 const char *location
)
397 struct tstream_npa_connect_state
*state
=
399 struct tstream_npa_connect_state
);
400 struct tstream_context
*stream
;
401 struct tstream_npa
*npas
;
402 uint16_t device_state
= 0;
403 uint64_t allocation_size
= 0;
405 if (tevent_req_is_unix_error(req
, perrno
)) {
406 tevent_req_received(req
);
410 stream
= tstream_context_create(mem_ctx
,
420 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
421 switch (state
->auth_rep
.level
) {
424 npas
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
425 device_state
= 0x00ff;
426 allocation_size
= 2048;
429 npas
->file_type
= state
->auth_rep
.info
.info2
.file_type
;
430 device_state
= state
->auth_rep
.info
.info2
.device_state
;
431 allocation_size
= state
->auth_rep
.info
.info2
.allocation_size
;
434 npas
->file_type
= state
->auth_rep
.info
.info3
.file_type
;
435 device_state
= state
->auth_rep
.info
.info3
.device_state
;
436 allocation_size
= state
->auth_rep
.info
.info3
.allocation_size
;
441 *_file_type
= npas
->file_type
;
442 *_device_state
= device_state
;
443 *_allocation_size
= allocation_size
;
444 tevent_req_received(req
);
448 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
450 struct tstream_npa
*npas
= tstream_context_data(stream
,
454 if (!npas
->unix_stream
) {
459 switch (npas
->file_type
) {
460 case FILE_TYPE_BYTE_MODE_PIPE
:
461 ret
= tstream_pending_bytes(npas
->unix_stream
);
464 case FILE_TYPE_MESSAGE_MODE_PIPE
:
465 ret
= npas
->pending
.iov_len
;
475 struct tstream_npa_readv_state
{
476 struct tstream_context
*stream
;
478 struct iovec
*vector
;
481 /* the header for message mode */
488 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
489 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
492 struct iovec
**_vector
,
494 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
496 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
497 struct tevent_context
*ev
,
498 struct tstream_context
*stream
,
499 struct iovec
*vector
,
502 struct tevent_req
*req
;
503 struct tstream_npa_readv_state
*state
;
504 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
505 struct tevent_req
*subreq
;
510 req
= tevent_req_create(mem_ctx
, &state
,
511 struct tstream_npa_readv_state
);
516 state
->stream
= stream
;
519 if (!npas
->unix_stream
) {
520 tevent_req_error(req
, ENOTCONN
);
524 switch (npas
->file_type
) {
525 case FILE_TYPE_BYTE_MODE_PIPE
:
526 state
->vector
= vector
;
527 state
->count
= count
;
529 subreq
= tstream_readv_send(state
,
534 if (tevent_req_nomem(subreq
,req
)) {
537 tevent_req_set_callback(subreq
,
538 tstream_npa_readv_byte_mode_handler
,
543 case FILE_TYPE_MESSAGE_MODE_PIPE
:
545 * we make a copy of the vector and prepend a header
548 state
->vector
= talloc_array(state
, struct iovec
, count
);
549 if (tevent_req_nomem(state
->vector
, req
)) {
552 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
553 state
->count
= count
;
556 * copy the pending buffer first
559 left
= npas
->pending
.iov_len
;
560 pbase
= (uint8_t *)npas
->pending
.iov_base
;
562 while (left
> 0 && state
->count
> 0) {
564 base
= (uint8_t *)state
->vector
[0].iov_base
;
565 if (left
< state
->vector
[0].iov_len
) {
566 memcpy(base
, pbase
+ ofs
, left
);
569 state
->vector
[0].iov_base
= base
;
570 state
->vector
[0].iov_len
-= left
;
575 ZERO_STRUCT(npas
->pending
);
578 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
580 ofs
+= state
->vector
[0].iov_len
;
581 left
-= state
->vector
[0].iov_len
;
587 ZERO_STRUCT(npas
->pending
);
593 memmove(pbase
, pbase
+ ofs
, left
);
594 npas
->pending
.iov_base
= pbase
;
595 npas
->pending
.iov_len
= left
;
597 * this cannot fail and even if it
598 * fails we can handle it
600 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
602 npas
->pending
.iov_base
= pbase
;
609 if (state
->count
== 0) {
610 tevent_req_done(req
);
614 ZERO_STRUCT(state
->hdr
);
615 state
->wait_for_hdr
= false;
617 subreq
= tstream_readv_pdu_send(state
,
620 tstream_npa_readv_next_vector
,
622 if (tevent_req_nomem(subreq
, req
)) {
625 tevent_req_set_callback(subreq
,
626 tstream_npa_readv_msg_mode_handler
,
632 /* this can't happen */
633 tevent_req_error(req
, EINVAL
);
637 tevent_req_post(req
, ev
);
641 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
643 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
645 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
646 struct tstream_npa_readv_state
);
650 ret
= tstream_readv_recv(subreq
, &sys_errno
);
653 tevent_req_error(req
, sys_errno
);
659 tevent_req_done(req
);
662 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
665 struct iovec
**_vector
,
668 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
669 struct tstream_npa_readv_state
);
670 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
672 struct iovec
*vector
;
677 if (state
->count
== 0) {
683 if (!state
->wait_for_hdr
) {
684 /* we need to get a message header */
685 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
689 ZERO_STRUCT(state
->hdr
);
690 vector
[0].iov_base
= state
->hdr
;
691 vector
[0].iov_len
= sizeof(state
->hdr
);
695 state
->wait_for_hdr
= true;
702 /* and now fill the callers buffers and maybe the pending buffer */
703 state
->wait_for_hdr
= false;
705 msg_len
= SVAL(state
->hdr
, 0);
712 state
->wait_for_hdr
= false;
714 /* +1 because we may need to fill the pending buffer */
715 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
722 while (left
> 0 && state
->count
> 0) {
723 if (left
< state
->vector
[0].iov_len
) {
725 base
= (uint8_t *)state
->vector
[0].iov_base
;
726 vector
[count
].iov_base
= base
;
727 vector
[count
].iov_len
= left
;
730 state
->vector
[0].iov_base
= base
;
731 state
->vector
[0].iov_len
-= left
;
734 vector
[count
] = state
->vector
[0];
736 left
-= state
->vector
[0].iov_len
;
743 * if the message is longer than the buffers the caller
744 * requested, we need to consume the rest of the message
745 * into the pending buffer, where the next readv can
748 npas
->pending
.iov_base
= talloc_array(npas
, uint8_t, left
);
749 if (!npas
->pending
.iov_base
) {
752 npas
->pending
.iov_len
= left
;
754 vector
[count
] = npas
->pending
;
758 state
->ret
+= (msg_len
- left
);
765 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
767 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
772 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
775 tevent_req_error(req
, sys_errno
);
780 * we do not set state->ret here as ret includes the headr size.
781 * we set it in tstream_npa_readv_pdu_next_vector()
784 tevent_req_done(req
);
787 static int tstream_npa_readv_recv(struct tevent_req
*req
,
790 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
791 struct tstream_npa_readv_state
);
794 ret
= tsocket_simple_int_recv(req
, perrno
);
799 tevent_req_received(req
);
803 struct tstream_npa_writev_state
{
804 const struct iovec
*vector
;
807 /* the header for message mode */
814 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
816 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
817 struct tevent_context
*ev
,
818 struct tstream_context
*stream
,
819 const struct iovec
*vector
,
822 struct tevent_req
*req
;
823 struct tstream_npa_writev_state
*state
;
824 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
825 struct tevent_req
*subreq
;
828 struct iovec
*new_vector
;
830 req
= tevent_req_create(mem_ctx
, &state
,
831 struct tstream_npa_writev_state
);
838 if (!npas
->unix_stream
) {
839 tevent_req_error(req
, ENOTCONN
);
843 switch (npas
->file_type
) {
844 case FILE_TYPE_BYTE_MODE_PIPE
:
845 state
->hdr_used
= false;
846 state
->vector
= vector
;
847 state
->count
= count
;
850 case FILE_TYPE_MESSAGE_MODE_PIPE
:
852 * we make a copy of the vector and prepend a header
855 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
856 if (tevent_req_nomem(new_vector
, req
)) {
859 new_vector
[0].iov_base
= state
->hdr
;
860 new_vector
[0].iov_len
= sizeof(state
->hdr
);
861 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
863 state
->hdr_used
= true;
864 state
->vector
= new_vector
;
865 state
->count
= count
+ 1;
868 for (i
=0; i
< count
; i
++) {
869 msg_len
+= vector
[i
].iov_len
;
872 if (msg_len
> UINT16_MAX
) {
873 tevent_req_error(req
, EMSGSIZE
);
877 SSVAL(state
->hdr
, 0, msg_len
);
881 subreq
= tstream_writev_send(state
,
886 if (tevent_req_nomem(subreq
, req
)) {
889 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
894 tevent_req_post(req
, ev
);
898 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
900 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
902 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
903 struct tstream_npa_writev_state
);
907 ret
= tstream_writev_recv(subreq
, &sys_errno
);
910 tevent_req_error(req
, sys_errno
);
915 * in message mode we need to hide the length
916 * of the hdr from the caller
918 if (state
->hdr_used
) {
919 ret
-= sizeof(state
->hdr
);
924 tevent_req_done(req
);
927 static int tstream_npa_writev_recv(struct tevent_req
*req
,
930 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
931 struct tstream_npa_writev_state
);
934 ret
= tsocket_simple_int_recv(req
, perrno
);
939 tevent_req_received(req
);
943 struct tstream_npa_disconnect_state
{
944 struct tstream_context
*stream
;
947 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
949 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
950 struct tevent_context
*ev
,
951 struct tstream_context
*stream
)
953 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
954 struct tevent_req
*req
;
955 struct tstream_npa_disconnect_state
*state
;
956 struct tevent_req
*subreq
;
958 req
= tevent_req_create(mem_ctx
, &state
,
959 struct tstream_npa_disconnect_state
);
964 state
->stream
= stream
;
966 if (!npas
->unix_stream
) {
967 tevent_req_error(req
, ENOTCONN
);
971 subreq
= tstream_disconnect_send(state
,
974 if (tevent_req_nomem(subreq
, req
)) {
977 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
982 tevent_req_post(req
, ev
);
986 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
988 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
990 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
991 struct tstream_npa_disconnect_state
);
992 struct tstream_context
*stream
= state
->stream
;
993 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
997 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
1000 tevent_req_error(req
, sys_errno
);
1004 TALLOC_FREE(npas
->unix_stream
);
1006 tevent_req_done(req
);
1009 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
1014 ret
= tsocket_simple_int_recv(req
, perrno
);
1016 tevent_req_received(req
);
1020 static const struct tstream_context_ops tstream_npa_ops
= {
1023 .pending_bytes
= tstream_npa_pending_bytes
,
1025 .readv_send
= tstream_npa_readv_send
,
1026 .readv_recv
= tstream_npa_readv_recv
,
1028 .writev_send
= tstream_npa_writev_send
,
1029 .writev_recv
= tstream_npa_writev_recv
,
1031 .disconnect_send
= tstream_npa_disconnect_send
,
1032 .disconnect_recv
= tstream_npa_disconnect_recv
,
1035 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1038 struct tstream_context
**_stream
,
1039 const char *location
)
1041 struct tstream_context
*stream
;
1042 struct tstream_npa
*npas
;
1045 switch (file_type
) {
1046 case FILE_TYPE_BYTE_MODE_PIPE
:
1048 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1055 stream
= tstream_context_create(mem_ctx
,
1065 npas
->file_type
= file_type
;
1067 ret
= tstream_bsd_existing_socket(stream
, fd
,
1068 &npas
->unix_stream
);
1070 int saved_errno
= errno
;
1071 talloc_free(stream
);
1072 errno
= saved_errno
;
1081 struct tstream_npa_accept_state
{
1082 struct tevent_context
*ev
;
1083 struct tstream_context
*plain
;
1085 uint16_t device_state
;
1086 uint64_t alloc_size
;
1089 struct iovec out_iov
;
1092 NTSTATUS accept_status
;
1093 struct tsocket_address
*client
;
1095 struct tsocket_address
*server
;
1097 struct netr_SamInfo3
*info3
;
1098 DATA_BLOB session_key
;
1099 DATA_BLOB delegated_creds
;
1102 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1104 TALLOC_CTX
*mem_ctx
,
1105 struct iovec
**_vector
,
1107 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1108 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1110 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1111 struct tevent_context
*ev
,
1112 struct tstream_context
*plain
,
1114 uint16_t device_state
,
1115 uint64_t allocation_size
)
1117 struct tstream_npa_accept_state
*state
;
1118 struct tevent_req
*req
, *subreq
;
1120 req
= tevent_req_create(mem_ctx
, &state
,
1121 struct tstream_npa_accept_state
);
1126 switch (file_type
) {
1127 case FILE_TYPE_BYTE_MODE_PIPE
:
1129 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1132 tevent_req_error(req
, EINVAL
);
1136 ZERO_STRUCTP(state
);
1139 state
->plain
= plain
;
1140 state
->file_type
= file_type
;
1141 state
->device_state
= device_state
;
1142 state
->alloc_size
= allocation_size
;
1145 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1146 * named_pipe_full_request provides the pdu length then.
1148 subreq
= tstream_readv_pdu_send(state
, ev
, plain
,
1149 tstream_npa_accept_next_vector
,
1151 if (tevent_req_nomem(subreq
, req
)) {
1155 tevent_req_set_callback(subreq
,
1156 tstream_npa_accept_existing_reply
, req
);
1161 tevent_req_post(req
, ev
);
1165 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1167 TALLOC_CTX
*mem_ctx
,
1168 struct iovec
**_vector
,
1171 struct tstream_npa_accept_state
*state
=
1172 talloc_get_type_abort(private_data
,
1173 struct tstream_npa_accept_state
);
1174 struct iovec
*vector
;
1178 if (state
->npa_blob
.length
== 0) {
1179 state
->npa_blob
= data_blob_talloc(state
, NULL
, 4);
1180 if (!state
->npa_blob
.data
) {
1183 } else if (state
->npa_blob
.length
== 4) {
1188 msg_len
= RIVAL(state
->npa_blob
.data
, 0);
1190 if (msg_len
> 0x00FFFFFF) {
1202 state
->npa_blob
.data
= talloc_realloc(state
,
1203 state
->npa_blob
.data
,
1205 if (!state
->npa_blob
.data
) {
1208 state
->npa_blob
.length
= msg_len
;
1210 if (memcmp(&state
->npa_blob
.data
[4],
1211 NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1212 DEBUG(0, ("Wrong protocol\n"));
1213 #if defined(EPROTONOSUPPORT)
1214 errno
= EPROTONOSUPPORT
;
1215 #elif defined(EPROTO)
1227 /* we need to get a message header */
1228 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1232 vector
[0].iov_base
= state
->npa_blob
.data
+ ofs
;
1233 vector
[0].iov_len
= state
->npa_blob
.length
- ofs
;
1241 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1243 struct tevent_req
*req
=
1244 tevent_req_callback_data(subreq
, struct tevent_req
);
1245 struct tstream_npa_accept_state
*state
=
1246 tevent_req_data(req
, struct tstream_npa_accept_state
);
1247 struct named_pipe_auth_req
*pipe_request
;
1248 struct named_pipe_auth_rep pipe_reply
;
1249 struct named_pipe_auth_req_info3 i3
;
1250 enum ndr_err_code ndr_err
;
1255 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
1256 TALLOC_FREE(subreq
);
1258 tevent_req_error(req
, sys_errno
);
1262 DEBUG(10, ("Received packet of length %lu\n",
1263 (long)state
->npa_blob
.length
));
1264 dump_data(11, state
->npa_blob
.data
, state
->npa_blob
.length
);
1266 ZERO_STRUCT(pipe_reply
);
1267 pipe_reply
.level
= 0;
1268 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1270 * TODO: check it's a root (uid == 0) pipe
1273 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1274 if (!pipe_request
) {
1275 DEBUG(0, ("Out of memory!\n"));
1279 /* parse the passed credentials */
1280 ndr_err
= ndr_pull_struct_blob_all(
1281 &state
->npa_blob
, pipe_request
, pipe_request
,
1282 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1283 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1284 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1285 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1286 nt_errstr(pipe_reply
.status
)));
1291 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1296 switch (pipe_request
->level
) {
1298 pipe_reply
.level
= 0;
1299 pipe_reply
.status
= NT_STATUS_OK
;
1301 /* we need to force byte mode in this level */
1302 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1306 pipe_reply
.level
= 1;
1307 pipe_reply
.status
= NT_STATUS_OK
;
1309 /* We must copy net3_SamInfo3, so that
1310 * info3 is an actual talloc pointer, then we steal
1311 * pipe_request on info3 so that all the allocated memory
1312 * pointed by the structrue members is preserved */
1313 state
->info3
= (struct netr_SamInfo3
*)talloc_memdup(state
,
1314 &pipe_request
->info
.info1
,
1315 sizeof(struct netr_SamInfo3
));
1316 if (!state
->info3
) {
1317 pipe_reply
.status
= NT_STATUS_NO_MEMORY
;
1318 DEBUG(0, ("Out of memory!\n"));
1321 talloc_move(state
->info3
, &pipe_request
);
1323 /* we need to force byte mode in this level */
1324 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1328 pipe_reply
.level
= 2;
1329 pipe_reply
.status
= NT_STATUS_OK
;
1330 pipe_reply
.info
.info2
.file_type
= state
->file_type
;
1331 pipe_reply
.info
.info2
.device_state
= state
->device_state
;
1332 pipe_reply
.info
.info2
.allocation_size
= state
->alloc_size
;
1334 i3
.client_name
= pipe_request
->info
.info2
.client_name
;
1335 i3
.client_addr
= pipe_request
->info
.info2
.client_addr
;
1336 i3
.client_port
= pipe_request
->info
.info2
.client_port
;
1337 i3
.server_name
= pipe_request
->info
.info2
.server_name
;
1338 i3
.server_addr
= pipe_request
->info
.info2
.server_addr
;
1339 i3
.server_port
= pipe_request
->info
.info2
.server_port
;
1340 i3
.sam_info3
= pipe_request
->info
.info2
.sam_info3
;
1341 i3
.session_key_length
=
1342 pipe_request
->info
.info2
.session_key_length
;
1343 i3
.session_key
= pipe_request
->info
.info2
.session_key
;
1347 pipe_reply
.level
= 3;
1348 pipe_reply
.status
= NT_STATUS_OK
;
1349 pipe_reply
.info
.info3
.file_type
= state
->file_type
;
1350 pipe_reply
.info
.info3
.device_state
= state
->device_state
;
1351 pipe_reply
.info
.info3
.allocation_size
= state
->alloc_size
;
1353 i3
= pipe_request
->info
.info3
;
1357 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1358 pipe_reply
.level
= 0;
1359 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1363 if (pipe_reply
.level
>=2) {
1365 if (i3
.server_addr
== NULL
) {
1366 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1367 DEBUG(2, ("Missing server address\n"));
1370 if (i3
.client_addr
== NULL
) {
1371 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1372 DEBUG(2, ("Missing client address\n"));
1376 state
->server_name
= discard_const_p(char,
1377 talloc_move(state
, &i3
.server_name
));
1378 ret
= tsocket_address_inet_from_strings(state
, "ip",
1383 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1384 i3
.server_addr
, i3
.server_port
,
1386 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1390 state
->client_name
= discard_const_p(char,
1391 talloc_move(state
, &i3
.client_name
));
1392 ret
= tsocket_address_inet_from_strings(state
, "ip",
1397 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1398 i3
.client_addr
, i3
.client_port
,
1400 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1404 state
->info3
= talloc_move(state
, &i3
.sam_info3
);
1405 state
->session_key
.data
= talloc_move(state
, &i3
.session_key
);
1406 state
->session_key
.length
= i3
.session_key_length
;
1409 if (pipe_reply
.level
>= 3) {
1410 state
->delegated_creds
.data
=
1411 talloc_move(state
, &i3
.gssapi_delegated_creds
);
1412 state
->delegated_creds
.length
=
1413 i3
.gssapi_delegated_creds_length
;
1417 /* create the output */
1418 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1419 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1420 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1421 DEBUG(2, ("Error encoding structure: %s",
1422 ndr_map_error2string(ndr_err
)));
1423 tevent_req_error(req
, EIO
);
1427 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1428 dump_data(11, out
.data
, out
.length
);
1431 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1434 state
->accept_status
= pipe_reply
.status
;
1436 state
->out_iov
.iov_base
= out
.data
;
1437 state
->out_iov
.iov_len
= out
.length
;
1439 subreq
= tstream_writev_send(state
, state
->ev
,
1441 &state
->out_iov
, 1);
1442 if (tevent_req_nomem(subreq
, req
)) {
1443 DEBUG(0, ("no memory for tstream_writev_send"));
1447 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1450 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1452 struct tevent_req
*req
=
1453 tevent_req_callback_data(subreq
, struct tevent_req
);
1457 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1458 TALLOC_FREE(subreq
);
1460 tevent_req_error(req
, sys_errno
);
1464 tevent_req_done(req
);
1467 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1469 TALLOC_CTX
*mem_ctx
,
1470 struct tstream_context
**stream
,
1471 struct tsocket_address
**client
,
1472 char **_client_name
,
1473 struct tsocket_address
**server
,
1475 struct netr_SamInfo3
**info3
,
1476 DATA_BLOB
*session_key
,
1477 DATA_BLOB
*delegated_creds
,
1478 const char *location
)
1480 struct tstream_npa_accept_state
*state
=
1481 tevent_req_data(req
, struct tstream_npa_accept_state
);
1482 struct tstream_npa
*npas
;
1485 ret
= tsocket_simple_int_recv(req
, perrno
);
1487 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1488 strerror(*perrno
)));
1489 tevent_req_received(req
);
1493 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1494 #if defined(EPROTONOSUPPORT)
1495 *perrno
= EPROTONOSUPPORT
;
1496 #elif defined(EPROTO)
1501 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1502 nt_errstr(state
->accept_status
),
1503 strerror(*perrno
)));
1504 tevent_req_received(req
);
1508 *stream
= tstream_context_create(mem_ctx
,
1515 tevent_req_received(req
);
1519 npas
->unix_stream
= state
->plain
;
1520 npas
->file_type
= state
->file_type
;
1522 *client
= talloc_move(mem_ctx
, &state
->client
);
1523 *_client_name
= talloc_move(mem_ctx
, &state
->client_name
);
1524 *server
= talloc_move(mem_ctx
, &state
->server
);
1525 *server_name
= talloc_move(mem_ctx
, &state
->server_name
);
1526 *info3
= talloc_move(mem_ctx
, &state
->info3
);
1527 *session_key
= state
->session_key
;
1528 talloc_move(mem_ctx
, &state
->session_key
.data
);
1529 *delegated_creds
= state
->delegated_creds
;
1530 talloc_move(mem_ctx
, &state
->delegated_creds
.data
);
1532 tevent_req_received(req
);