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
;
76 char *lower_case_npipe
;
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 struct named_pipe_auth_req_info3
*info3
;
120 tevent_req_error(req
, EINVAL
);
124 state
->auth_req
.level
= 3;
125 info3
= &state
->auth_req
.info
.info3
;
127 info3
->client_name
= client_name_in
;
128 info3
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
129 if (!info3
->client_addr
) {
130 /* errno might be EINVAL */
131 tevent_req_error(req
, errno
);
134 info3
->client_port
= tsocket_address_inet_port(client
);
135 if (!info3
->client_name
) {
136 info3
->client_name
= info3
->client_addr
;
139 info3
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
140 if (!info3
->server_addr
) {
141 /* errno might be EINVAL */
142 tevent_req_error(req
, errno
);
145 info3
->server_port
= tsocket_address_inet_port(server
);
146 if (!info3
->server_name
) {
147 info3
->server_name
= info3
->server_addr
;
150 info3
->sam_info3
= discard_const_p(struct netr_SamInfo3
, sam_info3
);
151 info3
->session_key_length
= session_key
.length
;
152 info3
->session_key
= session_key
.data
;
153 info3
->gssapi_delegated_creds_length
= delegated_creds
.length
;
154 info3
->gssapi_delegated_creds
= delegated_creds
.data
;
156 } else if (sam_info3
) {
157 state
->auth_req
.level
= 1;
158 state
->auth_req
.info
.info1
= *sam_info3
;
160 state
->auth_req
.level
= 0;
164 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
167 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
168 state
, &state
->auth_req
,
169 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
170 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
171 tevent_req_error(req
, EINVAL
);
175 state
->auth_req_iov
.iov_base
= state
->auth_req_blob
.data
;
176 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
178 subreq
= tstream_unix_connect_send(state
,
182 if (tevent_req_nomem(subreq
, req
)) {
185 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
190 tevent_req_post(req
, ev
);
194 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
196 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
198 struct tevent_req
*req
=
199 tevent_req_callback_data(subreq
,
201 struct tstream_npa_connect_state
*state
=
203 struct tstream_npa_connect_state
);
207 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
208 state
, &state
->unix_stream
);
211 tevent_req_error(req
, sys_errno
);
215 subreq
= tstream_writev_send(state
,
218 &state
->auth_req_iov
, 1);
219 if (tevent_req_nomem(subreq
, req
)) {
222 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
225 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
228 struct iovec
**_vector
,
230 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
232 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
234 struct tevent_req
*req
=
235 tevent_req_callback_data(subreq
,
237 struct tstream_npa_connect_state
*state
=
239 struct tstream_npa_connect_state
);
243 ret
= tstream_writev_recv(subreq
, &sys_errno
);
246 tevent_req_error(req
, sys_errno
);
250 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
252 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
254 tstream_npa_connect_next_vector
,
256 if (tevent_req_nomem(subreq
, req
)) {
259 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
262 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
265 struct iovec
**_vector
,
268 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
269 struct tstream_npa_connect_state
);
270 struct iovec
*vector
;
274 if (state
->auth_rep_blob
.length
== 0) {
275 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
276 if (!state
->auth_rep_blob
.data
) {
279 } else if (state
->auth_rep_blob
.length
== 4) {
284 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
286 if (msg_len
> 0x00FFFFFF) {
298 state
->auth_rep_blob
.data
= talloc_realloc(state
,
299 state
->auth_rep_blob
.data
,
301 if (!state
->auth_rep_blob
.data
) {
304 state
->auth_rep_blob
.length
= msg_len
;
311 /* we need to get a message header */
312 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
316 vector
[0].iov_base
= state
->auth_rep_blob
.data
+ ofs
;
317 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
325 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
327 struct tevent_req
*req
=
328 tevent_req_callback_data(subreq
,
330 struct tstream_npa_connect_state
*state
=
332 struct tstream_npa_connect_state
);
335 enum ndr_err_code ndr_err
;
337 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
340 tevent_req_error(req
, sys_errno
);
344 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
345 (uint32_t)state
->auth_rep_blob
.length
));
346 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
348 ndr_err
= ndr_pull_struct_blob(
349 &state
->auth_rep_blob
, state
,
351 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
353 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
354 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
355 ndr_map_error2string(ndr_err
)));
356 tevent_req_error(req
, EIO
);
361 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
364 if (state
->auth_rep
.length
< 16) {
365 DEBUG(0, ("req invalid length: %u < 16\n",
366 state
->auth_rep
.length
));
367 tevent_req_error(req
, EIO
);
371 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
372 DEBUG(0, ("req invalid magic: %s != %s\n",
373 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
374 tevent_req_error(req
, EIO
);
378 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
379 DEBUG(0, ("req failed: %s\n",
380 nt_errstr(state
->auth_rep
.status
)));
381 tevent_req_error(req
, EACCES
);
385 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
386 DEBUG(0, ("req invalid level: %u != %u\n",
387 state
->auth_rep
.level
, state
->auth_req
.level
));
388 tevent_req_error(req
, EIO
);
392 tevent_req_done(req
);
395 int _tstream_npa_connect_recv(struct tevent_req
*req
,
398 struct tstream_context
**_stream
,
399 uint16_t *_file_type
,
400 uint16_t *_device_state
,
401 uint64_t *_allocation_size
,
402 const char *location
)
404 struct tstream_npa_connect_state
*state
=
406 struct tstream_npa_connect_state
);
407 struct tstream_context
*stream
;
408 struct tstream_npa
*npas
;
409 uint16_t device_state
= 0;
410 uint64_t allocation_size
= 0;
412 if (tevent_req_is_unix_error(req
, perrno
)) {
413 tevent_req_received(req
);
417 stream
= tstream_context_create(mem_ctx
,
424 tevent_req_received(req
);
429 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
430 switch (state
->auth_rep
.level
) {
433 npas
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
434 device_state
= 0x00ff;
435 allocation_size
= 2048;
438 npas
->file_type
= state
->auth_rep
.info
.info2
.file_type
;
439 device_state
= state
->auth_rep
.info
.info2
.device_state
;
440 allocation_size
= state
->auth_rep
.info
.info2
.allocation_size
;
443 npas
->file_type
= state
->auth_rep
.info
.info3
.file_type
;
444 device_state
= state
->auth_rep
.info
.info3
.device_state
;
445 allocation_size
= state
->auth_rep
.info
.info3
.allocation_size
;
450 *_file_type
= npas
->file_type
;
451 *_device_state
= device_state
;
452 *_allocation_size
= allocation_size
;
453 tevent_req_received(req
);
457 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
459 struct tstream_npa
*npas
= tstream_context_data(stream
,
463 if (!npas
->unix_stream
) {
468 switch (npas
->file_type
) {
469 case FILE_TYPE_BYTE_MODE_PIPE
:
470 ret
= tstream_pending_bytes(npas
->unix_stream
);
473 case FILE_TYPE_MESSAGE_MODE_PIPE
:
474 ret
= npas
->pending
.iov_len
;
484 struct tstream_npa_readv_state
{
485 struct tstream_context
*stream
;
487 struct iovec
*vector
;
490 /* the header for message mode */
497 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
498 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
501 struct iovec
**_vector
,
503 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
505 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
506 struct tevent_context
*ev
,
507 struct tstream_context
*stream
,
508 struct iovec
*vector
,
511 struct tevent_req
*req
;
512 struct tstream_npa_readv_state
*state
;
513 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
514 struct tevent_req
*subreq
;
519 req
= tevent_req_create(mem_ctx
, &state
,
520 struct tstream_npa_readv_state
);
525 state
->stream
= stream
;
528 if (!npas
->unix_stream
) {
529 tevent_req_error(req
, ENOTCONN
);
533 switch (npas
->file_type
) {
534 case FILE_TYPE_BYTE_MODE_PIPE
:
535 state
->vector
= vector
;
536 state
->count
= count
;
538 subreq
= tstream_readv_send(state
,
543 if (tevent_req_nomem(subreq
,req
)) {
546 tevent_req_set_callback(subreq
,
547 tstream_npa_readv_byte_mode_handler
,
552 case FILE_TYPE_MESSAGE_MODE_PIPE
:
554 * we make a copy of the vector and prepend a header
557 state
->vector
= talloc_array(state
, struct iovec
, count
);
558 if (tevent_req_nomem(state
->vector
, req
)) {
561 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
562 state
->count
= count
;
565 * copy the pending buffer first
568 left
= npas
->pending
.iov_len
;
569 pbase
= (uint8_t *)npas
->pending
.iov_base
;
571 while (left
> 0 && state
->count
> 0) {
573 base
= (uint8_t *)state
->vector
[0].iov_base
;
574 if (left
< state
->vector
[0].iov_len
) {
575 memcpy(base
, pbase
+ ofs
, left
);
578 state
->vector
[0].iov_base
= base
;
579 state
->vector
[0].iov_len
-= left
;
584 ZERO_STRUCT(npas
->pending
);
587 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
589 ofs
+= state
->vector
[0].iov_len
;
590 left
-= state
->vector
[0].iov_len
;
596 ZERO_STRUCT(npas
->pending
);
602 memmove(pbase
, pbase
+ ofs
, left
);
603 npas
->pending
.iov_base
= pbase
;
604 npas
->pending
.iov_len
= left
;
606 * this cannot fail and even if it
607 * fails we can handle it
609 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
611 npas
->pending
.iov_base
= pbase
;
618 if (state
->count
== 0) {
619 tevent_req_done(req
);
623 ZERO_STRUCT(state
->hdr
);
624 state
->wait_for_hdr
= false;
626 subreq
= tstream_readv_pdu_send(state
,
629 tstream_npa_readv_next_vector
,
631 if (tevent_req_nomem(subreq
, req
)) {
634 tevent_req_set_callback(subreq
,
635 tstream_npa_readv_msg_mode_handler
,
641 /* this can't happen */
642 tevent_req_error(req
, EINVAL
);
646 tevent_req_post(req
, ev
);
650 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
652 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
654 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
655 struct tstream_npa_readv_state
);
659 ret
= tstream_readv_recv(subreq
, &sys_errno
);
662 tevent_req_error(req
, sys_errno
);
668 tevent_req_done(req
);
671 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
674 struct iovec
**_vector
,
677 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
678 struct tstream_npa_readv_state
);
679 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
681 struct iovec
*vector
;
686 if (state
->count
== 0) {
692 if (!state
->wait_for_hdr
) {
693 /* we need to get a message header */
694 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
698 ZERO_STRUCT(state
->hdr
);
699 vector
[0].iov_base
= state
->hdr
;
700 vector
[0].iov_len
= sizeof(state
->hdr
);
704 state
->wait_for_hdr
= true;
711 /* and now fill the callers buffers and maybe the pending buffer */
712 state
->wait_for_hdr
= false;
714 msg_len
= SVAL(state
->hdr
, 0);
721 state
->wait_for_hdr
= false;
723 /* +1 because we may need to fill the pending buffer */
724 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
731 while (left
> 0 && state
->count
> 0) {
732 if (left
< state
->vector
[0].iov_len
) {
734 base
= (uint8_t *)state
->vector
[0].iov_base
;
735 vector
[count
].iov_base
= base
;
736 vector
[count
].iov_len
= left
;
739 state
->vector
[0].iov_base
= base
;
740 state
->vector
[0].iov_len
-= left
;
743 vector
[count
] = state
->vector
[0];
745 left
-= state
->vector
[0].iov_len
;
752 * if the message is longer than the buffers the caller
753 * requested, we need to consume the rest of the message
754 * into the pending buffer, where the next readv can
757 npas
->pending
.iov_base
= talloc_array(npas
, uint8_t, left
);
758 if (!npas
->pending
.iov_base
) {
761 npas
->pending
.iov_len
= left
;
763 vector
[count
] = npas
->pending
;
767 state
->ret
+= (msg_len
- left
);
774 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
776 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
781 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
784 tevent_req_error(req
, sys_errno
);
789 * we do not set state->ret here as ret includes the headr size.
790 * we set it in tstream_npa_readv_pdu_next_vector()
793 tevent_req_done(req
);
796 static int tstream_npa_readv_recv(struct tevent_req
*req
,
799 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
800 struct tstream_npa_readv_state
);
803 ret
= tsocket_simple_int_recv(req
, perrno
);
808 tevent_req_received(req
);
812 struct tstream_npa_writev_state
{
813 const struct iovec
*vector
;
816 /* the header for message mode */
823 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
825 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
826 struct tevent_context
*ev
,
827 struct tstream_context
*stream
,
828 const struct iovec
*vector
,
831 struct tevent_req
*req
;
832 struct tstream_npa_writev_state
*state
;
833 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
834 struct tevent_req
*subreq
;
837 struct iovec
*new_vector
;
839 req
= tevent_req_create(mem_ctx
, &state
,
840 struct tstream_npa_writev_state
);
847 if (!npas
->unix_stream
) {
848 tevent_req_error(req
, ENOTCONN
);
852 switch (npas
->file_type
) {
853 case FILE_TYPE_BYTE_MODE_PIPE
:
854 state
->hdr_used
= false;
855 state
->vector
= vector
;
856 state
->count
= count
;
859 case FILE_TYPE_MESSAGE_MODE_PIPE
:
861 * we make a copy of the vector and prepend a header
864 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
865 if (tevent_req_nomem(new_vector
, req
)) {
868 new_vector
[0].iov_base
= state
->hdr
;
869 new_vector
[0].iov_len
= sizeof(state
->hdr
);
870 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
872 state
->hdr_used
= true;
873 state
->vector
= new_vector
;
874 state
->count
= count
+ 1;
877 for (i
=0; i
< count
; i
++) {
878 msg_len
+= vector
[i
].iov_len
;
881 if (msg_len
> UINT16_MAX
) {
882 tevent_req_error(req
, EMSGSIZE
);
886 SSVAL(state
->hdr
, 0, msg_len
);
890 subreq
= tstream_writev_send(state
,
895 if (tevent_req_nomem(subreq
, req
)) {
898 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
903 tevent_req_post(req
, ev
);
907 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
909 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
911 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
912 struct tstream_npa_writev_state
);
916 ret
= tstream_writev_recv(subreq
, &sys_errno
);
919 tevent_req_error(req
, sys_errno
);
924 * in message mode we need to hide the length
925 * of the hdr from the caller
927 if (state
->hdr_used
) {
928 ret
-= sizeof(state
->hdr
);
933 tevent_req_done(req
);
936 static int tstream_npa_writev_recv(struct tevent_req
*req
,
939 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
940 struct tstream_npa_writev_state
);
943 ret
= tsocket_simple_int_recv(req
, perrno
);
948 tevent_req_received(req
);
952 struct tstream_npa_disconnect_state
{
953 struct tstream_context
*stream
;
956 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
958 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
959 struct tevent_context
*ev
,
960 struct tstream_context
*stream
)
962 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
963 struct tevent_req
*req
;
964 struct tstream_npa_disconnect_state
*state
;
965 struct tevent_req
*subreq
;
967 req
= tevent_req_create(mem_ctx
, &state
,
968 struct tstream_npa_disconnect_state
);
973 state
->stream
= stream
;
975 if (!npas
->unix_stream
) {
976 tevent_req_error(req
, ENOTCONN
);
980 subreq
= tstream_disconnect_send(state
,
983 if (tevent_req_nomem(subreq
, req
)) {
986 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
991 tevent_req_post(req
, ev
);
995 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
997 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
999 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
1000 struct tstream_npa_disconnect_state
);
1001 struct tstream_context
*stream
= state
->stream
;
1002 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
1006 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
1007 TALLOC_FREE(subreq
);
1009 tevent_req_error(req
, sys_errno
);
1013 TALLOC_FREE(npas
->unix_stream
);
1015 tevent_req_done(req
);
1018 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
1023 ret
= tsocket_simple_int_recv(req
, perrno
);
1025 tevent_req_received(req
);
1029 static const struct tstream_context_ops tstream_npa_ops
= {
1032 .pending_bytes
= tstream_npa_pending_bytes
,
1034 .readv_send
= tstream_npa_readv_send
,
1035 .readv_recv
= tstream_npa_readv_recv
,
1037 .writev_send
= tstream_npa_writev_send
,
1038 .writev_recv
= tstream_npa_writev_recv
,
1040 .disconnect_send
= tstream_npa_disconnect_send
,
1041 .disconnect_recv
= tstream_npa_disconnect_recv
,
1044 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1047 struct tstream_context
**_stream
,
1048 const char *location
)
1050 struct tstream_context
*stream
;
1051 struct tstream_npa
*npas
;
1054 switch (file_type
) {
1055 case FILE_TYPE_BYTE_MODE_PIPE
:
1057 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1064 stream
= tstream_context_create(mem_ctx
,
1074 npas
->file_type
= file_type
;
1076 ret
= tstream_bsd_existing_socket(stream
, fd
,
1077 &npas
->unix_stream
);
1079 int saved_errno
= errno
;
1080 talloc_free(stream
);
1081 errno
= saved_errno
;
1090 struct tstream_npa_accept_state
{
1091 struct tevent_context
*ev
;
1092 struct tstream_context
*plain
;
1094 uint16_t device_state
;
1095 uint64_t alloc_size
;
1098 struct iovec out_iov
;
1101 NTSTATUS accept_status
;
1102 struct tsocket_address
*client
;
1104 struct tsocket_address
*server
;
1106 struct netr_SamInfo3
*info3
;
1107 DATA_BLOB session_key
;
1108 DATA_BLOB delegated_creds
;
1111 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1113 TALLOC_CTX
*mem_ctx
,
1114 struct iovec
**_vector
,
1116 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1117 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1119 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1120 struct tevent_context
*ev
,
1121 struct tstream_context
*plain
,
1123 uint16_t device_state
,
1124 uint64_t allocation_size
)
1126 struct tstream_npa_accept_state
*state
;
1127 struct tevent_req
*req
, *subreq
;
1129 req
= tevent_req_create(mem_ctx
, &state
,
1130 struct tstream_npa_accept_state
);
1135 switch (file_type
) {
1136 case FILE_TYPE_BYTE_MODE_PIPE
:
1138 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1141 tevent_req_error(req
, EINVAL
);
1145 ZERO_STRUCTP(state
);
1148 state
->plain
= plain
;
1149 state
->file_type
= file_type
;
1150 state
->device_state
= device_state
;
1151 state
->alloc_size
= allocation_size
;
1154 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1155 * named_pipe_full_request provides the pdu length then.
1157 subreq
= tstream_readv_pdu_send(state
, ev
, plain
,
1158 tstream_npa_accept_next_vector
,
1160 if (tevent_req_nomem(subreq
, req
)) {
1164 tevent_req_set_callback(subreq
,
1165 tstream_npa_accept_existing_reply
, req
);
1170 tevent_req_post(req
, ev
);
1174 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1176 TALLOC_CTX
*mem_ctx
,
1177 struct iovec
**_vector
,
1180 struct tstream_npa_accept_state
*state
=
1181 talloc_get_type_abort(private_data
,
1182 struct tstream_npa_accept_state
);
1183 struct iovec
*vector
;
1187 if (state
->npa_blob
.length
== 0) {
1188 state
->npa_blob
= data_blob_talloc(state
, NULL
, 4);
1189 if (!state
->npa_blob
.data
) {
1192 } else if (state
->npa_blob
.length
== 4) {
1197 msg_len
= RIVAL(state
->npa_blob
.data
, 0);
1199 if (msg_len
> 0x00FFFFFF) {
1211 state
->npa_blob
.data
= talloc_realloc(state
,
1212 state
->npa_blob
.data
,
1214 if (!state
->npa_blob
.data
) {
1217 state
->npa_blob
.length
= msg_len
;
1219 if (memcmp(&state
->npa_blob
.data
[4],
1220 NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1221 DEBUG(0, ("Wrong protocol\n"));
1222 #if defined(EPROTONOSUPPORT)
1223 errno
= EPROTONOSUPPORT
;
1224 #elif defined(EPROTO)
1236 /* we need to get a message header */
1237 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1241 vector
[0].iov_base
= state
->npa_blob
.data
+ ofs
;
1242 vector
[0].iov_len
= state
->npa_blob
.length
- ofs
;
1250 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1252 struct tevent_req
*req
=
1253 tevent_req_callback_data(subreq
, struct tevent_req
);
1254 struct tstream_npa_accept_state
*state
=
1255 tevent_req_data(req
, struct tstream_npa_accept_state
);
1256 struct named_pipe_auth_req
*pipe_request
;
1257 struct named_pipe_auth_rep pipe_reply
;
1258 struct named_pipe_auth_req_info3 i3
;
1259 enum ndr_err_code ndr_err
;
1264 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
1265 TALLOC_FREE(subreq
);
1267 tevent_req_error(req
, sys_errno
);
1271 DEBUG(10, ("Received packet of length %lu\n",
1272 (long)state
->npa_blob
.length
));
1273 dump_data(11, state
->npa_blob
.data
, state
->npa_blob
.length
);
1275 ZERO_STRUCT(pipe_reply
);
1276 pipe_reply
.level
= 0;
1277 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1279 * TODO: check it's a root (uid == 0) pipe
1282 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1283 if (!pipe_request
) {
1284 DEBUG(0, ("Out of memory!\n"));
1288 /* parse the passed credentials */
1289 ndr_err
= ndr_pull_struct_blob_all(
1290 &state
->npa_blob
, pipe_request
, pipe_request
,
1291 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1292 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1293 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1294 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1295 nt_errstr(pipe_reply
.status
)));
1300 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1305 switch (pipe_request
->level
) {
1307 pipe_reply
.level
= 0;
1308 pipe_reply
.status
= NT_STATUS_OK
;
1310 /* we need to force byte mode in this level */
1311 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1315 pipe_reply
.level
= 1;
1316 pipe_reply
.status
= NT_STATUS_OK
;
1318 /* We must copy net3_SamInfo3, so that
1319 * info3 is an actual talloc pointer, then we steal
1320 * pipe_request on info3 so that all the allocated memory
1321 * pointed by the structrue members is preserved */
1322 state
->info3
= (struct netr_SamInfo3
*)talloc_memdup(state
,
1323 &pipe_request
->info
.info1
,
1324 sizeof(struct netr_SamInfo3
));
1325 if (!state
->info3
) {
1326 pipe_reply
.status
= NT_STATUS_NO_MEMORY
;
1327 DEBUG(0, ("Out of memory!\n"));
1330 talloc_steal(state
->info3
, pipe_request
);
1332 /* we need to force byte mode in this level */
1333 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1337 pipe_reply
.level
= 2;
1338 pipe_reply
.status
= NT_STATUS_OK
;
1339 pipe_reply
.info
.info2
.file_type
= state
->file_type
;
1340 pipe_reply
.info
.info2
.device_state
= state
->device_state
;
1341 pipe_reply
.info
.info2
.allocation_size
= state
->alloc_size
;
1343 i3
.client_name
= pipe_request
->info
.info2
.client_name
;
1344 i3
.client_addr
= pipe_request
->info
.info2
.client_addr
;
1345 i3
.client_port
= pipe_request
->info
.info2
.client_port
;
1346 i3
.server_name
= pipe_request
->info
.info2
.server_name
;
1347 i3
.server_addr
= pipe_request
->info
.info2
.server_addr
;
1348 i3
.server_port
= pipe_request
->info
.info2
.server_port
;
1349 i3
.sam_info3
= pipe_request
->info
.info2
.sam_info3
;
1350 i3
.session_key_length
=
1351 pipe_request
->info
.info2
.session_key_length
;
1352 i3
.session_key
= pipe_request
->info
.info2
.session_key
;
1356 pipe_reply
.level
= 3;
1357 pipe_reply
.status
= NT_STATUS_OK
;
1358 pipe_reply
.info
.info3
.file_type
= state
->file_type
;
1359 pipe_reply
.info
.info3
.device_state
= state
->device_state
;
1360 pipe_reply
.info
.info3
.allocation_size
= state
->alloc_size
;
1362 i3
= pipe_request
->info
.info3
;
1366 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1367 pipe_reply
.level
= 0;
1368 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1372 if (pipe_reply
.level
>=2) {
1374 if (i3
.server_addr
== NULL
) {
1375 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1376 DEBUG(2, ("Missing server address\n"));
1379 if (i3
.client_addr
== NULL
) {
1380 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1381 DEBUG(2, ("Missing client address\n"));
1385 state
->server_name
= discard_const_p(char,
1386 talloc_move(state
, &i3
.server_name
));
1387 ret
= tsocket_address_inet_from_strings(state
, "ip",
1392 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1393 i3
.server_addr
, i3
.server_port
,
1395 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1399 state
->client_name
= discard_const_p(char,
1400 talloc_move(state
, &i3
.client_name
));
1401 ret
= tsocket_address_inet_from_strings(state
, "ip",
1406 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1407 i3
.client_addr
, i3
.client_port
,
1409 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1413 state
->info3
= talloc_move(state
, &i3
.sam_info3
);
1414 state
->session_key
.data
= talloc_move(state
, &i3
.session_key
);
1415 state
->session_key
.length
= i3
.session_key_length
;
1418 if (pipe_reply
.level
>= 3) {
1419 state
->delegated_creds
.data
=
1420 talloc_move(state
, &i3
.gssapi_delegated_creds
);
1421 state
->delegated_creds
.length
=
1422 i3
.gssapi_delegated_creds_length
;
1426 /* create the output */
1427 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1428 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1429 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1430 DEBUG(2, ("Error encoding structure: %s",
1431 ndr_map_error2string(ndr_err
)));
1432 tevent_req_error(req
, EIO
);
1436 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1437 dump_data(11, out
.data
, out
.length
);
1440 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1443 state
->accept_status
= pipe_reply
.status
;
1445 state
->out_iov
.iov_base
= out
.data
;
1446 state
->out_iov
.iov_len
= out
.length
;
1448 subreq
= tstream_writev_send(state
, state
->ev
,
1450 &state
->out_iov
, 1);
1451 if (tevent_req_nomem(subreq
, req
)) {
1452 DEBUG(0, ("no memory for tstream_writev_send"));
1456 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1459 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1461 struct tevent_req
*req
=
1462 tevent_req_callback_data(subreq
, struct tevent_req
);
1466 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1467 TALLOC_FREE(subreq
);
1469 tevent_req_error(req
, sys_errno
);
1473 tevent_req_done(req
);
1476 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1478 TALLOC_CTX
*mem_ctx
,
1479 struct tstream_context
**stream
,
1480 struct tsocket_address
**client
,
1481 char **_client_name
,
1482 struct tsocket_address
**server
,
1484 struct netr_SamInfo3
**info3
,
1485 DATA_BLOB
*session_key
,
1486 DATA_BLOB
*delegated_creds
,
1487 const char *location
)
1489 struct tstream_npa_accept_state
*state
=
1490 tevent_req_data(req
, struct tstream_npa_accept_state
);
1491 struct tstream_npa
*npas
;
1494 ret
= tsocket_simple_int_recv(req
, perrno
);
1496 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1497 strerror(*perrno
)));
1498 tevent_req_received(req
);
1502 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1503 #if defined(EPROTONOSUPPORT)
1504 *perrno
= EPROTONOSUPPORT
;
1505 #elif defined(EPROTO)
1510 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1511 nt_errstr(state
->accept_status
),
1512 strerror(*perrno
)));
1513 tevent_req_received(req
);
1517 *stream
= tstream_context_create(mem_ctx
,
1524 tevent_req_received(req
);
1528 npas
->unix_stream
= state
->plain
;
1529 npas
->file_type
= state
->file_type
;
1531 *client
= talloc_move(mem_ctx
, &state
->client
);
1532 *_client_name
= talloc_move(mem_ctx
, &state
->client_name
);
1533 *server
= talloc_move(mem_ctx
, &state
->server
);
1534 *server_name
= talloc_move(mem_ctx
, &state
->server_name
);
1535 *info3
= talloc_move(mem_ctx
, &state
->info3
);
1536 *session_key
= state
->session_key
;
1537 talloc_steal(mem_ctx
, state
->session_key
.data
);
1538 *delegated_creds
= state
->delegated_creds
;
1539 talloc_steal(mem_ctx
, state
->delegated_creds
.data
);
1541 tevent_req_received(req
);