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 netr_SamInfo3
*sam_info3
,
70 DATA_BLOB session_key
,
71 DATA_BLOB delegated_creds
)
73 struct tevent_req
*req
;
74 struct tstream_npa_connect_state
*state
;
75 struct tevent_req
*subreq
;
77 enum ndr_err_code ndr_err
;
78 char *lower_case_npipe
;
80 req
= tevent_req_create(mem_ctx
, &state
,
81 struct tstream_npa_connect_state
);
86 state
->caller
.ev
= ev
;
88 lower_case_npipe
= strlower_talloc(state
, npipe
);
89 if (tevent_req_nomem(lower_case_npipe
, req
)) {
93 state
->unix_path
= talloc_asprintf(state
, "%s/%s",
96 talloc_free(lower_case_npipe
);
97 if (tevent_req_nomem(state
->unix_path
, req
)) {
101 ret
= tsocket_address_unix_from_path(state
,
105 tevent_req_error(req
, errno
);
109 ret
= tsocket_address_unix_from_path(state
,
113 tevent_req_error(req
, errno
);
117 ZERO_STRUCT(state
->auth_req
);
119 struct named_pipe_auth_req_info3
*info3
;
122 tevent_req_error(req
, EINVAL
);
126 state
->auth_req
.level
= 3;
127 info3
= &state
->auth_req
.info
.info3
;
129 info3
->client_name
= client_name_in
;
130 info3
->client_addr
= tsocket_address_inet_addr_string(client
, state
);
131 if (!info3
->client_addr
) {
132 /* errno might be EINVAL */
133 tevent_req_error(req
, errno
);
136 info3
->client_port
= tsocket_address_inet_port(client
);
137 if (!info3
->client_name
) {
138 info3
->client_name
= info3
->client_addr
;
141 info3
->server_addr
= tsocket_address_inet_addr_string(server
, state
);
142 if (!info3
->server_addr
) {
143 /* errno might be EINVAL */
144 tevent_req_error(req
, errno
);
147 info3
->server_port
= tsocket_address_inet_port(server
);
148 if (!info3
->server_name
) {
149 info3
->server_name
= info3
->server_addr
;
152 info3
->sam_info3
= discard_const_p(struct netr_SamInfo3
, sam_info3
);
153 info3
->session_key_length
= session_key
.length
;
154 info3
->session_key
= session_key
.data
;
155 info3
->gssapi_delegated_creds_length
= delegated_creds
.length
;
156 info3
->gssapi_delegated_creds
= delegated_creds
.data
;
158 } else if (sam_info3
) {
159 state
->auth_req
.level
= 1;
160 state
->auth_req
.info
.info1
= *sam_info3
;
162 state
->auth_req
.level
= 0;
166 NDR_PRINT_DEBUG(named_pipe_auth_req
, &state
->auth_req
);
169 ndr_err
= ndr_push_struct_blob(&state
->auth_req_blob
,
170 state
, &state
->auth_req
,
171 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_req
);
172 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
173 tevent_req_error(req
, EINVAL
);
177 state
->auth_req_iov
.iov_base
= (char *) state
->auth_req_blob
.data
;
178 state
->auth_req_iov
.iov_len
= state
->auth_req_blob
.length
;
180 subreq
= tstream_unix_connect_send(state
,
184 if (tevent_req_nomem(subreq
, req
)) {
187 tevent_req_set_callback(subreq
, tstream_npa_connect_unix_done
, req
);
192 tevent_req_post(req
, ev
);
196 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
);
198 static void tstream_npa_connect_unix_done(struct tevent_req
*subreq
)
200 struct tevent_req
*req
=
201 tevent_req_callback_data(subreq
,
203 struct tstream_npa_connect_state
*state
=
205 struct tstream_npa_connect_state
);
209 ret
= tstream_unix_connect_recv(subreq
, &sys_errno
,
210 state
, &state
->unix_stream
);
213 tevent_req_error(req
, sys_errno
);
217 subreq
= tstream_writev_send(state
,
220 &state
->auth_req_iov
, 1);
221 if (tevent_req_nomem(subreq
, req
)) {
224 tevent_req_set_callback(subreq
, tstream_npa_connect_writev_done
, req
);
227 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
230 struct iovec
**_vector
,
232 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
);
234 static void tstream_npa_connect_writev_done(struct tevent_req
*subreq
)
236 struct tevent_req
*req
=
237 tevent_req_callback_data(subreq
,
239 struct tstream_npa_connect_state
*state
=
241 struct tstream_npa_connect_state
);
245 ret
= tstream_writev_recv(subreq
, &sys_errno
);
248 tevent_req_error(req
, sys_errno
);
252 state
->auth_rep_blob
= data_blob_const(NULL
, 0);
254 subreq
= tstream_readv_pdu_send(state
, state
->caller
.ev
,
256 tstream_npa_connect_next_vector
,
258 if (tevent_req_nomem(subreq
, req
)) {
261 tevent_req_set_callback(subreq
, tstream_npa_connect_readv_done
, req
);
264 static int tstream_npa_connect_next_vector(struct tstream_context
*unix_stream
,
267 struct iovec
**_vector
,
270 struct tstream_npa_connect_state
*state
= talloc_get_type_abort(private_data
,
271 struct tstream_npa_connect_state
);
272 struct iovec
*vector
;
276 if (state
->auth_rep_blob
.length
== 0) {
277 state
->auth_rep_blob
= data_blob_talloc(state
, NULL
, 4);
278 if (!state
->auth_rep_blob
.data
) {
281 } else if (state
->auth_rep_blob
.length
== 4) {
286 msg_len
= RIVAL(state
->auth_rep_blob
.data
, 0);
288 if (msg_len
> 0x00FFFFFF) {
300 state
->auth_rep_blob
.data
= talloc_realloc(state
,
301 state
->auth_rep_blob
.data
,
303 if (!state
->auth_rep_blob
.data
) {
306 state
->auth_rep_blob
.length
= msg_len
;
313 /* we need to get a message header */
314 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
318 vector
[0].iov_base
= (char *) (state
->auth_rep_blob
.data
+ ofs
);
319 vector
[0].iov_len
= state
->auth_rep_blob
.length
- ofs
;
327 static void tstream_npa_connect_readv_done(struct tevent_req
*subreq
)
329 struct tevent_req
*req
=
330 tevent_req_callback_data(subreq
,
332 struct tstream_npa_connect_state
*state
=
334 struct tstream_npa_connect_state
);
337 enum ndr_err_code ndr_err
;
339 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
342 tevent_req_error(req
, sys_errno
);
346 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
347 (uint32_t)state
->auth_rep_blob
.length
));
348 dump_data(11, state
->auth_rep_blob
.data
, state
->auth_rep_blob
.length
);
350 ndr_err
= ndr_pull_struct_blob(
351 &state
->auth_rep_blob
, state
,
353 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_rep
);
355 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
356 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
357 ndr_map_error2string(ndr_err
)));
358 tevent_req_error(req
, EIO
);
363 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &state
->auth_rep
);
366 if (state
->auth_rep
.length
< 16) {
367 DEBUG(0, ("req invalid length: %u < 16\n",
368 state
->auth_rep
.length
));
369 tevent_req_error(req
, EIO
);
373 if (strcmp(NAMED_PIPE_AUTH_MAGIC
, state
->auth_rep
.magic
) != 0) {
374 DEBUG(0, ("req invalid magic: %s != %s\n",
375 state
->auth_rep
.magic
, NAMED_PIPE_AUTH_MAGIC
));
376 tevent_req_error(req
, EIO
);
380 if (!NT_STATUS_IS_OK(state
->auth_rep
.status
)) {
381 DEBUG(0, ("req failed: %s\n",
382 nt_errstr(state
->auth_rep
.status
)));
383 tevent_req_error(req
, EACCES
);
387 if (state
->auth_rep
.level
!= state
->auth_req
.level
) {
388 DEBUG(0, ("req invalid level: %u != %u\n",
389 state
->auth_rep
.level
, state
->auth_req
.level
));
390 tevent_req_error(req
, EIO
);
394 tevent_req_done(req
);
397 int _tstream_npa_connect_recv(struct tevent_req
*req
,
400 struct tstream_context
**_stream
,
401 uint16_t *_file_type
,
402 uint16_t *_device_state
,
403 uint64_t *_allocation_size
,
404 const char *location
)
406 struct tstream_npa_connect_state
*state
=
408 struct tstream_npa_connect_state
);
409 struct tstream_context
*stream
;
410 struct tstream_npa
*npas
;
411 uint16_t device_state
= 0;
412 uint64_t allocation_size
= 0;
414 if (tevent_req_is_unix_error(req
, perrno
)) {
415 tevent_req_received(req
);
419 stream
= tstream_context_create(mem_ctx
,
426 tevent_req_received(req
);
431 npas
->unix_stream
= talloc_move(stream
, &state
->unix_stream
);
432 switch (state
->auth_rep
.level
) {
435 npas
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
436 device_state
= 0x00ff;
437 allocation_size
= 2048;
440 npas
->file_type
= state
->auth_rep
.info
.info2
.file_type
;
441 device_state
= state
->auth_rep
.info
.info2
.device_state
;
442 allocation_size
= state
->auth_rep
.info
.info2
.allocation_size
;
445 npas
->file_type
= state
->auth_rep
.info
.info3
.file_type
;
446 device_state
= state
->auth_rep
.info
.info3
.device_state
;
447 allocation_size
= state
->auth_rep
.info
.info3
.allocation_size
;
452 *_file_type
= npas
->file_type
;
453 *_device_state
= device_state
;
454 *_allocation_size
= allocation_size
;
455 tevent_req_received(req
);
459 static ssize_t
tstream_npa_pending_bytes(struct tstream_context
*stream
)
461 struct tstream_npa
*npas
= tstream_context_data(stream
,
465 if (!npas
->unix_stream
) {
470 switch (npas
->file_type
) {
471 case FILE_TYPE_BYTE_MODE_PIPE
:
472 ret
= tstream_pending_bytes(npas
->unix_stream
);
475 case FILE_TYPE_MESSAGE_MODE_PIPE
:
476 ret
= npas
->pending
.iov_len
;
486 struct tstream_npa_readv_state
{
487 struct tstream_context
*stream
;
489 struct iovec
*vector
;
492 /* the header for message mode */
499 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
);
500 static int tstream_npa_readv_next_vector(struct tstream_context
*stream
,
503 struct iovec
**_vector
,
505 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
);
507 static struct tevent_req
*tstream_npa_readv_send(TALLOC_CTX
*mem_ctx
,
508 struct tevent_context
*ev
,
509 struct tstream_context
*stream
,
510 struct iovec
*vector
,
513 struct tevent_req
*req
;
514 struct tstream_npa_readv_state
*state
;
515 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
516 struct tevent_req
*subreq
;
521 req
= tevent_req_create(mem_ctx
, &state
,
522 struct tstream_npa_readv_state
);
527 state
->stream
= stream
;
530 if (!npas
->unix_stream
) {
531 tevent_req_error(req
, ENOTCONN
);
535 switch (npas
->file_type
) {
536 case FILE_TYPE_BYTE_MODE_PIPE
:
537 state
->vector
= vector
;
538 state
->count
= count
;
540 subreq
= tstream_readv_send(state
,
545 if (tevent_req_nomem(subreq
,req
)) {
548 tevent_req_set_callback(subreq
,
549 tstream_npa_readv_byte_mode_handler
,
554 case FILE_TYPE_MESSAGE_MODE_PIPE
:
556 * we make a copy of the vector and prepend a header
559 state
->vector
= talloc_array(state
, struct iovec
, count
);
560 if (tevent_req_nomem(state
->vector
, req
)) {
563 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
564 state
->count
= count
;
567 * copy the pending buffer first
570 left
= npas
->pending
.iov_len
;
571 pbase
= (uint8_t *)npas
->pending
.iov_base
;
573 while (left
> 0 && state
->count
> 0) {
575 base
= (uint8_t *)state
->vector
[0].iov_base
;
576 if (left
< state
->vector
[0].iov_len
) {
577 memcpy(base
, pbase
+ ofs
, left
);
580 state
->vector
[0].iov_base
= (char *) base
;
581 state
->vector
[0].iov_len
-= left
;
586 ZERO_STRUCT(npas
->pending
);
589 memcpy(base
, pbase
+ ofs
, state
->vector
[0].iov_len
);
591 ofs
+= state
->vector
[0].iov_len
;
592 left
-= state
->vector
[0].iov_len
;
598 ZERO_STRUCT(npas
->pending
);
604 memmove(pbase
, pbase
+ ofs
, left
);
605 npas
->pending
.iov_base
= (char *) pbase
;
606 npas
->pending
.iov_len
= left
;
608 * this cannot fail and even if it
609 * fails we can handle it
611 pbase
= talloc_realloc(npas
, pbase
, uint8_t, left
);
613 npas
->pending
.iov_base
= (char *) pbase
;
620 if (state
->count
== 0) {
621 tevent_req_done(req
);
625 ZERO_STRUCT(state
->hdr
);
626 state
->wait_for_hdr
= false;
628 subreq
= tstream_readv_pdu_send(state
,
631 tstream_npa_readv_next_vector
,
633 if (tevent_req_nomem(subreq
, req
)) {
636 tevent_req_set_callback(subreq
,
637 tstream_npa_readv_msg_mode_handler
,
643 /* this can't happen */
644 tevent_req_error(req
, EINVAL
);
648 tevent_req_post(req
, ev
);
652 static void tstream_npa_readv_byte_mode_handler(struct tevent_req
*subreq
)
654 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
656 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
657 struct tstream_npa_readv_state
);
661 ret
= tstream_readv_recv(subreq
, &sys_errno
);
664 tevent_req_error(req
, sys_errno
);
670 tevent_req_done(req
);
673 static int tstream_npa_readv_next_vector(struct tstream_context
*unix_stream
,
676 struct iovec
**_vector
,
679 struct tstream_npa_readv_state
*state
= talloc_get_type_abort(private_data
,
680 struct tstream_npa_readv_state
);
681 struct tstream_npa
*npas
= tstream_context_data(state
->stream
,
683 struct iovec
*vector
;
688 if (state
->count
== 0) {
694 if (!state
->wait_for_hdr
) {
695 /* we need to get a message header */
696 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
700 ZERO_STRUCT(state
->hdr
);
701 vector
[0].iov_base
= (char *) state
->hdr
;
702 vector
[0].iov_len
= sizeof(state
->hdr
);
706 state
->wait_for_hdr
= true;
713 /* and now fill the callers buffers and maybe the pending buffer */
714 state
->wait_for_hdr
= false;
716 msg_len
= SVAL(state
->hdr
, 0);
723 state
->wait_for_hdr
= false;
725 /* +1 because we may need to fill the pending buffer */
726 vector
= talloc_array(mem_ctx
, struct iovec
, state
->count
+ 1);
733 while (left
> 0 && state
->count
> 0) {
734 if (left
< state
->vector
[0].iov_len
) {
736 base
= (uint8_t *)state
->vector
[0].iov_base
;
737 vector
[count
].iov_base
= (char *) base
;
738 vector
[count
].iov_len
= left
;
741 state
->vector
[0].iov_base
= (char *) base
;
742 state
->vector
[0].iov_len
-= left
;
745 vector
[count
] = state
->vector
[0];
747 left
-= state
->vector
[0].iov_len
;
754 * if the message is longer than the buffers the caller
755 * requested, we need to consume the rest of the message
756 * into the pending buffer, where the next readv can
759 npas
->pending
.iov_base
= talloc_array(npas
, char, left
);
760 if (!npas
->pending
.iov_base
) {
763 npas
->pending
.iov_len
= left
;
765 vector
[count
] = npas
->pending
;
769 state
->ret
+= (msg_len
- left
);
776 static void tstream_npa_readv_msg_mode_handler(struct tevent_req
*subreq
)
778 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
783 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
786 tevent_req_error(req
, sys_errno
);
791 * we do not set state->ret here as ret includes the headr size.
792 * we set it in tstream_npa_readv_pdu_next_vector()
795 tevent_req_done(req
);
798 static int tstream_npa_readv_recv(struct tevent_req
*req
,
801 struct tstream_npa_readv_state
*state
= tevent_req_data(req
,
802 struct tstream_npa_readv_state
);
805 ret
= tsocket_simple_int_recv(req
, perrno
);
810 tevent_req_received(req
);
814 struct tstream_npa_writev_state
{
815 const struct iovec
*vector
;
818 /* the header for message mode */
825 static void tstream_npa_writev_handler(struct tevent_req
*subreq
);
827 static struct tevent_req
*tstream_npa_writev_send(TALLOC_CTX
*mem_ctx
,
828 struct tevent_context
*ev
,
829 struct tstream_context
*stream
,
830 const struct iovec
*vector
,
833 struct tevent_req
*req
;
834 struct tstream_npa_writev_state
*state
;
835 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
836 struct tevent_req
*subreq
;
839 struct iovec
*new_vector
;
841 req
= tevent_req_create(mem_ctx
, &state
,
842 struct tstream_npa_writev_state
);
849 if (!npas
->unix_stream
) {
850 tevent_req_error(req
, ENOTCONN
);
854 switch (npas
->file_type
) {
855 case FILE_TYPE_BYTE_MODE_PIPE
:
856 state
->hdr_used
= false;
857 state
->vector
= vector
;
858 state
->count
= count
;
861 case FILE_TYPE_MESSAGE_MODE_PIPE
:
863 * we make a copy of the vector and prepend a header
866 new_vector
= talloc_array(state
, struct iovec
, count
+ 1);
867 if (tevent_req_nomem(new_vector
, req
)) {
870 new_vector
[0].iov_base
= (char *) state
->hdr
;
871 new_vector
[0].iov_len
= sizeof(state
->hdr
);
872 memcpy(new_vector
+ 1, vector
, sizeof(struct iovec
)*count
);
874 state
->hdr_used
= true;
875 state
->vector
= new_vector
;
876 state
->count
= count
+ 1;
879 for (i
=0; i
< count
; i
++) {
880 msg_len
+= vector
[i
].iov_len
;
883 if (msg_len
> UINT16_MAX
) {
884 tevent_req_error(req
, EMSGSIZE
);
888 SSVAL(state
->hdr
, 0, msg_len
);
892 subreq
= tstream_writev_send(state
,
897 if (tevent_req_nomem(subreq
, req
)) {
900 tevent_req_set_callback(subreq
, tstream_npa_writev_handler
, req
);
905 tevent_req_post(req
, ev
);
909 static void tstream_npa_writev_handler(struct tevent_req
*subreq
)
911 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
913 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
914 struct tstream_npa_writev_state
);
918 ret
= tstream_writev_recv(subreq
, &sys_errno
);
921 tevent_req_error(req
, sys_errno
);
926 * in message mode we need to hide the length
927 * of the hdr from the caller
929 if (state
->hdr_used
) {
930 ret
-= sizeof(state
->hdr
);
935 tevent_req_done(req
);
938 static int tstream_npa_writev_recv(struct tevent_req
*req
,
941 struct tstream_npa_writev_state
*state
= tevent_req_data(req
,
942 struct tstream_npa_writev_state
);
945 ret
= tsocket_simple_int_recv(req
, perrno
);
950 tevent_req_received(req
);
954 struct tstream_npa_disconnect_state
{
955 struct tstream_context
*stream
;
958 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
);
960 static struct tevent_req
*tstream_npa_disconnect_send(TALLOC_CTX
*mem_ctx
,
961 struct tevent_context
*ev
,
962 struct tstream_context
*stream
)
964 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
965 struct tevent_req
*req
;
966 struct tstream_npa_disconnect_state
*state
;
967 struct tevent_req
*subreq
;
969 req
= tevent_req_create(mem_ctx
, &state
,
970 struct tstream_npa_disconnect_state
);
975 state
->stream
= stream
;
977 if (!npas
->unix_stream
) {
978 tevent_req_error(req
, ENOTCONN
);
982 subreq
= tstream_disconnect_send(state
,
985 if (tevent_req_nomem(subreq
, req
)) {
988 tevent_req_set_callback(subreq
, tstream_npa_disconnect_handler
, req
);
993 tevent_req_post(req
, ev
);
997 static void tstream_npa_disconnect_handler(struct tevent_req
*subreq
)
999 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
1001 struct tstream_npa_disconnect_state
*state
= tevent_req_data(req
,
1002 struct tstream_npa_disconnect_state
);
1003 struct tstream_context
*stream
= state
->stream
;
1004 struct tstream_npa
*npas
= tstream_context_data(stream
, struct tstream_npa
);
1008 ret
= tstream_disconnect_recv(subreq
, &sys_errno
);
1009 TALLOC_FREE(subreq
);
1011 tevent_req_error(req
, sys_errno
);
1015 TALLOC_FREE(npas
->unix_stream
);
1017 tevent_req_done(req
);
1020 static int tstream_npa_disconnect_recv(struct tevent_req
*req
,
1025 ret
= tsocket_simple_int_recv(req
, perrno
);
1027 tevent_req_received(req
);
1031 static const struct tstream_context_ops tstream_npa_ops
= {
1034 .pending_bytes
= tstream_npa_pending_bytes
,
1036 .readv_send
= tstream_npa_readv_send
,
1037 .readv_recv
= tstream_npa_readv_recv
,
1039 .writev_send
= tstream_npa_writev_send
,
1040 .writev_recv
= tstream_npa_writev_recv
,
1042 .disconnect_send
= tstream_npa_disconnect_send
,
1043 .disconnect_recv
= tstream_npa_disconnect_recv
,
1046 int _tstream_npa_existing_socket(TALLOC_CTX
*mem_ctx
,
1049 struct tstream_context
**_stream
,
1050 const char *location
)
1052 struct tstream_context
*stream
;
1053 struct tstream_npa
*npas
;
1056 switch (file_type
) {
1057 case FILE_TYPE_BYTE_MODE_PIPE
:
1059 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1066 stream
= tstream_context_create(mem_ctx
,
1076 npas
->file_type
= file_type
;
1078 ret
= tstream_bsd_existing_socket(stream
, fd
,
1079 &npas
->unix_stream
);
1081 int saved_errno
= errno
;
1082 talloc_free(stream
);
1083 errno
= saved_errno
;
1092 struct tstream_npa_accept_state
{
1093 struct tevent_context
*ev
;
1094 struct tstream_context
*plain
;
1096 uint16_t device_state
;
1097 uint64_t alloc_size
;
1100 struct iovec out_iov
;
1103 NTSTATUS accept_status
;
1104 struct tsocket_address
*client
;
1106 struct tsocket_address
*server
;
1108 struct netr_SamInfo3
*info3
;
1109 DATA_BLOB session_key
;
1110 DATA_BLOB delegated_creds
;
1113 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1115 TALLOC_CTX
*mem_ctx
,
1116 struct iovec
**_vector
,
1118 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
);
1119 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
);
1121 struct tevent_req
*tstream_npa_accept_existing_send(TALLOC_CTX
*mem_ctx
,
1122 struct tevent_context
*ev
,
1123 struct tstream_context
*plain
,
1125 uint16_t device_state
,
1126 uint64_t allocation_size
)
1128 struct tstream_npa_accept_state
*state
;
1129 struct tevent_req
*req
, *subreq
;
1131 req
= tevent_req_create(mem_ctx
, &state
,
1132 struct tstream_npa_accept_state
);
1137 switch (file_type
) {
1138 case FILE_TYPE_BYTE_MODE_PIPE
:
1140 case FILE_TYPE_MESSAGE_MODE_PIPE
:
1143 tevent_req_error(req
, EINVAL
);
1147 ZERO_STRUCTP(state
);
1150 state
->plain
= plain
;
1151 state
->file_type
= file_type
;
1152 state
->device_state
= device_state
;
1153 state
->alloc_size
= allocation_size
;
1156 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1157 * named_pipe_full_request provides the pdu length then.
1159 subreq
= tstream_readv_pdu_send(state
, ev
, plain
,
1160 tstream_npa_accept_next_vector
,
1162 if (tevent_req_nomem(subreq
, req
)) {
1166 tevent_req_set_callback(subreq
,
1167 tstream_npa_accept_existing_reply
, req
);
1172 tevent_req_post(req
, ev
);
1176 static int tstream_npa_accept_next_vector(struct tstream_context
*unix_stream
,
1178 TALLOC_CTX
*mem_ctx
,
1179 struct iovec
**_vector
,
1182 struct tstream_npa_accept_state
*state
=
1183 talloc_get_type_abort(private_data
,
1184 struct tstream_npa_accept_state
);
1185 struct iovec
*vector
;
1189 if (state
->npa_blob
.length
== 0) {
1190 state
->npa_blob
= data_blob_talloc(state
, NULL
, 4);
1191 if (!state
->npa_blob
.data
) {
1194 } else if (state
->npa_blob
.length
== 4) {
1199 msg_len
= RIVAL(state
->npa_blob
.data
, 0);
1201 if (msg_len
> 0x00FFFFFF) {
1213 state
->npa_blob
.data
= talloc_realloc(state
,
1214 state
->npa_blob
.data
,
1216 if (!state
->npa_blob
.data
) {
1219 state
->npa_blob
.length
= msg_len
;
1221 if (memcmp(&state
->npa_blob
.data
[4],
1222 NAMED_PIPE_AUTH_MAGIC
, 4) != 0) {
1223 DEBUG(0, ("Wrong protocol\n"));
1224 #if defined(EPROTONOSUPPORT)
1225 errno
= EPROTONOSUPPORT
;
1226 #elif defined(EPROTO)
1238 /* we need to get a message header */
1239 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
1243 vector
[0].iov_base
= (char *) (state
->npa_blob
.data
+ ofs
);
1244 vector
[0].iov_len
= state
->npa_blob
.length
- ofs
;
1252 static void tstream_npa_accept_existing_reply(struct tevent_req
*subreq
)
1254 struct tevent_req
*req
=
1255 tevent_req_callback_data(subreq
, struct tevent_req
);
1256 struct tstream_npa_accept_state
*state
=
1257 tevent_req_data(req
, struct tstream_npa_accept_state
);
1258 struct named_pipe_auth_req
*pipe_request
;
1259 struct named_pipe_auth_rep pipe_reply
;
1260 struct named_pipe_auth_req_info3 i3
;
1261 enum ndr_err_code ndr_err
;
1266 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
1267 TALLOC_FREE(subreq
);
1269 tevent_req_error(req
, sys_errno
);
1273 DEBUG(10, ("Received packet of length %lu\n",
1274 (long)state
->npa_blob
.length
));
1275 dump_data(11, state
->npa_blob
.data
, state
->npa_blob
.length
);
1277 ZERO_STRUCT(pipe_reply
);
1278 pipe_reply
.level
= 0;
1279 pipe_reply
.status
= NT_STATUS_INTERNAL_ERROR
;
1281 * TODO: check it's a root (uid == 0) pipe
1284 pipe_request
= talloc(state
, struct named_pipe_auth_req
);
1285 if (!pipe_request
) {
1286 DEBUG(0, ("Out of memory!\n"));
1290 /* parse the passed credentials */
1291 ndr_err
= ndr_pull_struct_blob_all(
1292 &state
->npa_blob
, pipe_request
, pipe_request
,
1293 (ndr_pull_flags_fn_t
)ndr_pull_named_pipe_auth_req
);
1294 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1295 pipe_reply
.status
= ndr_map_error2ntstatus(ndr_err
);
1296 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1297 nt_errstr(pipe_reply
.status
)));
1302 NDR_PRINT_DEBUG(named_pipe_auth_req
, pipe_request
);
1307 switch (pipe_request
->level
) {
1309 pipe_reply
.level
= 0;
1310 pipe_reply
.status
= NT_STATUS_OK
;
1312 /* we need to force byte mode in this level */
1313 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1317 pipe_reply
.level
= 1;
1318 pipe_reply
.status
= NT_STATUS_OK
;
1320 /* We must copy net3_SamInfo3, so that
1321 * info3 is an actual talloc pointer, then we steal
1322 * pipe_request on info3 so that all the allocated memory
1323 * pointed by the structrue members is preserved */
1324 state
->info3
= (struct netr_SamInfo3
*)talloc_memdup(state
,
1325 &pipe_request
->info
.info1
,
1326 sizeof(struct netr_SamInfo3
));
1327 if (!state
->info3
) {
1328 pipe_reply
.status
= NT_STATUS_NO_MEMORY
;
1329 DEBUG(0, ("Out of memory!\n"));
1332 talloc_steal(state
->info3
, pipe_request
);
1334 /* we need to force byte mode in this level */
1335 state
->file_type
= FILE_TYPE_BYTE_MODE_PIPE
;
1339 pipe_reply
.level
= 2;
1340 pipe_reply
.status
= NT_STATUS_OK
;
1341 pipe_reply
.info
.info2
.file_type
= state
->file_type
;
1342 pipe_reply
.info
.info2
.device_state
= state
->device_state
;
1343 pipe_reply
.info
.info2
.allocation_size
= state
->alloc_size
;
1345 i3
.client_name
= pipe_request
->info
.info2
.client_name
;
1346 i3
.client_addr
= pipe_request
->info
.info2
.client_addr
;
1347 i3
.client_port
= pipe_request
->info
.info2
.client_port
;
1348 i3
.server_name
= pipe_request
->info
.info2
.server_name
;
1349 i3
.server_addr
= pipe_request
->info
.info2
.server_addr
;
1350 i3
.server_port
= pipe_request
->info
.info2
.server_port
;
1351 i3
.sam_info3
= pipe_request
->info
.info2
.sam_info3
;
1352 i3
.session_key_length
=
1353 pipe_request
->info
.info2
.session_key_length
;
1354 i3
.session_key
= pipe_request
->info
.info2
.session_key
;
1358 pipe_reply
.level
= 3;
1359 pipe_reply
.status
= NT_STATUS_OK
;
1360 pipe_reply
.info
.info3
.file_type
= state
->file_type
;
1361 pipe_reply
.info
.info3
.device_state
= state
->device_state
;
1362 pipe_reply
.info
.info3
.allocation_size
= state
->alloc_size
;
1364 i3
= pipe_request
->info
.info3
;
1368 DEBUG(0, ("Unknown level %u\n", pipe_request
->level
));
1369 pipe_reply
.level
= 0;
1370 pipe_reply
.status
= NT_STATUS_INVALID_LEVEL
;
1374 if (pipe_reply
.level
>=2) {
1376 if (i3
.server_addr
== NULL
) {
1377 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1378 DEBUG(2, ("Missing server address\n"));
1381 if (i3
.client_addr
== NULL
) {
1382 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1383 DEBUG(2, ("Missing client address\n"));
1387 state
->server_name
= discard_const_p(char,
1388 talloc_move(state
, &i3
.server_name
));
1389 ret
= tsocket_address_inet_from_strings(state
, "ip",
1394 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1395 i3
.server_addr
, i3
.server_port
,
1397 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1401 state
->client_name
= discard_const_p(char,
1402 talloc_move(state
, &i3
.client_name
));
1403 ret
= tsocket_address_inet_from_strings(state
, "ip",
1408 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1409 i3
.client_addr
, i3
.client_port
,
1411 pipe_reply
.status
= NT_STATUS_INVALID_ADDRESS
;
1415 state
->info3
= talloc_move(state
, &i3
.sam_info3
);
1416 state
->session_key
.data
= talloc_move(state
, &i3
.session_key
);
1417 state
->session_key
.length
= i3
.session_key_length
;
1420 if (pipe_reply
.level
>= 3) {
1421 state
->delegated_creds
.data
=
1422 talloc_move(state
, &i3
.gssapi_delegated_creds
);
1423 state
->delegated_creds
.length
=
1424 i3
.gssapi_delegated_creds_length
;
1428 /* create the output */
1429 ndr_err
= ndr_push_struct_blob(&out
, state
, &pipe_reply
,
1430 (ndr_push_flags_fn_t
)ndr_push_named_pipe_auth_rep
);
1431 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1432 DEBUG(2, ("Error encoding structure: %s",
1433 ndr_map_error2string(ndr_err
)));
1434 tevent_req_error(req
, EIO
);
1438 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out
.length
));
1439 dump_data(11, out
.data
, out
.length
);
1442 NDR_PRINT_DEBUG(named_pipe_auth_rep
, &pipe_reply
);
1445 state
->accept_status
= pipe_reply
.status
;
1447 state
->out_iov
.iov_base
= (char *) out
.data
;
1448 state
->out_iov
.iov_len
= out
.length
;
1450 subreq
= tstream_writev_send(state
, state
->ev
,
1452 &state
->out_iov
, 1);
1453 if (tevent_req_nomem(subreq
, req
)) {
1454 DEBUG(0, ("no memory for tstream_writev_send"));
1458 tevent_req_set_callback(subreq
, tstream_npa_accept_existing_done
, req
);
1461 static void tstream_npa_accept_existing_done(struct tevent_req
*subreq
)
1463 struct tevent_req
*req
=
1464 tevent_req_callback_data(subreq
, struct tevent_req
);
1468 ret
= tstream_writev_recv(subreq
, &sys_errno
);
1469 TALLOC_FREE(subreq
);
1471 tevent_req_error(req
, sys_errno
);
1475 tevent_req_done(req
);
1478 int _tstream_npa_accept_existing_recv(struct tevent_req
*req
,
1480 TALLOC_CTX
*mem_ctx
,
1481 struct tstream_context
**stream
,
1482 struct tsocket_address
**client
,
1483 char **_client_name
,
1484 struct tsocket_address
**server
,
1486 struct netr_SamInfo3
**info3
,
1487 DATA_BLOB
*session_key
,
1488 DATA_BLOB
*delegated_creds
,
1489 const char *location
)
1491 struct tstream_npa_accept_state
*state
=
1492 tevent_req_data(req
, struct tstream_npa_accept_state
);
1493 struct tstream_npa
*npas
;
1496 ret
= tsocket_simple_int_recv(req
, perrno
);
1498 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1499 strerror(*perrno
)));
1500 tevent_req_received(req
);
1504 if (!NT_STATUS_IS_OK(state
->accept_status
)) {
1505 #if defined(EPROTONOSUPPORT)
1506 *perrno
= EPROTONOSUPPORT
;
1507 #elif defined(EPROTO)
1512 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1513 nt_errstr(state
->accept_status
),
1514 strerror(*perrno
)));
1515 tevent_req_received(req
);
1519 *stream
= tstream_context_create(mem_ctx
,
1526 tevent_req_received(req
);
1530 npas
->unix_stream
= state
->plain
;
1531 npas
->file_type
= state
->file_type
;
1533 *client
= talloc_move(mem_ctx
, &state
->client
);
1534 *_client_name
= talloc_move(mem_ctx
, &state
->client_name
);
1535 *server
= talloc_move(mem_ctx
, &state
->server
);
1536 *server_name
= talloc_move(mem_ctx
, &state
->server_name
);
1537 *info3
= talloc_move(mem_ctx
, &state
->info3
);
1538 *session_key
= state
->session_key
;
1539 talloc_steal(mem_ctx
, state
->session_key
.data
);
1540 *delegated_creds
= state
->delegated_creds
;
1541 talloc_steal(mem_ctx
, state
->delegated_creds
.data
);
1543 tevent_req_received(req
);