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/named_pipe_auth/tstream_u32_read.h"
28 #include "../libcli/smb/smb_constants.h"
30 static const struct tstream_context_ops tstream_npa_ops;
33 struct tstream_context *unix_stream;
40 struct tstream_npa_connect_state {
42 struct tevent_context *ev;
45 const char *unix_path;
46 struct tsocket_address *unix_laddr;
47 struct tsocket_address *unix_raddr;
48 struct tstream_context *unix_stream;
50 struct named_pipe_auth_req auth_req;
51 DATA_BLOB auth_req_blob;
52 struct iovec auth_req_iov;
54 struct named_pipe_auth_rep auth_rep;
57 static void tstream_npa_connect_unix_done(struct tevent_req *subreq);
59 struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
60 struct tevent_context *ev,
61 const char *directory,
63 const struct tsocket_address *remote_client_addr,
64 const char *remote_client_name_in,
65 const struct tsocket_address *local_server_addr,
66 const char *local_server_name_in,
67 const struct auth_session_info_transport *session_info)
69 struct tevent_req *req;
70 struct tstream_npa_connect_state *state;
71 struct tevent_req *subreq;
73 enum ndr_err_code ndr_err;
74 char *lower_case_npipe;
75 struct named_pipe_auth_req_info4 *info4;
77 req = tevent_req_create(mem_ctx, &state,
78 struct tstream_npa_connect_state);
83 state->caller.ev = ev;
85 lower_case_npipe = strlower_talloc(state, npipe);
86 if (tevent_req_nomem(lower_case_npipe, req)) {
90 state->unix_path = talloc_asprintf(state, "%s/%s",
93 talloc_free(lower_case_npipe);
94 if (tevent_req_nomem(state->unix_path, req)) {
98 ret = tsocket_address_unix_from_path(state,
102 tevent_req_error(req, errno);
106 ret = tsocket_address_unix_from_path(state,
110 tevent_req_error(req, errno);
114 ZERO_STRUCT(state->auth_req);
116 if (!local_server_addr) {
117 tevent_req_error(req, EINVAL);
121 state->auth_req.level = 4;
122 info4 = &state->auth_req.info.info4;
124 info4->remote_client_name = remote_client_name_in;
125 info4->remote_client_addr = tsocket_address_inet_addr_string(remote_client_addr,
127 if (!info4->remote_client_addr) {
128 /* errno might be EINVAL */
129 tevent_req_error(req, errno);
132 info4->remote_client_port = tsocket_address_inet_port(remote_client_addr);
133 if (!info4->remote_client_name) {
134 info4->remote_client_name = info4->remote_client_addr;
137 info4->local_server_name = local_server_name_in;
138 info4->local_server_addr = tsocket_address_inet_addr_string(local_server_addr,
140 if (!info4->local_server_addr) {
141 /* errno might be EINVAL */
142 tevent_req_error(req, errno);
145 info4->local_server_port = tsocket_address_inet_port(local_server_addr);
146 if (!info4->local_server_name) {
147 info4->local_server_name = info4->local_server_addr;
150 info4->session_info = discard_const_p(struct auth_session_info_transport, session_info);
153 NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
156 ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
157 state, &state->auth_req,
158 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
159 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
160 tevent_req_error(req, EINVAL);
164 state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
165 state->auth_req_iov.iov_len = state->auth_req_blob.length;
167 subreq = tstream_unix_connect_send(state,
171 if (tevent_req_nomem(subreq, req)) {
174 tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
179 tevent_req_post(req, ev);
183 static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
185 static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
187 struct tevent_req *req =
188 tevent_req_callback_data(subreq,
190 struct tstream_npa_connect_state *state =
192 struct tstream_npa_connect_state);
196 ret = tstream_unix_connect_recv(subreq, &sys_errno,
197 state, &state->unix_stream);
200 tevent_req_error(req, sys_errno);
204 subreq = tstream_writev_send(state,
207 &state->auth_req_iov, 1);
208 if (tevent_req_nomem(subreq, req)) {
211 tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
214 static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
216 static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
218 struct tevent_req *req =
219 tevent_req_callback_data(subreq,
221 struct tstream_npa_connect_state *state =
223 struct tstream_npa_connect_state);
227 ret = tstream_writev_recv(subreq, &sys_errno);
230 tevent_req_error(req, sys_errno);
234 subreq = tstream_u32_read_send(
235 state, state->caller.ev, 0x00FFFFFF, state->unix_stream);
236 if (tevent_req_nomem(subreq, req)) {
239 tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
242 static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
244 struct tevent_req *req =
245 tevent_req_callback_data(subreq,
247 struct tstream_npa_connect_state *state =
249 struct tstream_npa_connect_state);
252 enum ndr_err_code ndr_err;
254 err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
256 if (tevent_req_error(req, err)) {
260 DBG_DEBUG("name_pipe_auth_rep(client)[%zu]\n", in.length);
261 dump_data(11, in.data, in.length);
263 ndr_err = ndr_pull_struct_blob_all(
267 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
269 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
270 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
271 ndr_map_error2string(ndr_err)));
272 tevent_req_error(req, EIO);
277 NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
280 if (state->auth_rep.length < 16) {
281 DEBUG(0, ("req invalid length: %u < 16\n",
282 state->auth_rep.length));
283 tevent_req_error(req, EIO);
287 if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
288 DEBUG(0, ("req invalid magic: %s != %s\n",
289 state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
290 tevent_req_error(req, EIO);
294 if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
295 DEBUG(0, ("req failed: %s\n",
296 nt_errstr(state->auth_rep.status)));
297 tevent_req_error(req, EACCES);
301 if (state->auth_rep.level != state->auth_req.level) {
302 DEBUG(0, ("req invalid level: %u != %u\n",
303 state->auth_rep.level, state->auth_req.level));
304 tevent_req_error(req, EIO);
308 tevent_req_done(req);
311 int _tstream_npa_connect_recv(struct tevent_req *req,
314 struct tstream_context **_stream,
315 uint16_t *_file_type,
316 uint16_t *_device_state,
317 uint64_t *_allocation_size,
318 const char *location)
320 struct tstream_npa_connect_state *state =
322 struct tstream_npa_connect_state);
323 struct tstream_context *stream;
324 struct tstream_npa *npas;
325 uint16_t device_state = 0;
326 uint64_t allocation_size = 0;
328 if (tevent_req_is_unix_error(req, perrno)) {
329 tevent_req_received(req);
333 stream = tstream_context_create(mem_ctx,
340 tevent_req_received(req);
345 npas->unix_stream = talloc_move(stream, &state->unix_stream);
346 switch (state->auth_rep.level) {
348 npas->file_type = state->auth_rep.info.info4.file_type;
349 device_state = state->auth_rep.info.info4.device_state;
350 allocation_size = state->auth_rep.info.info4.allocation_size;
355 *_file_type = npas->file_type;
356 *_device_state = device_state;
357 *_allocation_size = allocation_size;
358 tevent_req_received(req);
362 static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
364 struct tstream_npa *npas = tstream_context_data(stream,
368 if (!npas->unix_stream) {
373 switch (npas->file_type) {
374 case FILE_TYPE_BYTE_MODE_PIPE:
375 ret = tstream_pending_bytes(npas->unix_stream);
378 case FILE_TYPE_MESSAGE_MODE_PIPE:
379 ret = npas->pending.iov_len;
389 struct tstream_npa_readv_state {
390 struct tstream_context *stream;
392 struct iovec *vector;
395 /* the header for message mode */
402 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
403 static int tstream_npa_readv_next_vector(struct tstream_context *stream,
406 struct iovec **_vector,
408 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
410 static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
411 struct tevent_context *ev,
412 struct tstream_context *stream,
413 struct iovec *vector,
416 struct tevent_req *req;
417 struct tstream_npa_readv_state *state;
418 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
419 struct tevent_req *subreq;
424 req = tevent_req_create(mem_ctx, &state,
425 struct tstream_npa_readv_state);
430 state->stream = stream;
433 if (!npas->unix_stream) {
434 tevent_req_error(req, ENOTCONN);
438 switch (npas->file_type) {
439 case FILE_TYPE_BYTE_MODE_PIPE:
440 state->vector = vector;
441 state->count = count;
443 subreq = tstream_readv_send(state,
448 if (tevent_req_nomem(subreq,req)) {
451 tevent_req_set_callback(subreq,
452 tstream_npa_readv_byte_mode_handler,
457 case FILE_TYPE_MESSAGE_MODE_PIPE:
459 * we make a copy of the vector and prepend a header
462 state->vector = talloc_array(state, struct iovec, count);
463 if (tevent_req_nomem(state->vector, req)) {
466 memcpy(state->vector, vector, sizeof(struct iovec)*count);
467 state->count = count;
470 * copy the pending buffer first
473 left = npas->pending.iov_len;
474 pbase = (uint8_t *)npas->pending.iov_base;
476 while (left > 0 && state->count > 0) {
478 base = (uint8_t *)state->vector[0].iov_base;
479 if (left < state->vector[0].iov_len) {
480 memcpy(base, pbase + ofs, left);
483 state->vector[0].iov_base = (char *) base;
484 state->vector[0].iov_len -= left;
489 ZERO_STRUCT(npas->pending);
492 memcpy(base, pbase + ofs, state->vector[0].iov_len);
494 ofs += state->vector[0].iov_len;
495 left -= state->vector[0].iov_len;
501 ZERO_STRUCT(npas->pending);
507 memmove(pbase, pbase + ofs, left);
508 npas->pending.iov_base = (char *) pbase;
509 npas->pending.iov_len = left;
511 * this cannot fail and even if it
512 * fails we can handle it
514 pbase = talloc_realloc(npas, pbase, uint8_t, left);
516 npas->pending.iov_base = (char *) pbase;
523 if (state->count == 0) {
524 tevent_req_done(req);
528 ZERO_STRUCT(state->hdr);
529 state->wait_for_hdr = false;
531 subreq = tstream_readv_pdu_send(state,
534 tstream_npa_readv_next_vector,
536 if (tevent_req_nomem(subreq, req)) {
539 tevent_req_set_callback(subreq,
540 tstream_npa_readv_msg_mode_handler,
546 /* this can't happen */
547 tevent_req_error(req, EINVAL);
551 tevent_req_post(req, ev);
555 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
557 struct tevent_req *req = tevent_req_callback_data(subreq,
559 struct tstream_npa_readv_state *state = tevent_req_data(req,
560 struct tstream_npa_readv_state);
564 ret = tstream_readv_recv(subreq, &sys_errno);
567 tevent_req_error(req, sys_errno);
573 tevent_req_done(req);
576 static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
579 struct iovec **_vector,
582 struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
583 struct tstream_npa_readv_state);
584 struct tstream_npa *npas = tstream_context_data(state->stream,
586 struct iovec *vector;
591 if (state->count == 0) {
597 if (!state->wait_for_hdr) {
598 /* we need to get a message header */
599 vector = talloc_array(mem_ctx, struct iovec, 1);
603 ZERO_STRUCT(state->hdr);
604 vector[0].iov_base = (char *) state->hdr;
605 vector[0].iov_len = sizeof(state->hdr);
609 state->wait_for_hdr = true;
616 /* and now fill the callers buffers and maybe the pending buffer */
617 state->wait_for_hdr = false;
619 msg_len = SVAL(state->hdr, 0);
626 state->wait_for_hdr = false;
628 /* +1 because we may need to fill the pending buffer */
629 vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
636 while (left > 0 && state->count > 0) {
637 if (left < state->vector[0].iov_len) {
639 base = (uint8_t *)state->vector[0].iov_base;
640 vector[count].iov_base = (char *) base;
641 vector[count].iov_len = left;
644 state->vector[0].iov_base = (char *) base;
645 state->vector[0].iov_len -= left;
648 vector[count] = state->vector[0];
650 left -= state->vector[0].iov_len;
657 * if the message is longer than the buffers the caller
658 * requested, we need to consume the rest of the message
659 * into the pending buffer, where the next readv can
662 npas->pending.iov_base = talloc_array(npas, char, left);
663 if (!npas->pending.iov_base) {
666 npas->pending.iov_len = left;
668 vector[count] = npas->pending;
672 state->ret += (msg_len - left);
679 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
681 struct tevent_req *req = tevent_req_callback_data(subreq,
686 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
689 tevent_req_error(req, sys_errno);
694 * we do not set state->ret here as ret includes the header size.
695 * we set it in tstream_npa_readv_pdu_next_vector()
698 tevent_req_done(req);
701 static int tstream_npa_readv_recv(struct tevent_req *req,
704 struct tstream_npa_readv_state *state = tevent_req_data(req,
705 struct tstream_npa_readv_state);
708 ret = tsocket_simple_int_recv(req, perrno);
713 tevent_req_received(req);
717 struct tstream_npa_writev_state {
718 const struct iovec *vector;
721 /* the header for message mode */
728 static void tstream_npa_writev_handler(struct tevent_req *subreq);
730 static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
731 struct tevent_context *ev,
732 struct tstream_context *stream,
733 const struct iovec *vector,
736 struct tevent_req *req;
737 struct tstream_npa_writev_state *state;
738 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
739 struct tevent_req *subreq;
742 struct iovec *new_vector;
744 req = tevent_req_create(mem_ctx, &state,
745 struct tstream_npa_writev_state);
752 if (!npas->unix_stream) {
753 tevent_req_error(req, ENOTCONN);
757 switch (npas->file_type) {
758 case FILE_TYPE_BYTE_MODE_PIPE:
759 state->hdr_used = false;
760 state->vector = vector;
761 state->count = count;
764 case FILE_TYPE_MESSAGE_MODE_PIPE:
766 * we make a copy of the vector and prepend a header
769 new_vector = talloc_array(state, struct iovec, count + 1);
770 if (tevent_req_nomem(new_vector, req)) {
773 new_vector[0].iov_base = (char *) state->hdr;
774 new_vector[0].iov_len = sizeof(state->hdr);
775 memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
777 state->hdr_used = true;
778 state->vector = new_vector;
779 state->count = count + 1;
782 for (i=0; i < count; i++) {
784 * overflow check already done in tstream_writev_send
786 msg_len += vector[i].iov_len;
789 if (msg_len > UINT16_MAX) {
790 tevent_req_error(req, EMSGSIZE);
794 SSVAL(state->hdr, 0, msg_len);
798 subreq = tstream_writev_send(state,
803 if (tevent_req_nomem(subreq, req)) {
806 tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
811 tevent_req_post(req, ev);
815 static void tstream_npa_writev_handler(struct tevent_req *subreq)
817 struct tevent_req *req = tevent_req_callback_data(subreq,
819 struct tstream_npa_writev_state *state = tevent_req_data(req,
820 struct tstream_npa_writev_state);
824 ret = tstream_writev_recv(subreq, &sys_errno);
827 tevent_req_error(req, sys_errno);
832 * in message mode we need to hide the length
833 * of the hdr from the caller
835 if (state->hdr_used) {
836 ret -= sizeof(state->hdr);
841 tevent_req_done(req);
844 static int tstream_npa_writev_recv(struct tevent_req *req,
847 struct tstream_npa_writev_state *state = tevent_req_data(req,
848 struct tstream_npa_writev_state);
851 ret = tsocket_simple_int_recv(req, perrno);
856 tevent_req_received(req);
860 struct tstream_npa_disconnect_state {
861 struct tstream_context *stream;
864 static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
866 static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
867 struct tevent_context *ev,
868 struct tstream_context *stream)
870 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
871 struct tevent_req *req;
872 struct tstream_npa_disconnect_state *state;
873 struct tevent_req *subreq;
875 req = tevent_req_create(mem_ctx, &state,
876 struct tstream_npa_disconnect_state);
881 state->stream = stream;
883 if (!npas->unix_stream) {
884 tevent_req_error(req, ENOTCONN);
888 subreq = tstream_disconnect_send(state,
891 if (tevent_req_nomem(subreq, req)) {
894 tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
899 tevent_req_post(req, ev);
903 static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
905 struct tevent_req *req = tevent_req_callback_data(subreq,
907 struct tstream_npa_disconnect_state *state = tevent_req_data(req,
908 struct tstream_npa_disconnect_state);
909 struct tstream_context *stream = state->stream;
910 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
914 ret = tstream_disconnect_recv(subreq, &sys_errno);
917 tevent_req_error(req, sys_errno);
921 TALLOC_FREE(npas->unix_stream);
923 tevent_req_done(req);
926 static int tstream_npa_disconnect_recv(struct tevent_req *req,
931 ret = tsocket_simple_int_recv(req, perrno);
933 tevent_req_received(req);
937 static const struct tstream_context_ops tstream_npa_ops = {
940 .pending_bytes = tstream_npa_pending_bytes,
942 .readv_send = tstream_npa_readv_send,
943 .readv_recv = tstream_npa_readv_recv,
945 .writev_send = tstream_npa_writev_send,
946 .writev_recv = tstream_npa_writev_recv,
948 .disconnect_send = tstream_npa_disconnect_send,
949 .disconnect_recv = tstream_npa_disconnect_recv,
952 int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
955 struct tstream_context **_stream,
956 const char *location)
958 struct tstream_context *stream;
959 struct tstream_npa *npas;
963 case FILE_TYPE_BYTE_MODE_PIPE:
965 case FILE_TYPE_MESSAGE_MODE_PIPE:
972 stream = tstream_context_create(mem_ctx,
982 npas->file_type = file_type;
984 ret = tstream_bsd_existing_socket(stream, fd,
987 int saved_errno = errno;
998 struct tstream_npa_accept_state {
999 struct tevent_context *ev;
1000 struct tstream_context *plain;
1002 uint16_t device_state;
1003 uint64_t alloc_size;
1005 struct named_pipe_auth_req *pipe_request;
1008 struct iovec out_iov;
1011 NTSTATUS accept_status;
1012 struct tsocket_address *remote_client_addr;
1013 struct tsocket_address *local_server_addr;
1016 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1017 static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1019 struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1020 struct tevent_context *ev,
1021 struct tstream_context *plain,
1023 uint16_t device_state,
1024 uint64_t allocation_size)
1026 struct tstream_npa_accept_state *state;
1027 struct tevent_req *req, *subreq;
1029 req = tevent_req_create(mem_ctx, &state,
1030 struct tstream_npa_accept_state);
1035 switch (file_type) {
1036 case FILE_TYPE_BYTE_MODE_PIPE:
1038 case FILE_TYPE_MESSAGE_MODE_PIPE:
1041 tevent_req_error(req, EINVAL);
1046 state->plain = plain;
1047 state->file_type = file_type;
1048 state->device_state = device_state;
1049 state->alloc_size = allocation_size;
1051 subreq = tstream_u32_read_send(state, ev, 0x00FFFFFF, plain);
1052 if (tevent_req_nomem(subreq, req)) {
1056 tevent_req_set_callback(subreq,
1057 tstream_npa_accept_existing_reply, req);
1062 tevent_req_post(req, ev);
1066 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1068 struct tevent_req *req =
1069 tevent_req_callback_data(subreq, struct tevent_req);
1070 struct tstream_npa_accept_state *state =
1071 tevent_req_data(req, struct tstream_npa_accept_state);
1072 struct named_pipe_auth_req *pipe_request;
1073 struct named_pipe_auth_rep pipe_reply;
1074 struct named_pipe_auth_req_info4 i4;
1075 enum ndr_err_code ndr_err;
1080 err = tstream_u32_read_recv(subreq, state, &in.data, &in.length);
1082 tevent_req_error(req, err);
1085 if (in.length < 8) {
1086 tevent_req_error(req, EMSGSIZE);
1090 if (memcmp(&in.data[4], NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1091 DBG_ERR("Wrong protocol\n");
1092 #if defined(EPROTONOSUPPORT)
1093 err = EPROTONOSUPPORT;
1094 #elif defined(EPROTO)
1099 tevent_req_error(req, err);
1103 DBG_DEBUG("Received packet of length %zu\n", in.length);
1104 dump_data(11, in.data, in.length);
1106 ZERO_STRUCT(pipe_reply);
1107 pipe_reply.level = 0;
1108 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1110 * TODO: check it's a root (uid == 0) pipe
1113 pipe_request = talloc(state, struct named_pipe_auth_req);
1114 if (!pipe_request) {
1115 DEBUG(0, ("Out of memory!\n"));
1118 state->pipe_request = pipe_request;
1120 /* parse the passed credentials */
1121 ndr_err = ndr_pull_struct_blob_all(
1125 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1126 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1127 pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1128 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1129 nt_errstr(pipe_reply.status)));
1134 NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1139 if (pipe_request->level != 4) {
1140 DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1141 pipe_reply.level = 0;
1142 pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1146 pipe_reply.level = 4;
1147 pipe_reply.status = NT_STATUS_OK;
1148 pipe_reply.info.info4.file_type = state->file_type;
1149 pipe_reply.info.info4.device_state = state->device_state;
1150 pipe_reply.info.info4.allocation_size = state->alloc_size;
1152 i4 = pipe_request->info.info4;
1153 if (i4.local_server_addr == NULL) {
1154 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1155 DEBUG(2, ("Missing local server address\n"));
1158 if (i4.remote_client_addr == NULL) {
1159 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1160 DEBUG(2, ("Missing remote client address\n"));
1164 ret = tsocket_address_inet_from_strings(state, "ip",
1165 i4.local_server_addr,
1166 i4.local_server_port,
1167 &state->local_server_addr);
1169 DEBUG(2, ("Invalid local server address[%s:%u] - %s\n",
1170 i4.local_server_addr, i4.local_server_port,
1172 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1176 ret = tsocket_address_inet_from_strings(state, "ip",
1177 i4.remote_client_addr,
1178 i4.remote_client_port,
1179 &state->remote_client_addr);
1181 DEBUG(2, ("Invalid remote client address[%s:%u] - %s\n",
1182 i4.remote_client_addr, i4.remote_client_port,
1184 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1189 /* create the output */
1190 ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1191 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1192 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1193 DEBUG(2, ("Error encoding structure: %s",
1194 ndr_map_error2string(ndr_err)));
1195 tevent_req_error(req, EIO);
1199 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1200 dump_data(11, out.data, out.length);
1203 NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1206 state->accept_status = pipe_reply.status;
1208 state->out_iov.iov_base = (char *) out.data;
1209 state->out_iov.iov_len = out.length;
1211 subreq = tstream_writev_send(state, state->ev,
1213 &state->out_iov, 1);
1214 if (tevent_req_nomem(subreq, req)) {
1215 DEBUG(0, ("no memory for tstream_writev_send"));
1219 tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1222 static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1224 struct tevent_req *req =
1225 tevent_req_callback_data(subreq, struct tevent_req);
1229 ret = tstream_writev_recv(subreq, &sys_errno);
1230 TALLOC_FREE(subreq);
1232 tevent_req_error(req, sys_errno);
1236 tevent_req_done(req);
1239 static struct named_pipe_auth_req_info4 *copy_npa_info4(
1240 TALLOC_CTX *mem_ctx, const struct named_pipe_auth_req_info4 *src)
1242 struct named_pipe_auth_req_info4 *dst = NULL;
1244 enum ndr_err_code ndr_err;
1246 dst = talloc_zero(mem_ctx, struct named_pipe_auth_req_info4);
1251 ndr_err = ndr_push_struct_blob(
1255 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req_info4);
1256 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1257 DBG_WARNING("ndr_push_named_pipe_auth_req_info4 failed: %s\n",
1258 ndr_errstr(ndr_err));
1263 ndr_err = ndr_pull_struct_blob_all(
1267 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req_info4);
1268 TALLOC_FREE(blob.data);
1269 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1270 DBG_WARNING("ndr_push_named_pipe_auth_req_info4 failed: %s\n",
1271 ndr_errstr(ndr_err));
1279 int _tstream_npa_accept_existing_recv(
1280 struct tevent_req *req,
1282 TALLOC_CTX *mem_ctx,
1283 struct tstream_context **stream,
1284 struct named_pipe_auth_req_info4 **info4,
1285 struct tsocket_address **remote_client_addr,
1286 char **_remote_client_name,
1287 struct tsocket_address **local_server_addr,
1288 char **local_server_name,
1289 struct auth_session_info_transport **session_info,
1290 const char *location)
1292 struct tstream_npa_accept_state *state =
1293 tevent_req_data(req, struct tstream_npa_accept_state);
1294 struct named_pipe_auth_req_info4 *i4 = &state->pipe_request->info.info4;
1295 struct tstream_npa *npas;
1298 ret = tsocket_simple_int_recv(req, perrno);
1300 DEBUG(2, ("Failed to accept named pipe connection: %s\n",
1301 strerror(*perrno)));
1302 tevent_req_received(req);
1306 if (!NT_STATUS_IS_OK(state->accept_status)) {
1307 #if defined(EPROTONOSUPPORT)
1308 *perrno = EPROTONOSUPPORT;
1309 #elif defined(EPROTO)
1314 DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
1315 nt_errstr(state->accept_status),
1316 strerror(*perrno)));
1317 tevent_req_received(req);
1321 *stream = tstream_context_create(mem_ctx,
1328 tevent_req_received(req);
1332 npas->unix_stream = state->plain;
1333 npas->file_type = state->file_type;
1335 if (info4 != NULL) {
1337 * Make a full copy of "info4" because further down we
1338 * talloc_move() away substructures from
1339 * state->pipe_request.
1341 struct named_pipe_auth_req_info4 *dst = copy_npa_info4(
1345 tevent_req_received(req);
1351 if (remote_client_addr != NULL) {
1352 *remote_client_addr = talloc_move(
1353 mem_ctx, &state->remote_client_addr);
1355 if (_remote_client_name != NULL) {
1356 *_remote_client_name = discard_const_p(
1357 char, talloc_move(mem_ctx, &i4->remote_client_name));
1359 if (local_server_addr != NULL) {
1360 *local_server_addr = talloc_move(
1361 mem_ctx, &state->local_server_addr);
1363 if (local_server_name != NULL) {
1364 *local_server_name = discard_const_p(
1365 char, talloc_move(mem_ctx, &i4->local_server_name));
1367 if (session_info != NULL) {
1368 *session_info = talloc_move(mem_ctx, &i4->session_info);
1371 tevent_req_received(req);
1376 /* SOCKETPAIR for internal rpc communication */
1378 /* file_type is FILE_TYPE_BYTE_MODE_PIPE or FILE_TYPE_MESSAGE_MODE_PIPE */
1379 int _tstream_npa_socketpair(uint16_t file_type,
1380 TALLOC_CTX *mem_ctx1,
1381 struct tstream_context **pstream1,
1382 TALLOC_CTX *mem_ctx2,
1383 struct tstream_context **pstream2,
1384 const char *location)
1386 struct tstream_context *stream1 = NULL;
1387 struct tstream_context *stream2 = NULL;
1394 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1401 ok = smb_set_close_on_exec(fd1);
1406 ok = smb_set_close_on_exec(fd2);
1411 rc = set_blocking(fd1, false);
1416 rc = set_blocking(fd2, false);
1421 rc = _tstream_npa_existing_socket(mem_ctx1,
1430 rc = _tstream_npa_existing_socket(mem_ctx2,
1436 int sys_errno = errno;
1437 talloc_free(stream1);
1443 *pstream1 = stream1;
1444 *pstream2 = stream2;
1450 int sys_errno = errno;