1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-12 09:18:10 +03:00
samba-mirror/source4/smbd/service_named_pipe.c
Andrew Bartlett d66150c14d libcli/named_pipe_auth Change from 'info3' to auth_session_info_transport
This changes the structure being used to convey the current user state
from the netlogon-derived 'netr_SamInfo3' structure to a purpose-built
structure that matches the internals of the Samba auth subsystem and
contains the final group list, as well as the final privilege set and
session key.

These previously had to be re-created on the server side of the pipe
each time.

Andrew Bartlett

Signed-off-by: Andrew Tridgell <tridge@samba.org>
2011-02-10 06:51:06 +01:00

249 lines
6.4 KiB
C

/*
Unix SMB/CIFS implementation.
helper functions for NAMED PIPE servers
Copyright (C) Stefan (metze) Metzmacher 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include <tevent.h>
#include "smbd/service.h"
#include "param/param.h"
#include "auth/auth.h"
#include "auth/session.h"
#include "auth/auth_sam_reply.h"
#include "lib/socket/socket.h"
#include "lib/tsocket/tsocket.h"
#include "libcli/util/tstream.h"
#include "librpc/gen_ndr/ndr_named_pipe_auth.h"
#include "system/passwd.h"
#include "system/network.h"
#include "libcli/raw/smb.h"
#include "auth/session.h"
#include "libcli/security/security.h"
#include "libcli/named_pipe_auth/npa_tstream.h"
struct named_pipe_socket {
const char *pipe_name;
const char *pipe_path;
const struct stream_server_ops *ops;
void *private_data;
};
static void named_pipe_accept_done(struct tevent_req *subreq);
static void named_pipe_accept(struct stream_connection *conn)
{
struct tstream_context *plain_tstream;
int fd;
struct tevent_req *subreq;
int ret;
/* Let tstream take over fd operations */
fd = socket_get_fd(conn->socket);
socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);
TALLOC_FREE(conn->event.fde);
TALLOC_FREE(conn->socket);
ret = tstream_bsd_existing_socket(conn, fd, &plain_tstream);
if (ret != 0) {
stream_terminate_connection(conn,
"named_pipe_accept: out of memory");
return;
}
subreq = tstream_npa_accept_existing_send(conn, conn->event.ctx,
plain_tstream,
FILE_TYPE_MESSAGE_MODE_PIPE,
0xff | 0x0400 | 0x0100,
4096);
if (subreq == NULL) {
stream_terminate_connection(conn,
"named_pipe_accept: "
"no memory for tstream_npa_accept_existing_send");
return;
}
tevent_req_set_callback(subreq, named_pipe_accept_done, conn);
}
static void named_pipe_accept_done(struct tevent_req *subreq)
{
struct stream_connection *conn = tevent_req_callback_data(subreq,
struct stream_connection);
struct named_pipe_socket *pipe_sock =
talloc_get_type(conn->private_data,
struct named_pipe_socket);
struct tsocket_address *client;
char *client_name;
struct tsocket_address *server;
char *server_name;
struct auth_session_info_transport *session_info_transport;
const char *reason = NULL;
TALLOC_CTX *tmp_ctx;
int error;
int ret;
tmp_ctx = talloc_new(conn);
if (!tmp_ctx) {
reason = "Out of memory!\n";
goto out;
}
ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx,
&conn->tstream,
&client,
&client_name,
&server,
&server_name,
&session_info_transport);
TALLOC_FREE(subreq);
if (ret != 0) {
reason = talloc_asprintf(conn,
"tstream_npa_accept_existing_recv()"
" failed: %s", strerror(error));
goto out;
}
DEBUG(10, ("Accepted npa connection from %s. "
"Client: %s (%s). Server: %s (%s)\n",
tsocket_address_string(conn->remote_address, tmp_ctx),
client_name, tsocket_address_string(client, tmp_ctx),
server_name, tsocket_address_string(server, tmp_ctx)));
conn->session_info = auth_session_info_from_transport(conn, session_info_transport,
conn->lp_ctx,
&reason);
if (!conn->session_info) {
goto out;
}
/*
* hand over to the real pipe implementation,
* now that we have setup the transport session_info
*/
conn->ops = pipe_sock->ops;
conn->private_data = pipe_sock->private_data;
conn->ops->accept_connection(conn);
DEBUG(10, ("named pipe connection [%s] established\n",
conn->ops->name));
talloc_free(tmp_ctx);
return;
out:
talloc_free(tmp_ctx);
if (!reason) {
reason = "Internal error";
}
stream_terminate_connection(conn, reason);
}
/*
called when a pipe socket becomes readable
*/
static void named_pipe_recv(struct stream_connection *conn, uint16_t flags)
{
stream_terminate_connection(conn, "named_pipe_recv: called");
}
/*
called when a pipe socket becomes writable
*/
static void named_pipe_send(struct stream_connection *conn, uint16_t flags)
{
stream_terminate_connection(conn, "named_pipe_send: called");
}
static const struct stream_server_ops named_pipe_stream_ops = {
.name = "named_pipe",
.accept_connection = named_pipe_accept,
.recv_handler = named_pipe_recv,
.send_handler = named_pipe_send,
};
NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
struct tevent_context *event_context,
struct loadparm_context *lp_ctx,
const struct model_ops *model_ops,
const struct stream_server_ops *stream_ops,
const char *pipe_name,
void *private_data)
{
char *dirname;
struct named_pipe_socket *pipe_sock;
NTSTATUS status = NT_STATUS_NO_MEMORY;;
pipe_sock = talloc(mem_ctx, struct named_pipe_socket);
if (pipe_sock == NULL) {
goto fail;
}
/* remember the details about the pipe */
pipe_sock->pipe_name = talloc_strdup(pipe_sock, pipe_name);
if (pipe_sock->pipe_name == NULL) {
goto fail;
}
dirname = talloc_asprintf(pipe_sock, "%s/np", lpcfg_ncalrpc_dir(lp_ctx));
if (dirname == NULL) {
goto fail;
}
if (!directory_create_or_exist(dirname, geteuid(), 0700)) {
status = map_nt_error_from_unix(errno);
DEBUG(0,(__location__ ": Failed to create stream pipe directory %s - %s\n",
dirname, nt_errstr(status)));
goto fail;
}
if (strncmp(pipe_name, "\\pipe\\", 6) == 0) {
pipe_name += 6;
}
pipe_sock->pipe_path = talloc_asprintf(pipe_sock, "%s/%s", dirname,
pipe_name);
if (pipe_sock->pipe_path == NULL) {
goto fail;
}
talloc_free(dirname);
pipe_sock->ops = stream_ops;
pipe_sock->private_data = private_data;
status = stream_setup_socket(pipe_sock,
event_context,
lp_ctx,
model_ops,
&named_pipe_stream_ops,
"unix",
pipe_sock->pipe_path,
NULL,
NULL,
pipe_sock);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
return NT_STATUS_OK;
fail:
talloc_free(pipe_sock);
return status;
}