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/smb/smb_constants.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 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);
117 tevent_req_error(req, EINVAL);
121 state->auth_req.level = 4;
122 info4 = &state->auth_req.info.info4;
124 info4->client_name = client_name_in;
125 info4->client_addr = tsocket_address_inet_addr_string(client, state);
126 if (!info4->client_addr) {
127 /* errno might be EINVAL */
128 tevent_req_error(req, errno);
131 info4->client_port = tsocket_address_inet_port(client);
132 if (!info4->client_name) {
133 info4->client_name = info4->client_addr;
136 info4->server_addr = tsocket_address_inet_addr_string(server, state);
137 if (!info4->server_addr) {
138 /* errno might be EINVAL */
139 tevent_req_error(req, errno);
142 info4->server_port = tsocket_address_inet_port(server);
143 if (!info4->server_name) {
144 info4->server_name = info4->server_addr;
147 info4->session_info = discard_const_p(struct auth_session_info_transport, session_info);
150 NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
153 ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
154 state, &state->auth_req,
155 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
156 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
157 tevent_req_error(req, EINVAL);
161 state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
162 state->auth_req_iov.iov_len = state->auth_req_blob.length;
164 subreq = tstream_unix_connect_send(state,
168 if (tevent_req_nomem(subreq, req)) {
171 tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
176 tevent_req_post(req, ev);
180 static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
182 static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
184 struct tevent_req *req =
185 tevent_req_callback_data(subreq,
187 struct tstream_npa_connect_state *state =
189 struct tstream_npa_connect_state);
193 ret = tstream_unix_connect_recv(subreq, &sys_errno,
194 state, &state->unix_stream);
197 tevent_req_error(req, sys_errno);
201 subreq = tstream_writev_send(state,
204 &state->auth_req_iov, 1);
205 if (tevent_req_nomem(subreq, req)) {
208 tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
211 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
214 struct iovec **_vector,
216 static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
218 static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
220 struct tevent_req *req =
221 tevent_req_callback_data(subreq,
223 struct tstream_npa_connect_state *state =
225 struct tstream_npa_connect_state);
229 ret = tstream_writev_recv(subreq, &sys_errno);
232 tevent_req_error(req, sys_errno);
236 state->auth_rep_blob = data_blob_const(NULL, 0);
238 subreq = tstream_readv_pdu_send(state, state->caller.ev,
240 tstream_npa_connect_next_vector,
242 if (tevent_req_nomem(subreq, req)) {
245 tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
248 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
251 struct iovec **_vector,
254 struct tstream_npa_connect_state *state = talloc_get_type_abort(private_data,
255 struct tstream_npa_connect_state);
256 struct iovec *vector;
260 if (state->auth_rep_blob.length == 0) {
261 state->auth_rep_blob = data_blob_talloc(state, NULL, 4);
262 if (!state->auth_rep_blob.data) {
265 } else if (state->auth_rep_blob.length == 4) {
270 msg_len = RIVAL(state->auth_rep_blob.data, 0);
272 if (msg_len > 0x00FFFFFF) {
284 state->auth_rep_blob.data = talloc_realloc(state,
285 state->auth_rep_blob.data,
287 if (!state->auth_rep_blob.data) {
290 state->auth_rep_blob.length = msg_len;
297 /* we need to get a message header */
298 vector = talloc_array(mem_ctx, struct iovec, 1);
302 vector[0].iov_base = (char *) (state->auth_rep_blob.data + ofs);
303 vector[0].iov_len = state->auth_rep_blob.length - ofs;
311 static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
313 struct tevent_req *req =
314 tevent_req_callback_data(subreq,
316 struct tstream_npa_connect_state *state =
318 struct tstream_npa_connect_state);
321 enum ndr_err_code ndr_err;
323 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
326 tevent_req_error(req, sys_errno);
330 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
331 (uint32_t)state->auth_rep_blob.length));
332 dump_data(11, state->auth_rep_blob.data, state->auth_rep_blob.length);
334 ndr_err = ndr_pull_struct_blob(
335 &state->auth_rep_blob, state,
337 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
339 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
340 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
341 ndr_map_error2string(ndr_err)));
342 tevent_req_error(req, EIO);
347 NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
350 if (state->auth_rep.length < 16) {
351 DEBUG(0, ("req invalid length: %u < 16\n",
352 state->auth_rep.length));
353 tevent_req_error(req, EIO);
357 if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
358 DEBUG(0, ("req invalid magic: %s != %s\n",
359 state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
360 tevent_req_error(req, EIO);
364 if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
365 DEBUG(0, ("req failed: %s\n",
366 nt_errstr(state->auth_rep.status)));
367 tevent_req_error(req, EACCES);
371 if (state->auth_rep.level != state->auth_req.level) {
372 DEBUG(0, ("req invalid level: %u != %u\n",
373 state->auth_rep.level, state->auth_req.level));
374 tevent_req_error(req, EIO);
378 tevent_req_done(req);
381 int _tstream_npa_connect_recv(struct tevent_req *req,
384 struct tstream_context **_stream,
385 uint16_t *_file_type,
386 uint16_t *_device_state,
387 uint64_t *_allocation_size,
388 const char *location)
390 struct tstream_npa_connect_state *state =
392 struct tstream_npa_connect_state);
393 struct tstream_context *stream;
394 struct tstream_npa *npas;
395 uint16_t device_state = 0;
396 uint64_t allocation_size = 0;
398 if (tevent_req_is_unix_error(req, perrno)) {
399 tevent_req_received(req);
403 stream = tstream_context_create(mem_ctx,
410 tevent_req_received(req);
415 npas->unix_stream = talloc_move(stream, &state->unix_stream);
416 switch (state->auth_rep.level) {
418 npas->file_type = state->auth_rep.info.info4.file_type;
419 device_state = state->auth_rep.info.info4.device_state;
420 allocation_size = state->auth_rep.info.info4.allocation_size;
425 *_file_type = npas->file_type;
426 *_device_state = device_state;
427 *_allocation_size = allocation_size;
428 tevent_req_received(req);
432 static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
434 struct tstream_npa *npas = tstream_context_data(stream,
438 if (!npas->unix_stream) {
443 switch (npas->file_type) {
444 case FILE_TYPE_BYTE_MODE_PIPE:
445 ret = tstream_pending_bytes(npas->unix_stream);
448 case FILE_TYPE_MESSAGE_MODE_PIPE:
449 ret = npas->pending.iov_len;
459 struct tstream_npa_readv_state {
460 struct tstream_context *stream;
462 struct iovec *vector;
465 /* the header for message mode */
472 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
473 static int tstream_npa_readv_next_vector(struct tstream_context *stream,
476 struct iovec **_vector,
478 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
480 static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
481 struct tevent_context *ev,
482 struct tstream_context *stream,
483 struct iovec *vector,
486 struct tevent_req *req;
487 struct tstream_npa_readv_state *state;
488 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
489 struct tevent_req *subreq;
494 req = tevent_req_create(mem_ctx, &state,
495 struct tstream_npa_readv_state);
500 state->stream = stream;
503 if (!npas->unix_stream) {
504 tevent_req_error(req, ENOTCONN);
508 switch (npas->file_type) {
509 case FILE_TYPE_BYTE_MODE_PIPE:
510 state->vector = vector;
511 state->count = count;
513 subreq = tstream_readv_send(state,
518 if (tevent_req_nomem(subreq,req)) {
521 tevent_req_set_callback(subreq,
522 tstream_npa_readv_byte_mode_handler,
527 case FILE_TYPE_MESSAGE_MODE_PIPE:
529 * we make a copy of the vector and prepend a header
532 state->vector = talloc_array(state, struct iovec, count);
533 if (tevent_req_nomem(state->vector, req)) {
536 memcpy(state->vector, vector, sizeof(struct iovec)*count);
537 state->count = count;
540 * copy the pending buffer first
543 left = npas->pending.iov_len;
544 pbase = (uint8_t *)npas->pending.iov_base;
546 while (left > 0 && state->count > 0) {
548 base = (uint8_t *)state->vector[0].iov_base;
549 if (left < state->vector[0].iov_len) {
550 memcpy(base, pbase + ofs, left);
553 state->vector[0].iov_base = (char *) base;
554 state->vector[0].iov_len -= left;
559 ZERO_STRUCT(npas->pending);
562 memcpy(base, pbase + ofs, state->vector[0].iov_len);
564 ofs += state->vector[0].iov_len;
565 left -= state->vector[0].iov_len;
571 ZERO_STRUCT(npas->pending);
577 memmove(pbase, pbase + ofs, left);
578 npas->pending.iov_base = (char *) pbase;
579 npas->pending.iov_len = left;
581 * this cannot fail and even if it
582 * fails we can handle it
584 pbase = talloc_realloc(npas, pbase, uint8_t, left);
586 npas->pending.iov_base = (char *) pbase;
593 if (state->count == 0) {
594 tevent_req_done(req);
598 ZERO_STRUCT(state->hdr);
599 state->wait_for_hdr = false;
601 subreq = tstream_readv_pdu_send(state,
604 tstream_npa_readv_next_vector,
606 if (tevent_req_nomem(subreq, req)) {
609 tevent_req_set_callback(subreq,
610 tstream_npa_readv_msg_mode_handler,
616 /* this can't happen */
617 tevent_req_error(req, EINVAL);
621 tevent_req_post(req, ev);
625 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
627 struct tevent_req *req = tevent_req_callback_data(subreq,
629 struct tstream_npa_readv_state *state = tevent_req_data(req,
630 struct tstream_npa_readv_state);
634 ret = tstream_readv_recv(subreq, &sys_errno);
637 tevent_req_error(req, sys_errno);
643 tevent_req_done(req);
646 static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
649 struct iovec **_vector,
652 struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
653 struct tstream_npa_readv_state);
654 struct tstream_npa *npas = tstream_context_data(state->stream,
656 struct iovec *vector;
661 if (state->count == 0) {
667 if (!state->wait_for_hdr) {
668 /* we need to get a message header */
669 vector = talloc_array(mem_ctx, struct iovec, 1);
673 ZERO_STRUCT(state->hdr);
674 vector[0].iov_base = (char *) state->hdr;
675 vector[0].iov_len = sizeof(state->hdr);
679 state->wait_for_hdr = true;
686 /* and now fill the callers buffers and maybe the pending buffer */
687 state->wait_for_hdr = false;
689 msg_len = SVAL(state->hdr, 0);
696 state->wait_for_hdr = false;
698 /* +1 because we may need to fill the pending buffer */
699 vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
706 while (left > 0 && state->count > 0) {
707 if (left < state->vector[0].iov_len) {
709 base = (uint8_t *)state->vector[0].iov_base;
710 vector[count].iov_base = (char *) base;
711 vector[count].iov_len = left;
714 state->vector[0].iov_base = (char *) base;
715 state->vector[0].iov_len -= left;
718 vector[count] = state->vector[0];
720 left -= state->vector[0].iov_len;
727 * if the message is longer than the buffers the caller
728 * requested, we need to consume the rest of the message
729 * into the pending buffer, where the next readv can
732 npas->pending.iov_base = talloc_array(npas, char, left);
733 if (!npas->pending.iov_base) {
736 npas->pending.iov_len = left;
738 vector[count] = npas->pending;
742 state->ret += (msg_len - left);
749 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
751 struct tevent_req *req = tevent_req_callback_data(subreq,
756 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
759 tevent_req_error(req, sys_errno);
764 * we do not set state->ret here as ret includes the headr size.
765 * we set it in tstream_npa_readv_pdu_next_vector()
768 tevent_req_done(req);
771 static int tstream_npa_readv_recv(struct tevent_req *req,
774 struct tstream_npa_readv_state *state = tevent_req_data(req,
775 struct tstream_npa_readv_state);
778 ret = tsocket_simple_int_recv(req, perrno);
783 tevent_req_received(req);
787 struct tstream_npa_writev_state {
788 const struct iovec *vector;
791 /* the header for message mode */
798 static void tstream_npa_writev_handler(struct tevent_req *subreq);
800 static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
801 struct tevent_context *ev,
802 struct tstream_context *stream,
803 const struct iovec *vector,
806 struct tevent_req *req;
807 struct tstream_npa_writev_state *state;
808 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
809 struct tevent_req *subreq;
812 struct iovec *new_vector;
814 req = tevent_req_create(mem_ctx, &state,
815 struct tstream_npa_writev_state);
822 if (!npas->unix_stream) {
823 tevent_req_error(req, ENOTCONN);
827 switch (npas->file_type) {
828 case FILE_TYPE_BYTE_MODE_PIPE:
829 state->hdr_used = false;
830 state->vector = vector;
831 state->count = count;
834 case FILE_TYPE_MESSAGE_MODE_PIPE:
836 * we make a copy of the vector and prepend a header
839 new_vector = talloc_array(state, struct iovec, count + 1);
840 if (tevent_req_nomem(new_vector, req)) {
843 new_vector[0].iov_base = (char *) state->hdr;
844 new_vector[0].iov_len = sizeof(state->hdr);
845 memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
847 state->hdr_used = true;
848 state->vector = new_vector;
849 state->count = count + 1;
852 for (i=0; i < count; i++) {
853 msg_len += vector[i].iov_len;
856 if (msg_len > UINT16_MAX) {
857 tevent_req_error(req, EMSGSIZE);
861 SSVAL(state->hdr, 0, msg_len);
865 subreq = tstream_writev_send(state,
870 if (tevent_req_nomem(subreq, req)) {
873 tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
878 tevent_req_post(req, ev);
882 static void tstream_npa_writev_handler(struct tevent_req *subreq)
884 struct tevent_req *req = tevent_req_callback_data(subreq,
886 struct tstream_npa_writev_state *state = tevent_req_data(req,
887 struct tstream_npa_writev_state);
891 ret = tstream_writev_recv(subreq, &sys_errno);
894 tevent_req_error(req, sys_errno);
899 * in message mode we need to hide the length
900 * of the hdr from the caller
902 if (state->hdr_used) {
903 ret -= sizeof(state->hdr);
908 tevent_req_done(req);
911 static int tstream_npa_writev_recv(struct tevent_req *req,
914 struct tstream_npa_writev_state *state = tevent_req_data(req,
915 struct tstream_npa_writev_state);
918 ret = tsocket_simple_int_recv(req, perrno);
923 tevent_req_received(req);
927 struct tstream_npa_disconnect_state {
928 struct tstream_context *stream;
931 static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
933 static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
934 struct tevent_context *ev,
935 struct tstream_context *stream)
937 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
938 struct tevent_req *req;
939 struct tstream_npa_disconnect_state *state;
940 struct tevent_req *subreq;
942 req = tevent_req_create(mem_ctx, &state,
943 struct tstream_npa_disconnect_state);
948 state->stream = stream;
950 if (!npas->unix_stream) {
951 tevent_req_error(req, ENOTCONN);
955 subreq = tstream_disconnect_send(state,
958 if (tevent_req_nomem(subreq, req)) {
961 tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
966 tevent_req_post(req, ev);
970 static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
972 struct tevent_req *req = tevent_req_callback_data(subreq,
974 struct tstream_npa_disconnect_state *state = tevent_req_data(req,
975 struct tstream_npa_disconnect_state);
976 struct tstream_context *stream = state->stream;
977 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
981 ret = tstream_disconnect_recv(subreq, &sys_errno);
984 tevent_req_error(req, sys_errno);
988 TALLOC_FREE(npas->unix_stream);
990 tevent_req_done(req);
993 static int tstream_npa_disconnect_recv(struct tevent_req *req,
998 ret = tsocket_simple_int_recv(req, perrno);
1000 tevent_req_received(req);
1004 static const struct tstream_context_ops tstream_npa_ops = {
1007 .pending_bytes = tstream_npa_pending_bytes,
1009 .readv_send = tstream_npa_readv_send,
1010 .readv_recv = tstream_npa_readv_recv,
1012 .writev_send = tstream_npa_writev_send,
1013 .writev_recv = tstream_npa_writev_recv,
1015 .disconnect_send = tstream_npa_disconnect_send,
1016 .disconnect_recv = tstream_npa_disconnect_recv,
1019 int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
1022 struct tstream_context **_stream,
1023 const char *location)
1025 struct tstream_context *stream;
1026 struct tstream_npa *npas;
1029 switch (file_type) {
1030 case FILE_TYPE_BYTE_MODE_PIPE:
1032 case FILE_TYPE_MESSAGE_MODE_PIPE:
1039 stream = tstream_context_create(mem_ctx,
1049 npas->file_type = file_type;
1051 ret = tstream_bsd_existing_socket(stream, fd,
1052 &npas->unix_stream);
1054 int saved_errno = errno;
1055 talloc_free(stream);
1056 errno = saved_errno;
1065 struct tstream_npa_accept_state {
1066 struct tevent_context *ev;
1067 struct tstream_context *plain;
1069 uint16_t device_state;
1070 uint64_t alloc_size;
1073 struct iovec out_iov;
1076 NTSTATUS accept_status;
1077 struct tsocket_address *client;
1079 struct tsocket_address *server;
1081 struct auth_session_info_transport *session_info;
1084 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1086 TALLOC_CTX *mem_ctx,
1087 struct iovec **_vector,
1089 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1090 static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1092 struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1093 struct tevent_context *ev,
1094 struct tstream_context *plain,
1096 uint16_t device_state,
1097 uint64_t allocation_size)
1099 struct tstream_npa_accept_state *state;
1100 struct tevent_req *req, *subreq;
1102 req = tevent_req_create(mem_ctx, &state,
1103 struct tstream_npa_accept_state);
1108 switch (file_type) {
1109 case FILE_TYPE_BYTE_MODE_PIPE:
1111 case FILE_TYPE_MESSAGE_MODE_PIPE:
1114 tevent_req_error(req, EINVAL);
1118 ZERO_STRUCTP(state);
1121 state->plain = plain;
1122 state->file_type = file_type;
1123 state->device_state = device_state;
1124 state->alloc_size = allocation_size;
1127 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1128 * named_pipe_full_request provides the pdu length then.
1130 subreq = tstream_readv_pdu_send(state, ev, plain,
1131 tstream_npa_accept_next_vector,
1133 if (tevent_req_nomem(subreq, req)) {
1137 tevent_req_set_callback(subreq,
1138 tstream_npa_accept_existing_reply, req);
1143 tevent_req_post(req, ev);
1147 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1149 TALLOC_CTX *mem_ctx,
1150 struct iovec **_vector,
1153 struct tstream_npa_accept_state *state =
1154 talloc_get_type_abort(private_data,
1155 struct tstream_npa_accept_state);
1156 struct iovec *vector;
1160 if (state->npa_blob.length == 0) {
1161 state->npa_blob = data_blob_talloc(state, NULL, 4);
1162 if (!state->npa_blob.data) {
1165 } else if (state->npa_blob.length == 4) {
1170 msg_len = RIVAL(state->npa_blob.data, 0);
1172 if (msg_len > 0x00FFFFFF) {
1184 state->npa_blob.data = talloc_realloc(state,
1185 state->npa_blob.data,
1187 if (!state->npa_blob.data) {
1190 state->npa_blob.length = msg_len;
1192 if (memcmp(&state->npa_blob.data[4],
1193 NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1194 DEBUG(0, ("Wrong protocol\n"));
1195 #if defined(EPROTONOSUPPORT)
1196 errno = EPROTONOSUPPORT;
1197 #elif defined(EPROTO)
1209 /* we need to get a message header */
1210 vector = talloc_array(mem_ctx, struct iovec, 1);
1214 vector[0].iov_base = (char *) (state->npa_blob.data + ofs);
1215 vector[0].iov_len = state->npa_blob.length - ofs;
1223 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1225 struct tevent_req *req =
1226 tevent_req_callback_data(subreq, struct tevent_req);
1227 struct tstream_npa_accept_state *state =
1228 tevent_req_data(req, struct tstream_npa_accept_state);
1229 struct named_pipe_auth_req *pipe_request;
1230 struct named_pipe_auth_rep pipe_reply;
1231 struct named_pipe_auth_req_info4 i4;
1232 enum ndr_err_code ndr_err;
1237 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
1238 TALLOC_FREE(subreq);
1240 tevent_req_error(req, sys_errno);
1244 DEBUG(10, ("Received packet of length %lu\n",
1245 (long)state->npa_blob.length));
1246 dump_data(11, state->npa_blob.data, state->npa_blob.length);
1248 ZERO_STRUCT(pipe_reply);
1249 pipe_reply.level = 0;
1250 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1252 * TODO: check it's a root (uid == 0) pipe
1255 pipe_request = talloc(state, struct named_pipe_auth_req);
1256 if (!pipe_request) {
1257 DEBUG(0, ("Out of memory!\n"));
1261 /* parse the passed credentials */
1262 ndr_err = ndr_pull_struct_blob_all(
1263 &state->npa_blob, pipe_request, pipe_request,
1264 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1265 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1266 pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1267 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1268 nt_errstr(pipe_reply.status)));
1273 NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1278 if (pipe_request->level != 4) {
1279 DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1280 pipe_reply.level = 0;
1281 pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1285 pipe_reply.level = 4;
1286 pipe_reply.status = NT_STATUS_OK;
1287 pipe_reply.info.info4.file_type = state->file_type;
1288 pipe_reply.info.info4.device_state = state->device_state;
1289 pipe_reply.info.info4.allocation_size = state->alloc_size;
1291 i4 = pipe_request->info.info4;
1292 if (i4.server_addr == NULL) {
1293 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1294 DEBUG(2, ("Missing server address\n"));
1297 if (i4.client_addr == NULL) {
1298 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1299 DEBUG(2, ("Missing client address\n"));
1303 state->server_name = discard_const_p(char,
1304 talloc_move(state, &i4.server_name));
1305 ret = tsocket_address_inet_from_strings(state, "ip",
1310 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1311 i4.server_addr, i4.server_port,
1313 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1317 state->client_name = discard_const_p(char,
1318 talloc_move(state, &i4.client_name));
1319 ret = tsocket_address_inet_from_strings(state, "ip",
1324 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1325 i4.client_addr, i4.client_port,
1327 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1331 state->session_info = talloc_move(state, &i4.session_info);
1333 /* create the output */
1334 ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1335 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1336 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1337 DEBUG(2, ("Error encoding structure: %s",
1338 ndr_map_error2string(ndr_err)));
1339 tevent_req_error(req, EIO);
1343 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1344 dump_data(11, out.data, out.length);
1347 NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1350 state->accept_status = pipe_reply.status;
1352 state->out_iov.iov_base = (char *) out.data;
1353 state->out_iov.iov_len = out.length;
1355 subreq = tstream_writev_send(state, state->ev,
1357 &state->out_iov, 1);
1358 if (tevent_req_nomem(subreq, req)) {
1359 DEBUG(0, ("no memory for tstream_writev_send"));
1363 tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1366 static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1368 struct tevent_req *req =
1369 tevent_req_callback_data(subreq, struct tevent_req);
1373 ret = tstream_writev_recv(subreq, &sys_errno);
1374 TALLOC_FREE(subreq);
1376 tevent_req_error(req, sys_errno);
1380 tevent_req_done(req);
1383 int _tstream_npa_accept_existing_recv(struct tevent_req *req,
1385 TALLOC_CTX *mem_ctx,
1386 struct tstream_context **stream,
1387 struct tsocket_address **client,
1388 char **_client_name,
1389 struct tsocket_address **server,
1391 struct auth_session_info_transport **session_info,
1392 const char *location)
1394 struct tstream_npa_accept_state *state =
1395 tevent_req_data(req, struct tstream_npa_accept_state);
1396 struct tstream_npa *npas;
1399 ret = tsocket_simple_int_recv(req, perrno);
1401 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1402 strerror(*perrno)));
1403 tevent_req_received(req);
1407 if (!NT_STATUS_IS_OK(state->accept_status)) {
1408 #if defined(EPROTONOSUPPORT)
1409 *perrno = EPROTONOSUPPORT;
1410 #elif defined(EPROTO)
1415 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1416 nt_errstr(state->accept_status),
1417 strerror(*perrno)));
1418 tevent_req_received(req);
1422 *stream = tstream_context_create(mem_ctx,
1429 tevent_req_received(req);
1433 npas->unix_stream = state->plain;
1434 npas->file_type = state->file_type;
1436 *client = talloc_move(mem_ctx, &state->client);
1437 *_client_name = talloc_move(mem_ctx, &state->client_name);
1438 *server = talloc_move(mem_ctx, &state->server);
1439 *server_name = talloc_move(mem_ctx, &state->server_name);
1440 *session_info = talloc_move(mem_ctx, &state->session_info);
1442 tevent_req_received(req);