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,
427 npas->unix_stream = talloc_move(stream, &state->unix_stream);
428 switch (state->auth_rep.level) {
431 npas->file_type = FILE_TYPE_BYTE_MODE_PIPE;
432 device_state = 0x00ff;
433 allocation_size = 2048;
436 npas->file_type = state->auth_rep.info.info2.file_type;
437 device_state = state->auth_rep.info.info2.device_state;
438 allocation_size = state->auth_rep.info.info2.allocation_size;
441 npas->file_type = state->auth_rep.info.info3.file_type;
442 device_state = state->auth_rep.info.info3.device_state;
443 allocation_size = state->auth_rep.info.info3.allocation_size;
448 *_file_type = npas->file_type;
449 *_device_state = device_state;
450 *_allocation_size = allocation_size;
451 tevent_req_received(req);
455 static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
457 struct tstream_npa *npas = tstream_context_data(stream,
461 if (!npas->unix_stream) {
466 switch (npas->file_type) {
467 case FILE_TYPE_BYTE_MODE_PIPE:
468 ret = tstream_pending_bytes(npas->unix_stream);
471 case FILE_TYPE_MESSAGE_MODE_PIPE:
472 ret = npas->pending.iov_len;
482 struct tstream_npa_readv_state {
483 struct tstream_context *stream;
485 struct iovec *vector;
488 /* the header for message mode */
495 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
496 static int tstream_npa_readv_next_vector(struct tstream_context *stream,
499 struct iovec **_vector,
501 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
503 static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
504 struct tevent_context *ev,
505 struct tstream_context *stream,
506 struct iovec *vector,
509 struct tevent_req *req;
510 struct tstream_npa_readv_state *state;
511 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
512 struct tevent_req *subreq;
517 req = tevent_req_create(mem_ctx, &state,
518 struct tstream_npa_readv_state);
523 state->stream = stream;
526 if (!npas->unix_stream) {
527 tevent_req_error(req, ENOTCONN);
531 switch (npas->file_type) {
532 case FILE_TYPE_BYTE_MODE_PIPE:
533 state->vector = vector;
534 state->count = count;
536 subreq = tstream_readv_send(state,
541 if (tevent_req_nomem(subreq,req)) {
544 tevent_req_set_callback(subreq,
545 tstream_npa_readv_byte_mode_handler,
550 case FILE_TYPE_MESSAGE_MODE_PIPE:
552 * we make a copy of the vector and prepend a header
555 state->vector = talloc_array(state, struct iovec, count);
556 if (tevent_req_nomem(state->vector, req)) {
559 memcpy(state->vector, vector, sizeof(struct iovec)*count);
560 state->count = count;
563 * copy the pending buffer first
566 left = npas->pending.iov_len;
567 pbase = (uint8_t *)npas->pending.iov_base;
569 while (left > 0 && state->count > 0) {
571 base = (uint8_t *)state->vector[0].iov_base;
572 if (left < state->vector[0].iov_len) {
573 memcpy(base, pbase + ofs, left);
576 state->vector[0].iov_base = base;
577 state->vector[0].iov_len -= left;
582 ZERO_STRUCT(npas->pending);
585 memcpy(base, pbase + ofs, state->vector[0].iov_len);
587 ofs += state->vector[0].iov_len;
588 left -= state->vector[0].iov_len;
594 ZERO_STRUCT(npas->pending);
600 memmove(pbase, pbase + ofs, left);
601 npas->pending.iov_base = pbase;
602 npas->pending.iov_len = left;
604 * this cannot fail and even if it
605 * fails we can handle it
607 pbase = talloc_realloc(npas, pbase, uint8_t, left);
609 npas->pending.iov_base = pbase;
616 if (state->count == 0) {
617 tevent_req_done(req);
621 ZERO_STRUCT(state->hdr);
622 state->wait_for_hdr = false;
624 subreq = tstream_readv_pdu_send(state,
627 tstream_npa_readv_next_vector,
629 if (tevent_req_nomem(subreq, req)) {
632 tevent_req_set_callback(subreq,
633 tstream_npa_readv_msg_mode_handler,
639 /* this can't happen */
640 tevent_req_error(req, EINVAL);
644 tevent_req_post(req, ev);
648 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
650 struct tevent_req *req = tevent_req_callback_data(subreq,
652 struct tstream_npa_readv_state *state = tevent_req_data(req,
653 struct tstream_npa_readv_state);
657 ret = tstream_readv_recv(subreq, &sys_errno);
660 tevent_req_error(req, sys_errno);
666 tevent_req_done(req);
669 static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
672 struct iovec **_vector,
675 struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
676 struct tstream_npa_readv_state);
677 struct tstream_npa *npas = tstream_context_data(state->stream,
679 struct iovec *vector;
684 if (state->count == 0) {
690 if (!state->wait_for_hdr) {
691 /* we need to get a message header */
692 vector = talloc_array(mem_ctx, struct iovec, 1);
696 ZERO_STRUCT(state->hdr);
697 vector[0].iov_base = state->hdr;
698 vector[0].iov_len = sizeof(state->hdr);
702 state->wait_for_hdr = true;
709 /* and now fill the callers buffers and maybe the pending buffer */
710 state->wait_for_hdr = false;
712 msg_len = SVAL(state->hdr, 0);
719 state->wait_for_hdr = false;
721 /* +1 because we may need to fill the pending buffer */
722 vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
729 while (left > 0 && state->count > 0) {
730 if (left < state->vector[0].iov_len) {
732 base = (uint8_t *)state->vector[0].iov_base;
733 vector[count].iov_base = base;
734 vector[count].iov_len = left;
737 state->vector[0].iov_base = base;
738 state->vector[0].iov_len -= left;
741 vector[count] = state->vector[0];
743 left -= state->vector[0].iov_len;
750 * if the message is longer than the buffers the caller
751 * requested, we need to consume the rest of the message
752 * into the pending buffer, where the next readv can
755 npas->pending.iov_base = talloc_array(npas, uint8_t, left);
756 if (!npas->pending.iov_base) {
759 npas->pending.iov_len = left;
761 vector[count] = npas->pending;
765 state->ret += (msg_len - left);
772 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
774 struct tevent_req *req = tevent_req_callback_data(subreq,
779 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
782 tevent_req_error(req, sys_errno);
787 * we do not set state->ret here as ret includes the headr size.
788 * we set it in tstream_npa_readv_pdu_next_vector()
791 tevent_req_done(req);
794 static int tstream_npa_readv_recv(struct tevent_req *req,
797 struct tstream_npa_readv_state *state = tevent_req_data(req,
798 struct tstream_npa_readv_state);
801 ret = tsocket_simple_int_recv(req, perrno);
806 tevent_req_received(req);
810 struct tstream_npa_writev_state {
811 const struct iovec *vector;
814 /* the header for message mode */
821 static void tstream_npa_writev_handler(struct tevent_req *subreq);
823 static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
824 struct tevent_context *ev,
825 struct tstream_context *stream,
826 const struct iovec *vector,
829 struct tevent_req *req;
830 struct tstream_npa_writev_state *state;
831 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
832 struct tevent_req *subreq;
835 struct iovec *new_vector;
837 req = tevent_req_create(mem_ctx, &state,
838 struct tstream_npa_writev_state);
845 if (!npas->unix_stream) {
846 tevent_req_error(req, ENOTCONN);
850 switch (npas->file_type) {
851 case FILE_TYPE_BYTE_MODE_PIPE:
852 state->hdr_used = false;
853 state->vector = vector;
854 state->count = count;
857 case FILE_TYPE_MESSAGE_MODE_PIPE:
859 * we make a copy of the vector and prepend a header
862 new_vector = talloc_array(state, struct iovec, count + 1);
863 if (tevent_req_nomem(new_vector, req)) {
866 new_vector[0].iov_base = state->hdr;
867 new_vector[0].iov_len = sizeof(state->hdr);
868 memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
870 state->hdr_used = true;
871 state->vector = new_vector;
872 state->count = count + 1;
875 for (i=0; i < count; i++) {
876 msg_len += vector[i].iov_len;
879 if (msg_len > UINT16_MAX) {
880 tevent_req_error(req, EMSGSIZE);
884 SSVAL(state->hdr, 0, msg_len);
888 subreq = tstream_writev_send(state,
893 if (tevent_req_nomem(subreq, req)) {
896 tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
901 tevent_req_post(req, ev);
905 static void tstream_npa_writev_handler(struct tevent_req *subreq)
907 struct tevent_req *req = tevent_req_callback_data(subreq,
909 struct tstream_npa_writev_state *state = tevent_req_data(req,
910 struct tstream_npa_writev_state);
914 ret = tstream_writev_recv(subreq, &sys_errno);
917 tevent_req_error(req, sys_errno);
922 * in message mode we need to hide the length
923 * of the hdr from the caller
925 if (state->hdr_used) {
926 ret -= sizeof(state->hdr);
931 tevent_req_done(req);
934 static int tstream_npa_writev_recv(struct tevent_req *req,
937 struct tstream_npa_writev_state *state = tevent_req_data(req,
938 struct tstream_npa_writev_state);
941 ret = tsocket_simple_int_recv(req, perrno);
946 tevent_req_received(req);
950 struct tstream_npa_disconnect_state {
951 struct tstream_context *stream;
954 static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
956 static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
957 struct tevent_context *ev,
958 struct tstream_context *stream)
960 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
961 struct tevent_req *req;
962 struct tstream_npa_disconnect_state *state;
963 struct tevent_req *subreq;
965 req = tevent_req_create(mem_ctx, &state,
966 struct tstream_npa_disconnect_state);
971 state->stream = stream;
973 if (!npas->unix_stream) {
974 tevent_req_error(req, ENOTCONN);
978 subreq = tstream_disconnect_send(state,
981 if (tevent_req_nomem(subreq, req)) {
984 tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
989 tevent_req_post(req, ev);
993 static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
995 struct tevent_req *req = tevent_req_callback_data(subreq,
997 struct tstream_npa_disconnect_state *state = tevent_req_data(req,
998 struct tstream_npa_disconnect_state);
999 struct tstream_context *stream = state->stream;
1000 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
1004 ret = tstream_disconnect_recv(subreq, &sys_errno);
1005 TALLOC_FREE(subreq);
1007 tevent_req_error(req, sys_errno);
1011 TALLOC_FREE(npas->unix_stream);
1013 tevent_req_done(req);
1016 static int tstream_npa_disconnect_recv(struct tevent_req *req,
1021 ret = tsocket_simple_int_recv(req, perrno);
1023 tevent_req_received(req);
1027 static const struct tstream_context_ops tstream_npa_ops = {
1030 .pending_bytes = tstream_npa_pending_bytes,
1032 .readv_send = tstream_npa_readv_send,
1033 .readv_recv = tstream_npa_readv_recv,
1035 .writev_send = tstream_npa_writev_send,
1036 .writev_recv = tstream_npa_writev_recv,
1038 .disconnect_send = tstream_npa_disconnect_send,
1039 .disconnect_recv = tstream_npa_disconnect_recv,
1042 int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
1045 struct tstream_context **_stream,
1046 const char *location)
1048 struct tstream_context *stream;
1049 struct tstream_npa *npas;
1052 switch (file_type) {
1053 case FILE_TYPE_BYTE_MODE_PIPE:
1055 case FILE_TYPE_MESSAGE_MODE_PIPE:
1062 stream = tstream_context_create(mem_ctx,
1072 npas->file_type = file_type;
1074 ret = tstream_bsd_existing_socket(stream, fd,
1075 &npas->unix_stream);
1077 int saved_errno = errno;
1078 talloc_free(stream);
1079 errno = saved_errno;
1088 struct tstream_npa_accept_state {
1089 struct tevent_context *ev;
1090 struct tstream_context *plain;
1092 uint16_t device_state;
1093 uint64_t alloc_size;
1096 struct iovec out_iov;
1099 NTSTATUS accept_status;
1100 struct tsocket_address *client;
1102 struct tsocket_address *server;
1104 struct netr_SamInfo3 *info3;
1105 DATA_BLOB session_key;
1106 DATA_BLOB delegated_creds;
1109 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1111 TALLOC_CTX *mem_ctx,
1112 struct iovec **_vector,
1114 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1115 static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1117 struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1118 struct tevent_context *ev,
1119 struct tstream_context *plain,
1121 uint16_t device_state,
1122 uint64_t allocation_size)
1124 struct tstream_npa_accept_state *state;
1125 struct tevent_req *req, *subreq;
1127 req = tevent_req_create(mem_ctx, &state,
1128 struct tstream_npa_accept_state);
1133 switch (file_type) {
1134 case FILE_TYPE_BYTE_MODE_PIPE:
1136 case FILE_TYPE_MESSAGE_MODE_PIPE:
1139 tevent_req_error(req, EINVAL);
1143 ZERO_STRUCTP(state);
1146 state->plain = plain;
1147 state->file_type = file_type;
1148 state->device_state = device_state;
1149 state->alloc_size = allocation_size;
1152 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1153 * named_pipe_full_request provides the pdu length then.
1155 subreq = tstream_readv_pdu_send(state, ev, plain,
1156 tstream_npa_accept_next_vector,
1158 if (tevent_req_nomem(subreq, req)) {
1162 tevent_req_set_callback(subreq,
1163 tstream_npa_accept_existing_reply, req);
1168 tevent_req_post(req, ev);
1172 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1174 TALLOC_CTX *mem_ctx,
1175 struct iovec **_vector,
1178 struct tstream_npa_accept_state *state =
1179 talloc_get_type_abort(private_data,
1180 struct tstream_npa_accept_state);
1181 struct iovec *vector;
1185 if (state->npa_blob.length == 0) {
1186 state->npa_blob = data_blob_talloc(state, NULL, 4);
1187 if (!state->npa_blob.data) {
1190 } else if (state->npa_blob.length == 4) {
1195 msg_len = RIVAL(state->npa_blob.data, 0);
1197 if (msg_len > 0x00FFFFFF) {
1209 state->npa_blob.data = talloc_realloc(state,
1210 state->npa_blob.data,
1212 if (!state->npa_blob.data) {
1215 state->npa_blob.length = msg_len;
1217 if (memcmp(&state->npa_blob.data[4],
1218 NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1219 DEBUG(0, ("Wrong protocol\n"));
1220 #if defined(EPROTONOSUPPORT)
1221 errno = EPROTONOSUPPORT;
1222 #elif defined(EPROTO)
1234 /* we need to get a message header */
1235 vector = talloc_array(mem_ctx, struct iovec, 1);
1239 vector[0].iov_base = state->npa_blob.data + ofs;
1240 vector[0].iov_len = state->npa_blob.length - ofs;
1248 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1250 struct tevent_req *req =
1251 tevent_req_callback_data(subreq, struct tevent_req);
1252 struct tstream_npa_accept_state *state =
1253 tevent_req_data(req, struct tstream_npa_accept_state);
1254 struct named_pipe_auth_req *pipe_request;
1255 struct named_pipe_auth_rep pipe_reply;
1256 struct named_pipe_auth_req_info3 i3;
1257 enum ndr_err_code ndr_err;
1262 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
1263 TALLOC_FREE(subreq);
1265 tevent_req_error(req, sys_errno);
1269 DEBUG(10, ("Received packet of length %lu\n",
1270 (long)state->npa_blob.length));
1271 dump_data(11, state->npa_blob.data, state->npa_blob.length);
1273 ZERO_STRUCT(pipe_reply);
1274 pipe_reply.level = 0;
1275 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1277 * TODO: check it's a root (uid == 0) pipe
1280 pipe_request = talloc(state, struct named_pipe_auth_req);
1281 if (!pipe_request) {
1282 DEBUG(0, ("Out of memory!\n"));
1286 /* parse the passed credentials */
1287 ndr_err = ndr_pull_struct_blob_all(
1288 &state->npa_blob, pipe_request, pipe_request,
1289 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1290 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1291 pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1292 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1293 nt_errstr(pipe_reply.status)));
1298 NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1303 switch (pipe_request->level) {
1305 pipe_reply.level = 0;
1306 pipe_reply.status = NT_STATUS_OK;
1308 /* we need to force byte mode in this level */
1309 state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
1313 pipe_reply.level = 1;
1314 pipe_reply.status = NT_STATUS_OK;
1316 /* We must copy net3_SamInfo3, so that
1317 * info3 is an actual talloc pointer, then we steal
1318 * pipe_request on info3 so that all the allocated memory
1319 * pointed by the structrue members is preserved */
1320 state->info3 = (struct netr_SamInfo3 *)talloc_memdup(state,
1321 &pipe_request->info.info1,
1322 sizeof(struct netr_SamInfo3));
1323 if (!state->info3) {
1324 pipe_reply.status = NT_STATUS_NO_MEMORY;
1325 DEBUG(0, ("Out of memory!\n"));
1328 talloc_steal(state->info3, pipe_request);
1330 /* we need to force byte mode in this level */
1331 state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
1335 pipe_reply.level = 2;
1336 pipe_reply.status = NT_STATUS_OK;
1337 pipe_reply.info.info2.file_type = state->file_type;
1338 pipe_reply.info.info2.device_state = state->device_state;
1339 pipe_reply.info.info2.allocation_size = state->alloc_size;
1341 i3.client_name = pipe_request->info.info2.client_name;
1342 i3.client_addr = pipe_request->info.info2.client_addr;
1343 i3.client_port = pipe_request->info.info2.client_port;
1344 i3.server_name = pipe_request->info.info2.server_name;
1345 i3.server_addr = pipe_request->info.info2.server_addr;
1346 i3.server_port = pipe_request->info.info2.server_port;
1347 i3.sam_info3 = pipe_request->info.info2.sam_info3;
1348 i3.session_key_length =
1349 pipe_request->info.info2.session_key_length;
1350 i3.session_key = pipe_request->info.info2.session_key;
1354 pipe_reply.level = 3;
1355 pipe_reply.status = NT_STATUS_OK;
1356 pipe_reply.info.info3.file_type = state->file_type;
1357 pipe_reply.info.info3.device_state = state->device_state;
1358 pipe_reply.info.info3.allocation_size = state->alloc_size;
1360 i3 = pipe_request->info.info3;
1364 DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1365 pipe_reply.level = 0;
1366 pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1370 if (pipe_reply.level >=2) {
1372 if (i3.server_addr == NULL) {
1373 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1374 DEBUG(2, ("Missing server address\n"));
1377 if (i3.client_addr == NULL) {
1378 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1379 DEBUG(2, ("Missing client address\n"));
1383 state->server_name = discard_const_p(char,
1384 talloc_move(state, &i3.server_name));
1385 ret = tsocket_address_inet_from_strings(state, "ip",
1390 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1391 i3.server_addr, i3.server_port,
1393 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1397 state->client_name = discard_const_p(char,
1398 talloc_move(state, &i3.client_name));
1399 ret = tsocket_address_inet_from_strings(state, "ip",
1404 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1405 i3.client_addr, i3.client_port,
1407 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1411 state->info3 = talloc_move(state, &i3.sam_info3);
1412 state->session_key.data = talloc_move(state, &i3.session_key);
1413 state->session_key.length = i3.session_key_length;
1416 if (pipe_reply.level >= 3) {
1417 state->delegated_creds.data =
1418 talloc_move(state, &i3.gssapi_delegated_creds);
1419 state->delegated_creds.length =
1420 i3.gssapi_delegated_creds_length;
1424 /* create the output */
1425 ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1426 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1427 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1428 DEBUG(2, ("Error encoding structure: %s",
1429 ndr_map_error2string(ndr_err)));
1430 tevent_req_error(req, EIO);
1434 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1435 dump_data(11, out.data, out.length);
1438 NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1441 state->accept_status = pipe_reply.status;
1443 state->out_iov.iov_base = out.data;
1444 state->out_iov.iov_len = out.length;
1446 subreq = tstream_writev_send(state, state->ev,
1448 &state->out_iov, 1);
1449 if (tevent_req_nomem(subreq, req)) {
1450 DEBUG(0, ("no memory for tstream_writev_send"));
1454 tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1457 static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1459 struct tevent_req *req =
1460 tevent_req_callback_data(subreq, struct tevent_req);
1464 ret = tstream_writev_recv(subreq, &sys_errno);
1465 TALLOC_FREE(subreq);
1467 tevent_req_error(req, sys_errno);
1471 tevent_req_done(req);
1474 int _tstream_npa_accept_existing_recv(struct tevent_req *req,
1476 TALLOC_CTX *mem_ctx,
1477 struct tstream_context **stream,
1478 struct tsocket_address **client,
1479 char **_client_name,
1480 struct tsocket_address **server,
1482 struct netr_SamInfo3 **info3,
1483 DATA_BLOB *session_key,
1484 DATA_BLOB *delegated_creds,
1485 const char *location)
1487 struct tstream_npa_accept_state *state =
1488 tevent_req_data(req, struct tstream_npa_accept_state);
1489 struct tstream_npa *npas;
1492 ret = tsocket_simple_int_recv(req, perrno);
1494 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1495 strerror(*perrno)));
1496 tevent_req_received(req);
1500 if (!NT_STATUS_IS_OK(state->accept_status)) {
1501 #if defined(EPROTONOSUPPORT)
1502 *perrno = EPROTONOSUPPORT;
1503 #elif defined(EPROTO)
1508 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1509 nt_errstr(state->accept_status),
1510 strerror(*perrno)));
1511 tevent_req_received(req);
1515 *stream = tstream_context_create(mem_ctx,
1522 tevent_req_received(req);
1526 npas->unix_stream = state->plain;
1527 npas->file_type = state->file_type;
1529 *client = talloc_move(mem_ctx, &state->client);
1530 *_client_name = talloc_move(mem_ctx, &state->client_name);
1531 *server = talloc_move(mem_ctx, &state->server);
1532 *server_name = talloc_move(mem_ctx, &state->server_name);
1533 *info3 = talloc_move(mem_ctx, &state->info3);
1534 *session_key = state->session_key;
1535 talloc_steal(mem_ctx, state->session_key.data);
1536 *delegated_creds = state->delegated_creds;
1537 talloc_steal(mem_ctx, state->delegated_creds.data);
1539 tevent_req_received(req);