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;
42 struct smb_iconv_convenience *smb_iconv_c;
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;
55 DATA_BLOB auth_rep_blob;
58 static void tstream_npa_connect_unix_done(struct tevent_req *subreq);
60 struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
61 struct tevent_context *ev,
62 struct smb_iconv_convenience *smb_iconv_c,
63 const char *directory,
65 const struct tsocket_address *client,
66 const char *client_name_in,
67 const struct tsocket_address *server,
68 const char *server_name,
69 const struct netr_SamInfo3 *info3,
70 DATA_BLOB session_key)
72 struct tevent_req *req;
73 struct tstream_npa_connect_state *state;
74 struct tevent_req *subreq;
76 enum ndr_err_code ndr_err;
78 req = tevent_req_create(mem_ctx, &state,
79 struct tstream_npa_connect_state);
84 state->caller.ev = ev;
85 state->caller.smb_iconv_c = smb_iconv_c;
87 state->unix_path = talloc_asprintf(state, "%s/%s",
90 if (tevent_req_nomem(state->unix_path, req)) {
94 ret = tsocket_address_unix_from_path(state,
98 tevent_req_error(req, errno);
102 ret = tsocket_address_unix_from_path(state,
106 tevent_req_error(req, errno);
110 ZERO_STRUCT(state->auth_req);
112 struct named_pipe_auth_req_info2 *info2;
115 tevent_req_error(req, EINVAL);
119 state->auth_req.level = 2;
120 info2 = &state->auth_req.info.info2;
122 info2->client_name = client_name_in;
123 info2->client_addr = tsocket_address_inet_addr_string(client, state);
124 if (!info2->client_addr) {
125 /* errno might be EINVAL */
126 tevent_req_error(req, errno);
129 info2->client_port = tsocket_address_inet_port(client);
130 if (!info2->client_name) {
131 info2->client_name = info2->client_addr;
134 info2->server_addr = tsocket_address_inet_addr_string(server, state);
135 if (!info2->server_addr) {
136 /* errno might be EINVAL */
137 tevent_req_error(req, errno);
140 info2->server_port = tsocket_address_inet_port(server);
141 if (!info2->server_name) {
142 info2->server_name = info2->server_addr;
145 info2->sam_info3 = discard_const_p(struct netr_SamInfo3, info3);
146 info2->session_key_length = session_key.length;
147 info2->session_key = session_key.data;
149 state->auth_req.level = 1;
150 state->auth_req.info.info1 = *info3;
152 state->auth_req.level = 0;
156 NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
159 ndr_err = ndr_push_struct_blob(&state->auth_req_blob,
160 state, smb_iconv_c, &state->auth_req,
161 (ndr_push_flags_fn_t)ndr_push_named_pipe_auth_req);
162 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
163 tevent_req_error(req, EINVAL);
167 state->auth_req_iov.iov_base = state->auth_req_blob.data;
168 state->auth_req_iov.iov_len = state->auth_req_blob.length;
170 subreq = tstream_unix_connect_send(state,
174 if (tevent_req_nomem(subreq, req)) {
177 tevent_req_set_callback(subreq, tstream_npa_connect_unix_done, req);
182 tevent_req_post(req, ev);
186 static void tstream_npa_connect_writev_done(struct tevent_req *subreq);
188 static void tstream_npa_connect_unix_done(struct tevent_req *subreq)
190 struct tevent_req *req =
191 tevent_req_callback_data(subreq,
193 struct tstream_npa_connect_state *state =
195 struct tstream_npa_connect_state);
199 ret = tstream_unix_connect_recv(subreq, &sys_errno,
200 state, &state->unix_stream);
203 tevent_req_error(req, sys_errno);
207 subreq = tstream_writev_send(state,
210 &state->auth_req_iov, 1);
211 if (tevent_req_nomem(subreq, req)) {
214 tevent_req_set_callback(subreq, tstream_npa_connect_writev_done, req);
217 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
220 struct iovec **_vector,
222 static void tstream_npa_connect_readv_done(struct tevent_req *subreq);
224 static void tstream_npa_connect_writev_done(struct tevent_req *subreq)
226 struct tevent_req *req =
227 tevent_req_callback_data(subreq,
229 struct tstream_npa_connect_state *state =
231 struct tstream_npa_connect_state);
235 ret = tstream_writev_recv(subreq, &sys_errno);
238 tevent_req_error(req, sys_errno);
242 state->auth_rep_blob = data_blob_const(NULL, 0);
244 subreq = tstream_readv_pdu_send(state, state->caller.ev,
246 tstream_npa_connect_next_vector,
248 if (tevent_req_nomem(subreq, req)) {
251 tevent_req_set_callback(subreq, tstream_npa_connect_readv_done, req);
254 static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
257 struct iovec **_vector,
260 struct tstream_npa_connect_state *state = talloc_get_type_abort(private_data,
261 struct tstream_npa_connect_state);
262 struct iovec *vector;
266 if (state->auth_rep_blob.length == 0) {
267 state->auth_rep_blob = data_blob_talloc(state, NULL, 4);
268 if (!state->auth_rep_blob.data) {
271 } else if (state->auth_rep_blob.length == 4) {
276 msg_len = RIVAL(state->auth_rep_blob.data, 0);
278 if (msg_len > 0x00FFFFFF) {
290 state->auth_rep_blob.data = talloc_realloc(state,
291 state->auth_rep_blob.data,
293 if (!state->auth_rep_blob.data) {
296 state->auth_rep_blob.length = msg_len;
303 /* we need to get a message header */
304 vector = talloc_array(mem_ctx, struct iovec, 1);
308 vector[0].iov_base = state->auth_rep_blob.data + ofs;
309 vector[0].iov_len = state->auth_rep_blob.length - ofs;
317 static void tstream_npa_connect_readv_done(struct tevent_req *subreq)
319 struct tevent_req *req =
320 tevent_req_callback_data(subreq,
322 struct tstream_npa_connect_state *state =
324 struct tstream_npa_connect_state);
327 enum ndr_err_code ndr_err;
329 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
332 tevent_req_error(req, sys_errno);
336 DEBUG(10,("name_pipe_auth_rep(client)[%u]\n",
337 (uint32_t)state->auth_rep_blob.length));
338 dump_data(11, state->auth_rep_blob.data, state->auth_rep_blob.length);
340 ndr_err = ndr_pull_struct_blob(
341 &state->auth_rep_blob, state,
342 state->caller.smb_iconv_c, &state->auth_rep,
343 (ndr_pull_flags_fn_t)ndr_pull_named_pipe_auth_rep);
345 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
346 DEBUG(0, ("ndr_pull_named_pipe_auth_rep failed: %s\n",
347 ndr_map_error2string(ndr_err)));
348 tevent_req_error(req, EIO);
353 NDR_PRINT_DEBUG(named_pipe_auth_rep, &state->auth_rep);
356 if (state->auth_rep.length < 16) {
357 DEBUG(0, ("req invalid length: %u < 16\n",
358 state->auth_rep.length));
359 tevent_req_error(req, EIO);
363 if (strcmp(NAMED_PIPE_AUTH_MAGIC, state->auth_rep.magic) != 0) {
364 DEBUG(0, ("req invalid magic: %s != %s\n",
365 state->auth_rep.magic, NAMED_PIPE_AUTH_MAGIC));
366 tevent_req_error(req, EIO);
370 if (!NT_STATUS_IS_OK(state->auth_rep.status)) {
371 DEBUG(0, ("req failed: %s\n",
372 nt_errstr(state->auth_rep.status)));
373 tevent_req_error(req, EACCES);
377 if (state->auth_rep.level != state->auth_req.level) {
378 DEBUG(0, ("req invalid level: %u != %u\n",
379 state->auth_rep.level, state->auth_req.level));
380 tevent_req_error(req, EIO);
384 tevent_req_done(req);
387 int _tstream_npa_connect_recv(struct tevent_req *req,
390 struct tstream_context **_stream,
391 uint16_t *_file_type,
392 uint16_t *_device_state,
393 uint64_t *_allocation_size,
394 const char *location)
396 struct tstream_npa_connect_state *state =
398 struct tstream_npa_connect_state);
399 struct tstream_context *stream;
400 struct tstream_npa *npas;
401 uint16_t device_state = 0;
402 uint64_t allocation_size = 0;
404 if (tevent_req_is_unix_error(req, perrno)) {
405 tevent_req_received(req);
409 stream = tstream_context_create(mem_ctx,
419 npas->unix_stream = talloc_move(stream, &state->unix_stream);
420 switch (state->auth_rep.level) {
423 npas->file_type = FILE_TYPE_BYTE_MODE_PIPE;
424 device_state = 0x00ff;
425 allocation_size = 2048;
428 npas->file_type = state->auth_rep.info.info2.file_type;
429 device_state = state->auth_rep.info.info2.device_state;
430 allocation_size = state->auth_rep.info.info2.allocation_size;
435 *_file_type = npas->file_type;
436 *_device_state = device_state;
437 *_allocation_size = allocation_size;
438 tevent_req_received(req);
442 static ssize_t tstream_npa_pending_bytes(struct tstream_context *stream)
444 struct tstream_npa *npas = tstream_context_data(stream,
448 if (!npas->unix_stream) {
453 switch (npas->file_type) {
454 case FILE_TYPE_BYTE_MODE_PIPE:
455 ret = tstream_pending_bytes(npas->unix_stream);
458 case FILE_TYPE_MESSAGE_MODE_PIPE:
459 ret = npas->pending.iov_len;
469 struct tstream_npa_readv_state {
470 struct tstream_context *stream;
472 struct iovec *vector;
475 /* the header for message mode */
482 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq);
483 static int tstream_npa_readv_next_vector(struct tstream_context *stream,
486 struct iovec **_vector,
488 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq);
490 static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
491 struct tevent_context *ev,
492 struct tstream_context *stream,
493 struct iovec *vector,
496 struct tevent_req *req;
497 struct tstream_npa_readv_state *state;
498 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
499 struct tevent_req *subreq;
504 req = tevent_req_create(mem_ctx, &state,
505 struct tstream_npa_readv_state);
510 state->stream = stream;
513 if (!npas->unix_stream) {
514 tevent_req_error(req, ENOTCONN);
518 switch (npas->file_type) {
519 case FILE_TYPE_BYTE_MODE_PIPE:
520 state->vector = vector;
521 state->count = count;
523 subreq = tstream_readv_send(state,
528 if (tevent_req_nomem(subreq,req)) {
531 tevent_req_set_callback(subreq,
532 tstream_npa_readv_byte_mode_handler,
537 case FILE_TYPE_MESSAGE_MODE_PIPE:
539 * we make a copy of the vector and prepend a header
542 state->vector = talloc_array(state, struct iovec, count);
543 if (tevent_req_nomem(state->vector, req)) {
546 memcpy(state->vector, vector, sizeof(struct iovec)*count);
547 state->count = count;
550 * copy the pending buffer first
553 left = npas->pending.iov_len;
554 pbase = (uint8_t *)npas->pending.iov_base;
556 while (left > 0 && state->count > 0) {
558 base = (uint8_t *)state->vector[0].iov_base;
559 if (left < state->vector[0].iov_len) {
560 memcpy(base, pbase + ofs, left);
563 state->vector[0].iov_base = base;
564 state->vector[0].iov_len -= left;
569 ZERO_STRUCT(npas->pending);
572 memcpy(base, pbase + ofs, state->vector[0].iov_len);
574 ofs += state->vector[0].iov_len;
575 left -= state->vector[0].iov_len;
581 ZERO_STRUCT(npas->pending);
587 memmove(pbase, pbase + ofs, left);
588 npas->pending.iov_base = pbase;
589 npas->pending.iov_len = left;
591 * this cannot fail and even if it
592 * fails we can handle it
594 pbase = talloc_realloc(npas, pbase, uint8_t, left);
596 npas->pending.iov_base = pbase;
603 if (state->count == 0) {
604 tevent_req_done(req);
608 ZERO_STRUCT(state->hdr);
609 state->wait_for_hdr = false;
611 subreq = tstream_readv_pdu_send(state,
614 tstream_npa_readv_next_vector,
616 if (tevent_req_nomem(subreq, req)) {
619 tevent_req_set_callback(subreq,
620 tstream_npa_readv_msg_mode_handler,
626 /* this can't happen */
627 tevent_req_error(req, EINVAL);
631 tevent_req_post(req, ev);
635 static void tstream_npa_readv_byte_mode_handler(struct tevent_req *subreq)
637 struct tevent_req *req = tevent_req_callback_data(subreq,
639 struct tstream_npa_readv_state *state = tevent_req_data(req,
640 struct tstream_npa_readv_state);
644 ret = tstream_readv_recv(subreq, &sys_errno);
647 tevent_req_error(req, sys_errno);
653 tevent_req_done(req);
656 static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
659 struct iovec **_vector,
662 struct tstream_npa_readv_state *state = talloc_get_type_abort(private_data,
663 struct tstream_npa_readv_state);
664 struct tstream_npa *npas = tstream_context_data(state->stream,
666 struct iovec *vector;
671 if (state->count == 0) {
677 if (!state->wait_for_hdr) {
678 /* we need to get a message header */
679 vector = talloc_array(mem_ctx, struct iovec, 1);
683 ZERO_STRUCT(state->hdr);
684 vector[0].iov_base = state->hdr;
685 vector[0].iov_len = sizeof(state->hdr);
689 state->wait_for_hdr = true;
696 /* and now fill the callers buffers and maybe the pending buffer */
697 state->wait_for_hdr = false;
699 msg_len = SVAL(state->hdr, 0);
706 state->wait_for_hdr = false;
708 /* +1 because we may need to fill the pending buffer */
709 vector = talloc_array(mem_ctx, struct iovec, state->count + 1);
716 while (left > 0 && state->count > 0) {
717 if (left < state->vector[0].iov_len) {
719 base = (uint8_t *)state->vector[0].iov_base;
720 vector[count].iov_base = base;
721 vector[count].iov_len = left;
724 state->vector[0].iov_base = base;
725 state->vector[0].iov_len -= left;
728 vector[count] = state->vector[0];
730 left -= state->vector[0].iov_len;
737 * if the message if longer than the buffers the caller
738 * requested, we need to consume the rest of the message
739 * into the pending buffer, where the next readv can
742 npas->pending.iov_base = talloc_array(npas, uint8_t, left);
743 if (!npas->pending.iov_base) {
746 npas->pending.iov_len = left;
748 vector[count] = npas->pending;
752 state->ret += (msg_len - left);
759 static void tstream_npa_readv_msg_mode_handler(struct tevent_req *subreq)
761 struct tevent_req *req = tevent_req_callback_data(subreq,
766 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
769 tevent_req_error(req, sys_errno);
774 * we do not set state->ret here as ret includes the headr size.
775 * we set it in tstream_npa_readv_pdu_next_vector()
778 tevent_req_done(req);
781 static int tstream_npa_readv_recv(struct tevent_req *req,
784 struct tstream_npa_readv_state *state = tevent_req_data(req,
785 struct tstream_npa_readv_state);
788 ret = tsocket_simple_int_recv(req, perrno);
793 tevent_req_received(req);
797 struct tstream_npa_writev_state {
798 const struct iovec *vector;
801 /* the header for message mode */
807 static void tstream_npa_writev_handler(struct tevent_req *subreq);
809 static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
810 struct tevent_context *ev,
811 struct tstream_context *stream,
812 const struct iovec *vector,
815 struct tevent_req *req;
816 struct tstream_npa_writev_state *state;
817 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
818 struct tevent_req *subreq;
821 struct iovec *new_vector;
823 req = tevent_req_create(mem_ctx, &state,
824 struct tstream_npa_writev_state);
831 if (!npas->unix_stream) {
832 tevent_req_error(req, ENOTCONN);
836 switch (npas->file_type) {
837 case FILE_TYPE_BYTE_MODE_PIPE:
838 state->vector = vector;
839 state->count = count;
842 case FILE_TYPE_MESSAGE_MODE_PIPE:
844 * we make a copy of the vector and prepend a header
847 new_vector = talloc_array(state, struct iovec, count + 1);
848 if (tevent_req_nomem(new_vector, req)) {
851 new_vector[0].iov_base = state->hdr;
852 new_vector[0].iov_len = sizeof(state->hdr);
853 memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
855 state->vector = new_vector;
856 state->count = count + 1;
859 for (i=0; i < count; i++) {
860 msg_len += vector[i].iov_len;
863 if (msg_len > UINT16_MAX) {
864 tevent_req_error(req, EMSGSIZE);
868 SSVAL(state->hdr, 0, msg_len);
872 subreq = tstream_writev_send(state,
877 if (tevent_req_nomem(subreq, req)) {
880 tevent_req_set_callback(subreq, tstream_npa_writev_handler, req);
885 tevent_req_post(req, ev);
889 static void tstream_npa_writev_handler(struct tevent_req *subreq)
891 struct tevent_req *req = tevent_req_callback_data(subreq,
893 struct tstream_npa_writev_state *state = tevent_req_data(req,
894 struct tstream_npa_writev_state);
898 ret = tstream_writev_recv(subreq, &sys_errno);
901 tevent_req_error(req, sys_errno);
907 tevent_req_done(req);
910 static int tstream_npa_writev_recv(struct tevent_req *req,
913 struct tstream_npa_writev_state *state = tevent_req_data(req,
914 struct tstream_npa_writev_state);
917 ret = tsocket_simple_int_recv(req, perrno);
922 tevent_req_received(req);
926 struct tstream_npa_disconnect_state {
927 struct tstream_context *stream;
930 static void tstream_npa_disconnect_handler(struct tevent_req *subreq);
932 static struct tevent_req *tstream_npa_disconnect_send(TALLOC_CTX *mem_ctx,
933 struct tevent_context *ev,
934 struct tstream_context *stream)
936 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
937 struct tevent_req *req;
938 struct tstream_npa_disconnect_state *state;
939 struct tevent_req *subreq;
941 req = tevent_req_create(mem_ctx, &state,
942 struct tstream_npa_disconnect_state);
947 state->stream = stream;
949 if (!npas->unix_stream) {
950 tevent_req_error(req, ENOTCONN);
954 subreq = tstream_disconnect_send(state,
957 if (tevent_req_nomem(subreq, req)) {
960 tevent_req_set_callback(subreq, tstream_npa_disconnect_handler, req);
965 tevent_req_post(req, ev);
969 static void tstream_npa_disconnect_handler(struct tevent_req *subreq)
971 struct tevent_req *req = tevent_req_callback_data(subreq,
973 struct tstream_npa_disconnect_state *state = tevent_req_data(req,
974 struct tstream_npa_disconnect_state);
975 struct tstream_context *stream = state->stream;
976 struct tstream_npa *npas = tstream_context_data(stream, struct tstream_npa);
980 ret = tstream_disconnect_recv(subreq, &sys_errno);
983 tevent_req_error(req, sys_errno);
987 TALLOC_FREE(npas->unix_stream);
989 tevent_req_done(req);
992 static int tstream_npa_disconnect_recv(struct tevent_req *req,
997 ret = tsocket_simple_int_recv(req, perrno);
999 tevent_req_received(req);
1003 static const struct tstream_context_ops tstream_npa_ops = {
1006 .pending_bytes = tstream_npa_pending_bytes,
1008 .readv_send = tstream_npa_readv_send,
1009 .readv_recv = tstream_npa_readv_recv,
1011 .writev_send = tstream_npa_writev_send,
1012 .writev_recv = tstream_npa_writev_recv,
1014 .disconnect_send = tstream_npa_disconnect_send,
1015 .disconnect_recv = tstream_npa_disconnect_recv,
1018 int _tstream_npa_existing_socket(TALLOC_CTX *mem_ctx,
1021 struct tstream_context **_stream,
1022 const char *location)
1024 struct tstream_context *stream;
1025 struct tstream_npa *npas;
1028 switch (file_type) {
1029 case FILE_TYPE_BYTE_MODE_PIPE:
1031 case FILE_TYPE_MESSAGE_MODE_PIPE:
1038 stream = tstream_context_create(mem_ctx,
1048 npas->file_type = file_type;
1050 ret = tstream_bsd_existing_socket(stream, fd,
1051 &npas->unix_stream);
1053 int saved_errno = errno;
1054 talloc_free(stream);
1055 errno = saved_errno;