#include "rpc_server/srv_pipe_hnd.h"
#include "rpc_server/srv_pipe.h"
-#define SERVER_TCP_LOW_PORT 1024
-#define SERVER_TCP_HIGH_PORT 1300
-
-static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx,
- struct auth_session_info **session_info)
-{
- NTSTATUS status;
-
- status = make_session_info_guest(mem_ctx, session_info);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- return NT_STATUS_OK;
-}
-
/* Creates a pipes_struct and initializes it with the information
* sent from the client */
-static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
- struct messaging_context *msg_ctx,
- const char *pipe_name,
- enum dcerpc_transport_t transport,
- bool ncalrpc_as_system,
- const struct tsocket_address *local_address,
- const struct tsocket_address *remote_address,
- struct auth_session_info *session_info,
- struct pipes_struct **_p,
- int *perrno)
+int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
+ struct messaging_context *msg_ctx,
+ const char *pipe_name,
+ enum dcerpc_transport_t transport,
+ const struct tsocket_address *remote_address,
+ const struct tsocket_address *local_address,
+ struct auth_session_info *session_info,
+ struct pipes_struct **_p,
+ int *perrno)
{
struct pipes_struct *p;
int ret;
ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
transport, RPC_LITTLE_ENDIAN,
- ncalrpc_as_system,
remote_address, local_address, &p);
if (ret) {
*perrno = ret;
* lp_ncalrpc_dir()/np should have 0700, we need to
* create lp_ncalrpc_dir() first.
*/
- if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) {
+ if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
DEBUG(0, ("Failed to create pipe directory %s - %s\n",
lp_ncalrpc_dir(), strerror(errno)));
goto out;
goto out;
}
- if (!directory_create_or_exist(np_dir, geteuid(), 0700)) {
+ if (!directory_create_or_exist_strict(np_dir, geteuid(), 0700)) {
DEBUG(0, ("Failed to create pipe directory %s - %s\n",
np_dir, strerror(errno)));
goto out;
goto out;
}
- DEBUG(10, ("Openened pipe socket fd %d for %s\n", fd, pipe_name));
+ DEBUG(10, ("Opened pipe socket fd %d for %s\n", fd, pipe_name));
out:
talloc_free(np_dir);
state->ev_ctx = ev_ctx;
state->msg_ctx = msg_ctx;
- DEBUG(10, ("Openened pipe socket fd %d for %s\n",
+ DEBUG(10, ("Opened pipe socket fd %d for %s\n",
state->fd, pipe_name));
fde = tevent_add_fd(ev_ctx,
}
return;
}
+ smb_set_close_on_exec(sd);
DEBUG(6, ("Accepted socket %d\n", sd));
* Accepts connections from clients and process requests using the appropriate
* dispatcher table. */
-struct named_pipe_client {
- const char *pipe_name;
-
- struct tevent_context *ev;
- struct messaging_context *msg_ctx;
-
- uint16_t file_type;
- uint16_t device_state;
- uint64_t allocation_size;
-
- struct tstream_context *tstream;
-
- struct tsocket_address *client;
- char *client_name;
- struct tsocket_address *server;
- char *server_name;
-
- struct auth_session_info *session_info;
-
- struct pipes_struct *p;
-
- struct tevent_queue *write_queue;
-
- struct iovec *iov;
- size_t count;
-
- named_pipe_termination_fn *term_fn;
- void *private_data;
-};
-
static int named_pipe_destructor(struct named_pipe_client *npc)
{
if (npc->term_fn) {
return 0;
}
+struct named_pipe_client *named_pipe_client_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev_ctx,
+ struct messaging_context *msg_ctx,
+ const char *pipe_name,
+ named_pipe_termination_fn *term_fn,
+ uint16_t file_type,
+ uint16_t device_state,
+ uint64_t allocation_size,
+ void *private_data)
+{
+ struct named_pipe_client *npc;
+
+ npc = talloc_zero(mem_ctx, struct named_pipe_client);
+ if (npc == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ return NULL;
+ }
+ talloc_set_destructor(npc, named_pipe_destructor);
+
+ npc->pipe_name = talloc_strdup(npc, pipe_name);
+ if (npc->pipe_name == NULL) {
+ DEBUG(0, ("Out of memory!\n"));
+ talloc_free(npc);
+ return NULL;
+ }
+
+ npc->ev = ev_ctx;
+ npc->msg_ctx = msg_ctx;
+ npc->term_fn = term_fn;
+ npc->private_data = private_data;
+
+ npc->file_type = file_type;
+ npc->device_state = device_state;
+ npc->allocation_size = allocation_size;
+
+ return npc;
+}
+
static void named_pipe_accept_done(struct tevent_req *subreq);
void named_pipe_accept_function(struct tevent_context *ev_ctx,
tevent_req_set_callback(subreq, named_pipe_accept_done, npc);
}
-static void named_pipe_packet_process(struct tevent_req *subreq);
static void named_pipe_packet_done(struct tevent_req *subreq);
static void named_pipe_accept_done(struct tevent_req *subreq)
ret = tstream_npa_accept_existing_recv(subreq, &error, npc,
&npc->tstream,
- &npc->client,
- &npc->client_name,
- &npc->server,
- &npc->server_name,
+ &npc->remote_client_addr,
+ &npc->remote_client_name,
+ &npc->local_server_addr,
+ &npc->local_server_name,
&session_info_transport);
npc->session_info = talloc_move(npc, &session_info_transport->session_info);
ret = make_server_pipes_struct(npc,
npc->msg_ctx,
npc->pipe_name, NCACN_NP,
- false, npc->server, npc->client, npc->session_info,
- &npc->p, &error);
+ npc->remote_client_addr,
+ npc->local_server_addr,
+ npc->session_info,
+ &npc->p, &error);
if (ret != 0) {
DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
strerror(error)));
fail:
DEBUG(2, ("Fatal error. Terminating client(%s) connection!\n",
- npc->client_name));
+ npc->remote_client_name));
/* terminate client connection */
talloc_free(npc);
return;
}
-static void named_pipe_packet_process(struct tevent_req *subreq)
+void named_pipe_packet_process(struct tevent_req *subreq)
{
struct named_pipe_client *npc =
tevent_req_callback_data(subreq, struct named_pipe_client);
DATA_BLOB recv_buffer = data_blob_null;
struct ncacn_packet *pkt;
NTSTATUS status;
- ssize_t data_left;
- ssize_t data_used;
- char *data;
uint32_t to_send;
size_t i;
bool ok;
goto fail;
}
- data_left = recv_buffer.length;
- data = (char *)recv_buffer.data;
-
- while (data_left) {
-
- data_used = process_incoming_data(npc->p, data, data_left);
- if (data_used < 0) {
- DEBUG(3, ("Failed to process dceprc request!\n"));
- status = NT_STATUS_UNEXPECTED_IO_ERROR;
- goto fail;
- }
-
- data_left -= data_used;
- data += data_used;
+ /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
+ npc->p->in_data.pdu_needed_len = 0;
+ npc->p->in_data.pdu = recv_buffer;
+ if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
+ npc->p->endian = RPC_LITTLE_ENDIAN;
+ } else {
+ npc->p->endian = RPC_BIG_ENDIAN;
}
+ DEBUG(10, ("PDU is in %s Endian format!\n",
+ npc->p->endian ? "Big" : "Little"));
+ process_complete_pdu(npc->p, pkt);
- /* Do not leak this buffer, npc is a long lived context */
+ /* reset pipe state and free PDU */
+ npc->p->in_data.pdu.length = 0;
talloc_free(recv_buffer.data);
talloc_free(pkt);
fail:
DEBUG(2, ("Fatal error(%s). "
"Terminating client(%s) connection!\n",
- nt_errstr(status), npc->client_name));
+ nt_errstr(status), npc->remote_client_name));
/* terminate client connection */
talloc_free(npc);
return;
return;
}
+ if (npc->p->fault_state != 0) {
+ DEBUG(2, ("Disconnect after fault\n"));
+ sys_errno = EINVAL;
+ goto fail;
+ }
+
/* clear out any data that may have been left around */
npc->count = 0;
TALLOC_FREE(npc->iov);
fail:
DEBUG(2, ("Fatal error(%s). "
"Terminating client(%s) connection!\n",
- strerror(sys_errno), npc->client_name));
+ strerror(sys_errno), npc->remote_client_name));
/* terminate client connection */
talloc_free(npc);
return;
if (*port == 0) {
uint16_t i;
- for (i = SERVER_TCP_LOW_PORT; i <= SERVER_TCP_HIGH_PORT; i++) {
+ for (i = lp_rpc_low_port(); i <= lp_rpc_high_port(); i++) {
fd = open_socket_in(SOCK_STREAM,
i,
0,
ifss,
false);
- if (fd > 0) {
+ if (fd >= 0) {
*port = i;
break;
}
goto out;
}
- DEBUG(10, ("setup_tcpip_socket: openened socket fd %d for port %u\n",
+ DEBUG(10, ("setup_tcpip_socket: opened socket fd %d for port %u\n",
state->fd, state->ep.port));
fde = tevent_add_fd(state->ev_ctx,
}
return;
}
+ smb_set_close_on_exec(s);
rc = tsocket_address_bsd_from_sockaddr(state,
(struct sockaddr *)(void *) &addr,
name = "DEFAULT";
}
- if (!directory_create_or_exist(lp_ncalrpc_dir(), geteuid(), 0755)) {
+ if (!directory_create_or_exist(lp_ncalrpc_dir(), 0755)) {
DEBUG(0, ("Failed to create ncalrpc directory %s - %s\n",
lp_ncalrpc_dir(), strerror(errno)));
return -1;
return -1;
}
- DEBUG(10, ("Openened ncalrpc socket fd %d for %s\n", fd, name));
+ DEBUG(10, ("Opened ncalrpc socket fd %d for %s\n", fd, name));
return fd;
}
struct dcerpc_ncacn_listen_state *state =
talloc_get_type_abort(private_data,
struct dcerpc_ncacn_listen_state);
- struct tsocket_address *cli_addr = NULL;
+ struct tsocket_address *cli_addr = NULL, *srv_addr = NULL;
struct sockaddr_un sunaddr;
struct sockaddr *addr = (struct sockaddr *)(void *)&sunaddr;
socklen_t len = sizeof(sunaddr);
+ struct sockaddr_un sunaddr_server;
+ struct sockaddr *addr_server = (struct sockaddr *)(void *)&sunaddr_server;
+ socklen_t len_server = sizeof(sunaddr_server);
int sd = -1;
int rc;
ZERO_STRUCT(sunaddr);
+ ZERO_STRUCT(sunaddr_server);
sd = accept(state->fd, addr, &len);
if (sd == -1) {
}
return;
}
+ smb_set_close_on_exec(sd);
rc = tsocket_address_bsd_from_sockaddr(state,
addr, len,
return;
}
- DEBUG(10, ("Accepted ncalrpc socket %d\n", sd));
+ rc = getsockname(sd, addr_server, &len_server);
+ if (rc < 0) {
+ close(sd);
+ return;
+ }
+
+ rc = tsocket_address_bsd_from_sockaddr(state,
+ addr_server,
+ len_server,
+ &srv_addr);
+ if (rc < 0) {
+ close(sd);
+ return;
+ }
+
+ DEBUG(10, ("Accepted ncalrpc socket %s (fd: %d)\n",
+ sunaddr.sun_path, sd));
dcerpc_ncacn_accept(state->ev_ctx,
state->msg_ctx,
NCALRPC,
state->ep.name,
- cli_addr, NULL, sd,
+ cli_addr, srv_addr, sd,
state->disconnect_fn);
}
struct tstream_context *tstream;
struct tevent_queue *send_queue;
- struct tsocket_address *client;
- char *client_name;
- struct tsocket_address *server;
- char *server_name;
+ struct tsocket_address *remote_client_addr;
+ char *remote_client_name;
+ struct tsocket_address *local_server_addr;
+ char *local_server_name;
struct auth_session_info *session_info;
struct iovec *iov;
dcerpc_ncacn_disconnect_fn fn) {
struct dcerpc_ncacn_conn *ncacn_conn;
struct tevent_req *subreq;
- bool system_user = false;
char *pipe_name;
NTSTATUS status;
int sys_errno;
ncacn_conn->sock = s;
ncacn_conn->disconnect_fn = fn;
- ncacn_conn->client = talloc_move(ncacn_conn, &cli_addr);
- if (tsocket_address_is_inet(ncacn_conn->client, "ip")) {
- ncacn_conn->client_name =
- tsocket_address_inet_addr_string(ncacn_conn->client,
+ ncacn_conn->remote_client_addr = talloc_move(ncacn_conn, &cli_addr);
+ if (tsocket_address_is_inet(ncacn_conn->remote_client_addr, "ip")) {
+ ncacn_conn->remote_client_name =
+ tsocket_address_inet_addr_string(ncacn_conn->remote_client_addr,
ncacn_conn);
} else {
- ncacn_conn->client_name =
- tsocket_address_unix_path(ncacn_conn->client,
+ ncacn_conn->remote_client_name =
+ tsocket_address_unix_path(ncacn_conn->remote_client_addr,
ncacn_conn);
}
- if (ncacn_conn->client_name == NULL) {
- DEBUG(0, ("Out of memory!\n"));
+ if (ncacn_conn->remote_client_name == NULL) {
+ DEBUG(0, ("Out of memory obtaining remote socket address as a string!\n"));
talloc_free(ncacn_conn);
close(s);
return;
}
if (srv_addr != NULL) {
- ncacn_conn->server = talloc_move(ncacn_conn, &srv_addr);
-
- ncacn_conn->server_name =
- tsocket_address_inet_addr_string(ncacn_conn->server,
- ncacn_conn);
- if (ncacn_conn->server_name == NULL) {
- DEBUG(0, ("Out of memory!\n"));
+ ncacn_conn->local_server_addr = talloc_move(ncacn_conn, &srv_addr);
+
+ if (tsocket_address_is_inet(ncacn_conn->local_server_addr, "ip")) {
+ ncacn_conn->local_server_name =
+ tsocket_address_inet_addr_string(ncacn_conn->local_server_addr,
+ ncacn_conn);
+ } else {
+ ncacn_conn->local_server_name =
+ tsocket_address_unix_path(ncacn_conn->local_server_addr,
+ ncacn_conn);
+ }
+ if (ncacn_conn->local_server_name == NULL) {
+ DEBUG(0, ("Out of memory obtaining local socket address as a string!\n"));
talloc_free(ncacn_conn);
close(s);
return;
switch (transport) {
case NCACN_IP_TCP:
- pipe_name = tsocket_address_string(ncacn_conn->client,
+ pipe_name = tsocket_address_string(ncacn_conn->remote_client_addr,
ncacn_conn);
if (pipe_name == NULL) {
close(s);
"uid - %s!\n", strerror(errno)));
} else {
if (uid == sec_initial_uid()) {
- system_user = true;
+ TALLOC_FREE(ncacn_conn->remote_client_addr);
+
+ rc = tsocket_address_unix_from_path(ncacn_conn,
+ AS_SYSTEM_MAGIC_PATH_TOKEN,
+ &ncacn_conn->remote_client_addr);
+ if (rc < 0) {
+ DEBUG(0, ("Out of memory building magic ncalrpc_as_system path!\n"));
+ talloc_free(ncacn_conn);
+ close(s);
+ return;
+ }
+
+ TALLOC_FREE(ncacn_conn->remote_client_name);
+ ncacn_conn->remote_client_name
+ = tsocket_address_unix_path(ncacn_conn->remote_client_addr,
+ ncacn_conn);
+ if (ncacn_conn->remote_client_name == NULL) {
+ DEBUG(0, ("Out of memory getting magic ncalrpc_as_system string!\n"));
+ talloc_free(ncacn_conn);
+ close(s);
+ return;
+ }
}
}
- /* FALL TROUGH */
+
+ FALL_THROUGH;
case NCACN_NP:
pipe_name = talloc_strdup(ncacn_conn,
name);
}
if (ncacn_conn->session_info == NULL) {
- status = auth_anonymous_session_info(ncacn_conn,
+ status = make_session_info_anonymous(ncacn_conn,
&ncacn_conn->session_info);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("Failed to create "
- "auth_anonymous_session_info - %s\n",
+ "make_session_info_anonymous - %s\n",
nt_errstr(status)));
talloc_free(ncacn_conn);
return;
ncacn_conn->msg_ctx,
pipe_name,
ncacn_conn->transport,
- system_user,
- ncacn_conn->server,
- ncacn_conn->client,
+ ncacn_conn->remote_client_addr,
+ ncacn_conn->local_server_addr,
ncacn_conn->session_info,
&ncacn_conn->p,
&sys_errno);
ncacn_conn->send_queue = tevent_queue_create(ncacn_conn,
"dcerpc send queue");
if (ncacn_conn->send_queue == NULL) {
- DEBUG(0, ("Out of memory!\n"));
+ DEBUG(0, ("Out of memory building dcerpc send queue!\n"));
talloc_free(ncacn_conn);
return;
}
struct _output_data *out = &ncacn_conn->p->out_data;
DATA_BLOB recv_buffer = data_blob_null;
struct ncacn_packet *pkt;
- ssize_t data_left;
- ssize_t data_used;
uint32_t to_send;
- char *data;
NTSTATUS status;
bool ok;
goto fail;
}
- data_left = recv_buffer.length;
- data = (char *) recv_buffer.data;
-
- while (data_left) {
- data_used = process_incoming_data(ncacn_conn->p, data, data_left);
- if (data_used < 0) {
- DEBUG(3, ("Failed to process dcerpc request!\n"));
- status = NT_STATUS_UNEXPECTED_IO_ERROR;
- goto fail;
- }
-
- data_left -= data_used;
- data += data_used;
+ /* dcerpc_read_ncacn_packet_recv() returns a full PDU */
+ ncacn_conn->p->in_data.pdu_needed_len = 0;
+ ncacn_conn->p->in_data.pdu = recv_buffer;
+ if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
+ ncacn_conn->p->endian = RPC_LITTLE_ENDIAN;
+ } else {
+ ncacn_conn->p->endian = RPC_BIG_ENDIAN;
}
+ DEBUG(10, ("PDU is in %s Endian format!\n",
+ ncacn_conn->p->endian ? "Big" : "Little"));
+ process_complete_pdu(ncacn_conn->p, pkt);
- /* Do not leak this buffer */
+ /* reset pipe state and free PDU */
+ ncacn_conn->p->in_data.pdu.length = 0;
talloc_free(recv_buffer.data);
talloc_free(pkt);
fail:
DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
- ncacn_conn->client_name, nt_errstr(status)));
+ ncacn_conn->remote_client_name, nt_errstr(status)));
/* Terminate client connection */
talloc_free(ncacn_conn);
goto fail;
}
+ if (ncacn_conn->p->fault_state != 0) {
+ DEBUG(2, ("Disconnect after fault\n"));
+ sys_errno = EINVAL;
+ goto fail;
+ }
+
/* clear out any data that may have been left around */
ncacn_conn->count = 0;
TALLOC_FREE(ncacn_conn->iov);
fail:
DEBUG(3, ("Terminating client(%s) connection! - '%s'\n",
- ncacn_conn->client_name, nt_errstr(status)));
+ ncacn_conn->remote_client_name, nt_errstr(status)));
/* Terminate client connection */
talloc_free(ncacn_conn);