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 = strlower_talloc(mem_ctx, npipe);
78 if (!lower_case_npipe) {
82 req = tevent_req_create(mem_ctx, &state,
83 struct tstream_npa_connect_state);
88 state->caller.ev = ev;
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 struct named_pipe_auth_req_info3 *info3;
119 tevent_req_error(req, EINVAL);
123 state->auth_req.level = 3;
124 info3 = &state->auth_req.info.info3;
126 info3->client_name = client_name_in;
127 info3->client_addr = tsocket_address_inet_addr_string(client, state);
128 if (!info3->client_addr) {
129 /* errno might be EINVAL */
130 tevent_req_error(req, errno);
133 info3->client_port = tsocket_address_inet_port(client);
134 if (!info3->client_name) {
135 info3->client_name = info3->client_addr;
138 info3->server_addr = tsocket_address_inet_addr_string(server, state);
139 if (!info3->server_addr) {
140 /* errno might be EINVAL */
141 tevent_req_error(req, errno);
144 info3->server_port = tsocket_address_inet_port(server);
145 if (!info3->server_name) {
146 info3->server_name = info3->server_addr;
149 info3->sam_info3 = discard_const_p(struct netr_SamInfo3, sam_info3);
150 info3->session_key_length = session_key.length;
151 info3->session_key = session_key.data;
152 info3->gssapi_delegated_creds_length = delegated_creds.length;
153 info3->gssapi_delegated_creds = delegated_creds.data;
155 } else if (sam_info3) {
156 state->auth_req.level = 1;
157 state->auth_req.info.info1 = *sam_info3;
159 state->auth_req.level = 0;
163 NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
166 ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
167 state, &state->auth_req,
168 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
169 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
170 tevent_req_error(req, EINVAL);
174 state->auth_req_iov.iov_base = state->auth_req_blob.data;
175 state->auth_req_iov.iov_len = state->auth_req_blob.length;
177 subreq = tstream_unix_connect_send(state,
181 if (tevent_req_nomem(subreq, req)) {
184 tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
189 tevent_req_post(req, ev);
193 static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
195 static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
197 struct tevent_req *req =
198 tevent_req_callback_data(subreq,
200 struct tstream_npa_connect_state *state =
202 struct tstream_npa_connect_state);
206 ret = tstream_unix_connect_recv(subreq, &sys_errno,
207 state, &state->unix_stream);
210 tevent_req_error(req, sys_errno);
214 subreq = tstream_writev_send(state,
217 &state->auth_req_iov, 1);
218 if (tevent_req_nomem(subreq, req)) {
221 tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
224 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
227 struct iovec **_vector,
229 static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
231 static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
233 struct tevent_req *req =
234 tevent_req_callback_data(subreq,
236 struct tstream_npa_connect_state *state =
238 struct tstream_npa_connect_state);
242 ret = tstream_writev_recv(subreq, &sys_errno);
245 tevent_req_error(req, sys_errno);
249 state->auth_rep_blob = data_blob_const(NULL, 0);
251 subreq = tstream_readv_pdu_send(state, state->caller.ev,
253 tstream_npa_connect_next_vector,
255 if (tevent_req_nomem(subreq, req)) {
258 tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
261 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
264 struct iovec **_vector,
267 struct tstream_npa_connect_state *state = talloc_get_type_abort(private_data,
268 struct tstream_npa_connect_state);
269 struct iovec *vector;
273 if (state->auth_rep_blob.length == 0) {
274 state->auth_rep_blob = data_blob_talloc(state, NULL, 4);
275 if (!state->auth_rep_blob.data) {
278 } else if (state->auth_rep_blob.length == 4) {
283 msg_len = RIVAL(state->auth_rep_blob.data, 0);
285 if (msg_len > 0x00FFFFFF) {
297 state->auth_rep_blob.data = talloc_realloc(state,
298 state->auth_rep_blob.data,
300 if (!state->auth_rep_blob.data) {
303 state->auth_rep_blob.length = msg_len;
310 /* we need to get a message header */
311 vector = talloc_array(mem_ctx, struct iovec, 1);
315 vector[0].iov_base = state->auth_rep_blob.data + ofs;
316 vector[0].iov_len = state->auth_rep_blob.length - ofs;
324 static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
326 struct tevent_req *req =
327 tevent_req_callback_data(subreq,
329 struct tstream_npa_connect_state *state =
331 struct tstream_npa_connect_state);
334 enum ndr_err_code ndr_err;
336 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
339 tevent_req_error(req, sys_errno);
343 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
344 (uint32_t)state->auth_rep_blob.length));
345 dump_data(11, state->auth_rep_blob.data, state->auth_rep_blob.length);
347 ndr_err = ndr_pull_struct_blob(
348 &state->auth_rep_blob, state,
350 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
352 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
353 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
354 ndr_map_error2string(ndr_err)));
355 tevent_req_error(req, EIO);
360 NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
363 if (state->auth_rep.length < 16) {
364 DEBUG(0, ("req invalid length: %u < 16\n",
365 state->auth_rep.length));
366 tevent_req_error(req, EIO);
370 if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
371 DEBUG(0, ("req invalid magic: %s != %s\n",
372 state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
373 tevent_req_error(req, EIO);
377 if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
378 DEBUG(0, ("req failed: %s\n",
379 nt_errstr(state->auth_rep.status)));
380 tevent_req_error(req, EACCES);
384 if (state->auth_rep.level != state->auth_req.level) {
385 DEBUG(0, ("req invalid level: %u != %u\n",
386 state->auth_rep.level, state->auth_req.level));
387 tevent_req_error(req, EIO);
391 tevent_req_done(req);
394 int _tstream_npa_connect_recv(struct tevent_req *req,
397 struct tstream_context **_stream,
398 uint16_t *_file_type,
399 uint16_t *_device_state,
400 uint64_t *_allocation_size,
401 const char *location)
403 struct tstream_npa_connect_state *state =
405 struct tstream_npa_connect_state);
406 struct tstream_context *stream;
407 struct tstream_npa *npas;
408 uint16_t device_state = 0;
409 uint64_t allocation_size = 0;
411 if (tevent_req_is_unix_error(req, perrno)) {
412 tevent_req_received(req);
416 stream = tstream_context_create(mem_ctx,
426 npas->unix_stream = talloc_move(stream, &state->unix_stream);
427 switch (state->auth_rep.level) {
430 npas->file_type = FILE_TYPE_BYTE_MODE_PIPE;
431 device_state = 0x00ff;
432 allocation_size = 2048;
435 npas->file_type = state->auth_rep.info.info2.file_type;
436 device_state = state->auth_rep.info.info2.device_state;
437 allocation_size = state->auth_rep.info.info2.allocation_size;
440 npas->file_type = state->auth_rep.info.info3.file_type;
441 device_state = state->auth_rep.info.info3.device_state;
442 allocation_size = state->auth_rep.info.info3.allocation_size;
447 *_file_type = npas->file_type;
448 *_device_state = device_state;
449 *_allocation_size = allocation_size;
450 tevent_req_received(req);
454 static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
456 struct tstream_npa *npas = tstream_context_data(stream,
460 if (!npas->unix_stream) {
465 switch (npas->file_type) {
466 case FILE_TYPE_BYTE_MODE_PIPE:
467 ret = tstream_pending_bytes(npas->unix_stream);
470 case FILE_TYPE_MESSAGE_MODE_PIPE:
471 ret = npas->pending.iov_len;
481 struct tstream_npa_readv_state {
482 struct tstream_context *stream;
484 struct iovec *vector;
487 /* the header for message mode */
494 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
495 static int tstream_npa_readv_next_vector(struct tstream_context *stream,
498 struct iovec **_vector,
500 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
502 static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
503 struct tevent_context *ev,
504 struct tstream_context *stream,
505 struct iovec *vector,
508 struct tevent_req *req;
509 struct tstream_npa_readv_state *state;
510 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
511 struct tevent_req *subreq;
516 req = tevent_req_create(mem_ctx, &state,
517 struct tstream_npa_readv_state);
522 state->stream = stream;
525 if (!npas->unix_stream) {
526 tevent_req_error(req, ENOTCONN);
530 switch (npas->file_type) {
531 case FILE_TYPE_BYTE_MODE_PIPE:
532 state->vector = vector;
533 state->count = count;
535 subreq = tstream_readv_send(state,
540 if (tevent_req_nomem(subreq,req)) {
543 tevent_req_set_callback(subreq,
544 tstream_npa_readv_byte_mode_handler,
549 case FILE_TYPE_MESSAGE_MODE_PIPE:
551 * we make a copy of the vector and prepend a header
554 state->vector = talloc_array(state, struct iovec, count);
555 if (tevent_req_nomem(state->vector, req)) {
558 memcpy(state->vector, vector, sizeof(struct iovec)*count);
559 state->count = count;
562 * copy the pending buffer first
565 left = npas->pending.iov_len;
566 pbase = (uint8_t *)npas->pending.iov_base;
568 while (left > 0 && state->count > 0) {
570 base = (uint8_t *)state->vector[0].iov_base;
571 if (left < state->vector[0].iov_len) {
572 memcpy(base, pbase + ofs, left);
575 state->vector[0].iov_base = base;
576 state->vector[0].iov_len -= left;
581 ZERO_STRUCT(npas->pending);
584 memcpy(base, pbase + ofs, state->vector[0].iov_len);
586 ofs += state->vector[0].iov_len;
587 left -= state->vector[0].iov_len;
593 ZERO_STRUCT(npas->pending);
599 memmove(pbase, pbase + ofs, left);
600 npas->pending.iov_base = pbase;
601 npas->pending.iov_len = left;
603 * this cannot fail and even if it
604 * fails we can handle it
606 pbase = talloc_realloc(npas, pbase, uint8_t, left);
608 npas->pending.iov_base = pbase;
615 if (state->count == 0) {
616 tevent_req_done(req);
620 ZERO_STRUCT(state->hdr);
621 state->wait_for_hdr = false;
623 subreq = tstream_readv_pdu_send(state,
626 tstream_npa_readv_next_vector,
628 if (tevent_req_nomem(subreq, req)) {
631 tevent_req_set_callback(subreq,
632 tstream_npa_readv_msg_mode_handler,
638 /* this can't happen */
639 tevent_req_error(req, EINVAL);
643 tevent_req_post(req, ev);
647 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
649 struct tevent_req *req = tevent_req_callback_data(subreq,
651 struct tstream_npa_readv_state *state = tevent_req_data(req,
652 struct tstream_npa_readv_state);
656 ret = tstream_readv_recv(subreq, &sys_errno);
659 tevent_req_error(req, sys_errno);
665 tevent_req_done(req);
668 static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
671 struct iovec **_vector,
674 struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
675 struct tstream_npa_readv_state);
676 struct tstream_npa *npas = tstream_context_data(state->stream,
678 struct iovec *vector;
683 if (state->count == 0) {
689 if (!state->wait_for_hdr) {
690 /* we need to get a message header */
691 vector = talloc_array(mem_ctx, struct iovec, 1);
695 ZERO_STRUCT(state->hdr);
696 vector[0].iov_base = state->hdr;
697 vector[0].iov_len = sizeof(state->hdr);
701 state->wait_for_hdr = true;
708 /* and now fill the callers buffers and maybe the pending buffer */
709 state->wait_for_hdr = false;
711 msg_len = SVAL(state->hdr, 0);
718 state->wait_for_hdr = false;
720 /* +1 because we may need to fill the pending buffer */
721 vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
728 while (left > 0 && state->count > 0) {
729 if (left < state->vector[0].iov_len) {
731 base = (uint8_t *)state->vector[0].iov_base;
732 vector[count].iov_base = base;
733 vector[count].iov_len = left;
736 state->vector[0].iov_base = base;
737 state->vector[0].iov_len -= left;
740 vector[count] = state->vector[0];
742 left -= state->vector[0].iov_len;
749 * if the message is longer than the buffers the caller
750 * requested, we need to consume the rest of the message
751 * into the pending buffer, where the next readv can
754 npas->pending.iov_base = talloc_array(npas, uint8_t, left);
755 if (!npas->pending.iov_base) {
758 npas->pending.iov_len = left;
760 vector[count] = npas->pending;
764 state->ret += (msg_len - left);
771 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
773 struct tevent_req *req = tevent_req_callback_data(subreq,
778 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
781 tevent_req_error(req, sys_errno);
786 * we do not set state->ret here as ret includes the headr size.
787 * we set it in tstream_npa_readv_pdu_next_vector()
790 tevent_req_done(req);
793 static int tstream_npa_readv_recv(struct tevent_req *req,
796 struct tstream_npa_readv_state *state = tevent_req_data(req,
797 struct tstream_npa_readv_state);
800 ret = tsocket_simple_int_recv(req, perrno);
805 tevent_req_received(req);
809 struct tstream_npa_writev_state {
810 const struct iovec *vector;
813 /* the header for message mode */
820 static void tstream_npa_writev_handler(struct tevent_req *subreq);
822 static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
823 struct tevent_context *ev,
824 struct tstream_context *stream,
825 const struct iovec *vector,
828 struct tevent_req *req;
829 struct tstream_npa_writev_state *state;
830 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
831 struct tevent_req *subreq;
834 struct iovec *new_vector;
836 req = tevent_req_create(mem_ctx, &state,
837 struct tstream_npa_writev_state);
844 if (!npas->unix_stream) {
845 tevent_req_error(req, ENOTCONN);
849 switch (npas->file_type) {
850 case FILE_TYPE_BYTE_MODE_PIPE:
851 state->hdr_used = false;
852 state->vector = vector;
853 state->count = count;
856 case FILE_TYPE_MESSAGE_MODE_PIPE:
858 * we make a copy of the vector and prepend a header
861 new_vector = talloc_array(state, struct iovec, count + 1);
862 if (tevent_req_nomem(new_vector, req)) {
865 new_vector[0].iov_base = state->hdr;
866 new_vector[0].iov_len = sizeof(state->hdr);
867 memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
869 state->hdr_used = true;
870 state->vector = new_vector;
871 state->count = count + 1;
874 for (i=0; i < count; i++) {
875 msg_len += vector[i].iov_len;
878 if (msg_len > UINT16_MAX) {
879 tevent_req_error(req, EMSGSIZE);
883 SSVAL(state->hdr, 0, msg_len);
887 subreq = tstream_writev_send(state,
892 if (tevent_req_nomem(subreq, req)) {
895 tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
900 tevent_req_post(req, ev);
904 static void tstream_npa_writev_handler(struct tevent_req *subreq)
906 struct tevent_req *req = tevent_req_callback_data(subreq,
908 struct tstream_npa_writev_state *state = tevent_req_data(req,
909 struct tstream_npa_writev_state);
913 ret = tstream_writev_recv(subreq, &sys_errno);
916 tevent_req_error(req, sys_errno);
921 * in message mode we need to hide the length
922 * of the hdr from the caller
924 if (state->hdr_used) {
925 ret -= sizeof(state->hdr);
930 tevent_req_done(req);
933 static int tstream_npa_writev_recv(struct tevent_req *req,
936 struct tstream_npa_writev_state *state = tevent_req_data(req,
937 struct tstream_npa_writev_state);
940 ret = tsocket_simple_int_recv(req, perrno);
945 tevent_req_received(req);
949 struct tstream_npa_disconnect_state {
950 struct tstream_context *stream;
953 static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
955 static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
956 struct tevent_context *ev,
957 struct tstream_context *stream)
959 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
960 struct tevent_req *req;
961 struct tstream_npa_disconnect_state *state;
962 struct tevent_req *subreq;
964 req = tevent_req_create(mem_ctx, &state,
965 struct tstream_npa_disconnect_state);
970 state->stream = stream;
972 if (!npas->unix_stream) {
973 tevent_req_error(req, ENOTCONN);
977 subreq = tstream_disconnect_send(state,
980 if (tevent_req_nomem(subreq, req)) {
983 tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
988 tevent_req_post(req, ev);
992 static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
994 struct tevent_req *req = tevent_req_callback_data(subreq,
996 struct tstream_npa_disconnect_state *state = tevent_req_data(req,
997 struct tstream_npa_disconnect_state);
998 struct tstream_context *stream = state->stream;
999 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
1003 ret = tstream_disconnect_recv(subreq, &sys_errno);
1004 TALLOC_FREE(subreq);
1006 tevent_req_error(req, sys_errno);
1010 TALLOC_FREE(npas->unix_stream);
1012 tevent_req_done(req);
1015 static int tstream_npa_disconnect_recv(struct tevent_req *req,
1020 ret = tsocket_simple_int_recv(req, perrno);
1022 tevent_req_received(req);
1026 static const struct tstream_context_ops tstream_npa_ops = {
1029 .pending_bytes = tstream_npa_pending_bytes,
1031 .readv_send = tstream_npa_readv_send,
1032 .readv_recv = tstream_npa_readv_recv,
1034 .writev_send = tstream_npa_writev_send,
1035 .writev_recv = tstream_npa_writev_recv,
1037 .disconnect_send = tstream_npa_disconnect_send,
1038 .disconnect_recv = tstream_npa_disconnect_recv,
1041 int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
1044 struct tstream_context **_stream,
1045 const char *location)
1047 struct tstream_context *stream;
1048 struct tstream_npa *npas;
1051 switch (file_type) {
1052 case FILE_TYPE_BYTE_MODE_PIPE:
1054 case FILE_TYPE_MESSAGE_MODE_PIPE:
1061 stream = tstream_context_create(mem_ctx,
1071 npas->file_type = file_type;
1073 ret = tstream_bsd_existing_socket(stream, fd,
1074 &npas->unix_stream);
1076 int saved_errno = errno;
1077 talloc_free(stream);
1078 errno = saved_errno;
1087 struct tstream_npa_accept_state {
1088 struct tevent_context *ev;
1089 struct tstream_context *plain;
1091 uint16_t device_state;
1092 uint64_t alloc_size;
1095 struct iovec out_iov;
1098 NTSTATUS accept_status;
1099 struct tsocket_address *client;
1101 struct tsocket_address *server;
1103 struct netr_SamInfo3 *info3;
1104 DATA_BLOB session_key;
1105 DATA_BLOB delegated_creds;
1108 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1110 TALLOC_CTX *mem_ctx,
1111 struct iovec **_vector,
1113 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq);
1114 static void tstream_npa_accept_existing_done(struct tevent_req *subreq);
1116 struct tevent_req *tstream_npa_accept_existing_send(TALLOC_CTX *mem_ctx,
1117 struct tevent_context *ev,
1118 struct tstream_context *plain,
1120 uint16_t device_state,
1121 uint64_t allocation_size)
1123 struct tstream_npa_accept_state *state;
1124 struct tevent_req *req, *subreq;
1126 req = tevent_req_create(mem_ctx, &state,
1127 struct tstream_npa_accept_state);
1132 switch (file_type) {
1133 case FILE_TYPE_BYTE_MODE_PIPE:
1135 case FILE_TYPE_MESSAGE_MODE_PIPE:
1138 tevent_req_error(req, EINVAL);
1142 ZERO_STRUCTP(state);
1145 state->plain = plain;
1146 state->file_type = file_type;
1147 state->device_state = device_state;
1148 state->alloc_size = allocation_size;
1151 * The named pipe pdu's have the length as 8 byte (initial_read_size),
1152 * named_pipe_full_request provides the pdu length then.
1154 subreq = tstream_readv_pdu_send(state, ev, plain,
1155 tstream_npa_accept_next_vector,
1157 if (tevent_req_nomem(subreq, req)) {
1161 tevent_req_set_callback(subreq,
1162 tstream_npa_accept_existing_reply, req);
1167 tevent_req_post(req, ev);
1171 static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
1173 TALLOC_CTX *mem_ctx,
1174 struct iovec **_vector,
1177 struct tstream_npa_accept_state *state =
1178 talloc_get_type_abort(private_data,
1179 struct tstream_npa_accept_state);
1180 struct iovec *vector;
1184 if (state->npa_blob.length == 0) {
1185 state->npa_blob = data_blob_talloc(state, NULL, 4);
1186 if (!state->npa_blob.data) {
1189 } else if (state->npa_blob.length == 4) {
1194 msg_len = RIVAL(state->npa_blob.data, 0);
1196 if (msg_len > 0x00FFFFFF) {
1208 state->npa_blob.data = talloc_realloc(state,
1209 state->npa_blob.data,
1211 if (!state->npa_blob.data) {
1214 state->npa_blob.length = msg_len;
1216 if (memcmp(&state->npa_blob.data[4],
1217 NAMED_PIPE_AUTH_MAGIC, 4) != 0) {
1218 DEBUG(0, ("Wrong protocol\n"));
1219 #if defined(EPROTONOSUPPORT)
1220 errno = EPROTONOSUPPORT;
1221 #elif defined(EPROTO)
1233 /* we need to get a message header */
1234 vector = talloc_array(mem_ctx, struct iovec, 1);
1238 vector[0].iov_base = state->npa_blob.data + ofs;
1239 vector[0].iov_len = state->npa_blob.length - ofs;
1247 static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
1249 struct tevent_req *req =
1250 tevent_req_callback_data(subreq, struct tevent_req);
1251 struct tstream_npa_accept_state *state =
1252 tevent_req_data(req, struct tstream_npa_accept_state);
1253 struct named_pipe_auth_req *pipe_request;
1254 struct named_pipe_auth_rep pipe_reply;
1255 struct named_pipe_auth_req_info3 i3;
1256 enum ndr_err_code ndr_err;
1261 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
1262 TALLOC_FREE(subreq);
1264 tevent_req_error(req, sys_errno);
1268 DEBUG(10, ("Received packet of length %lu\n",
1269 (long)state->npa_blob.length));
1270 dump_data(11, state->npa_blob.data, state->npa_blob.length);
1272 ZERO_STRUCT(pipe_reply);
1273 pipe_reply.level = 0;
1274 pipe_reply.status = NT_STATUS_INTERNAL_ERROR;
1276 * TODO: check it's a root (uid == 0) pipe
1279 pipe_request = talloc(state, struct named_pipe_auth_req);
1280 if (!pipe_request) {
1281 DEBUG(0, ("Out of memory!\n"));
1285 /* parse the passed credentials */
1286 ndr_err = ndr_pull_struct_blob_all(
1287 &state->npa_blob, pipe_request, pipe_request,
1288 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_req);
1289 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1290 pipe_reply.status = ndr_map_error2ntstatus(ndr_err);
1291 DEBUG(2, ("Could not unmarshall named_pipe_auth_req: %s\n",
1292 nt_errstr(pipe_reply.status)));
1297 NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
1302 switch (pipe_request->level) {
1304 pipe_reply.level = 0;
1305 pipe_reply.status = NT_STATUS_OK;
1307 /* we need to force byte mode in this level */
1308 state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
1312 pipe_reply.level = 1;
1313 pipe_reply.status = NT_STATUS_OK;
1315 /* We must copy net3_SamInfo3, so that
1316 * info3 is an actual talloc pointer, then we steal
1317 * pipe_request on info3 so that all the allocated memory
1318 * pointed by the structrue members is preserved */
1319 state->info3 = (struct netr_SamInfo3 *)talloc_memdup(state,
1320 &pipe_request->info.info1,
1321 sizeof(struct netr_SamInfo3));
1322 if (!state->info3) {
1323 pipe_reply.status = NT_STATUS_NO_MEMORY;
1324 DEBUG(0, ("Out of memory!\n"));
1327 talloc_steal(state->info3, pipe_request);
1329 /* we need to force byte mode in this level */
1330 state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
1334 pipe_reply.level = 2;
1335 pipe_reply.status = NT_STATUS_OK;
1336 pipe_reply.info.info2.file_type = state->file_type;
1337 pipe_reply.info.info2.device_state = state->device_state;
1338 pipe_reply.info.info2.allocation_size = state->alloc_size;
1340 i3.client_name = pipe_request->info.info2.client_name;
1341 i3.client_addr = pipe_request->info.info2.client_addr;
1342 i3.client_port = pipe_request->info.info2.client_port;
1343 i3.server_name = pipe_request->info.info2.server_name;
1344 i3.server_addr = pipe_request->info.info2.server_addr;
1345 i3.server_port = pipe_request->info.info2.server_port;
1346 i3.sam_info3 = pipe_request->info.info2.sam_info3;
1347 i3.session_key_length =
1348 pipe_request->info.info2.session_key_length;
1349 i3.session_key = pipe_request->info.info2.session_key;
1353 pipe_reply.level = 3;
1354 pipe_reply.status = NT_STATUS_OK;
1355 pipe_reply.info.info3.file_type = state->file_type;
1356 pipe_reply.info.info3.device_state = state->device_state;
1357 pipe_reply.info.info3.allocation_size = state->alloc_size;
1359 i3 = pipe_request->info.info3;
1363 DEBUG(0, ("Unknown level %u\n", pipe_request->level));
1364 pipe_reply.level = 0;
1365 pipe_reply.status = NT_STATUS_INVALID_LEVEL;
1369 if (pipe_reply.level >=2) {
1371 if (i3.server_addr == NULL) {
1372 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1373 DEBUG(2, ("Missing server address\n"));
1376 if (i3.client_addr == NULL) {
1377 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1378 DEBUG(2, ("Missing client address\n"));
1382 state->server_name = discard_const_p(char,
1383 talloc_move(state, &i3.server_name));
1384 ret = tsocket_address_inet_from_strings(state, "ip",
1389 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1390 i3.server_addr, i3.server_port,
1392 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1396 state->client_name = discard_const_p(char,
1397 talloc_move(state, &i3.client_name));
1398 ret = tsocket_address_inet_from_strings(state, "ip",
1403 DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
1404 i3.client_addr, i3.client_port,
1406 pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
1410 state->info3 = talloc_move(state, &i3.sam_info3);
1411 state->session_key.data = talloc_move(state, &i3.session_key);
1412 state->session_key.length = i3.session_key_length;
1415 if (pipe_reply.level >= 3) {
1416 state->delegated_creds.data =
1417 talloc_move(state, &i3.gssapi_delegated_creds);
1418 state->delegated_creds.length =
1419 i3.gssapi_delegated_creds_length;
1423 /* create the output */
1424 ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
1425 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_rep);
1426 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1427 DEBUG(2, ("Error encoding structure: %s",
1428 ndr_map_error2string(ndr_err)));
1429 tevent_req_error(req, EIO);
1433 DEBUG(10, ("named_pipe_auth reply[%u]\n", (unsigned)out.length));
1434 dump_data(11, out.data, out.length);
1437 NDR_PRINT_DEBUG(named_pipe_auth_rep, &pipe_reply);
1440 state->accept_status = pipe_reply.status;
1442 state->out_iov.iov_base = out.data;
1443 state->out_iov.iov_len = out.length;
1445 subreq = tstream_writev_send(state, state->ev,
1447 &state->out_iov, 1);
1448 if (tevent_req_nomem(subreq, req)) {
1449 DEBUG(0, ("no memory for tstream_writev_send"));
1453 tevent_req_set_callback(subreq, tstream_npa_accept_existing_done, req);
1456 static void tstream_npa_accept_existing_done(struct tevent_req *subreq)
1458 struct tevent_req *req =
1459 tevent_req_callback_data(subreq, struct tevent_req);
1463 ret = tstream_writev_recv(subreq, &sys_errno);
1464 TALLOC_FREE(subreq);
1466 tevent_req_error(req, sys_errno);
1470 tevent_req_done(req);
1473 int _tstream_npa_accept_existing_recv(struct tevent_req *req,
1475 TALLOC_CTX *mem_ctx,
1476 struct tstream_context **stream,
1477 struct tsocket_address **client,
1478 char **_client_name,
1479 struct tsocket_address **server,
1481 struct netr_SamInfo3 **info3,
1482 DATA_BLOB *session_key,
1483 DATA_BLOB *delegated_creds,
1484 const char *location)
1486 struct tstream_npa_accept_state *state =
1487 tevent_req_data(req, struct tstream_npa_accept_state);
1488 struct tstream_npa *npas;
1491 ret = tsocket_simple_int_recv(req, perrno);
1493 DEBUG(2, ("Failed to accept named pipe conection: %s\n",
1494 strerror(*perrno)));
1495 tevent_req_received(req);
1499 if (!NT_STATUS_IS_OK(state->accept_status)) {
1500 #if defined(EPROTONOSUPPORT)
1501 *perrno = EPROTONOSUPPORT;
1502 #elif defined(EPROTO)
1507 DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
1508 nt_errstr(state->accept_status),
1509 strerror(*perrno)));
1510 tevent_req_received(req);
1514 *stream = tstream_context_create(mem_ctx,
1521 tevent_req_received(req);
1525 npas->unix_stream = state->plain;
1526 npas->file_type = state->file_type;
1528 *client = talloc_move(mem_ctx, &state->client);
1529 *_client_name = talloc_move(mem_ctx, &state->client_name);
1530 *server = talloc_move(mem_ctx, &state->server);
1531 *server_name = talloc_move(mem_ctx, &state->server_name);
1532 *info3 = talloc_move(mem_ctx, &state->info3);
1533 *session_key = state->session_key;
1534 talloc_steal(mem_ctx, state->session_key.data);
1535 *delegated_creds = state->delegated_creds;
1536 talloc_steal(mem_ctx, state->delegated_creds.data);
1538 tevent_req_received(req);