summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcli/named_pipe_auth/npa_tstream.c120
-rw-r--r--libcli/named_pipe_auth/npa_tstream.h32
-rw-r--r--librpc/idl/named_pipe_auth.idl17
-rw-r--r--librpc/wscript_build7
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/rpc_server/rpc_ncacn_np.c45
-rw-r--r--source3/rpc_server/rpc_server.c49
-rw-r--r--source4/auth/session.c147
-rw-r--r--source4/auth/session.h10
-rw-r--r--source4/ntvfs/ipc/vfs_ipc.c56
-rw-r--r--source4/smbd/service_named_pipe.c138
11 files changed, 323 insertions, 301 deletions
diff --git a/libcli/named_pipe_auth/npa_tstream.c b/libcli/named_pipe_auth/npa_tstream.c
index ace90d6664..2aeea5b0d3 100644
--- a/libcli/named_pipe_auth/npa_tstream.c
+++ b/libcli/named_pipe_auth/npa_tstream.c
@@ -59,16 +59,14 @@ struct tstream_npa_connect_state {
static void tstream_npa_connect_unix_done(struct tevent_req *subreq);
struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- const char *directory,
- const char *npipe,
- const struct tsocket_address *client,
- const char *client_name_in,
- const struct tsocket_address *server,
- const char *server_name,
- const struct netr_SamInfo3 *sam_info3,
- DATA_BLOB session_key,
- DATA_BLOB delegated_creds)
+ struct tevent_context *ev,
+ const char *directory,
+ const char *npipe,
+ const struct tsocket_address *client,
+ const char *client_name_in,
+ const struct tsocket_address *server,
+ const char *server_name,
+ const struct auth_session_info_transport *session_info)
{
struct tevent_req *req;
struct tstream_npa_connect_state *state;
@@ -76,7 +74,7 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
int ret;
enum ndr_err_code ndr_err;
char *lower_case_npipe;
- struct named_pipe_auth_req_info3 *info3;
+ struct named_pipe_auth_req_info4 *info4;
req = tevent_req_create(mem_ctx, &state,
struct tstream_npa_connect_state);
@@ -122,37 +120,33 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
goto post;
}
- state->auth_req.level = 3;
- info3 = &state->auth_req.info.info3;
+ state->auth_req.level = 4;
+ info4 = &state->auth_req.info.info4;
- info3->client_name = client_name_in;
- info3->client_addr = tsocket_address_inet_addr_string(client, state);
- if (!info3->client_addr) {
+ info4->client_name = client_name_in;
+ info4->client_addr = tsocket_address_inet_addr_string(client, state);
+ if (!info4->client_addr) {
/* errno might be EINVAL */
tevent_req_error(req, errno);
goto post;
}
- info3->client_port = tsocket_address_inet_port(client);
- if (!info3->client_name) {
- info3->client_name = info3->client_addr;
+ info4->client_port = tsocket_address_inet_port(client);
+ if (!info4->client_name) {
+ info4->client_name = info4->client_addr;
}
- info3->server_addr = tsocket_address_inet_addr_string(server, state);
- if (!info3->server_addr) {
+ info4->server_addr = tsocket_address_inet_addr_string(server, state);
+ if (!info4->server_addr) {
/* errno might be EINVAL */
tevent_req_error(req, errno);
goto post;
}
- info3->server_port = tsocket_address_inet_port(server);
- if (!info3->server_name) {
- info3->server_name = info3->server_addr;
+ info4->server_port = tsocket_address_inet_port(server);
+ if (!info4->server_name) {
+ info4->server_name = info4->server_addr;
}
- info3->sam_info3 = discard_const_p(struct netr_SamInfo3, sam_info3);
- info3->session_key_length = session_key.length;
- info3->session_key = session_key.data;
- info3->gssapi_delegated_creds_length = delegated_creds.length;
- info3->gssapi_delegated_creds = delegated_creds.data;
+ info4->session_info = discard_const_p(struct auth_session_info_transport, session_info);
if (DEBUGLVL(10)) {
NDR_PRINT_DEBUG(named_pipe_auth_req, &state->auth_req);
@@ -422,10 +416,10 @@ int _tstream_npa_connect_recv(struct tevent_req *req,
npas->unix_stream = talloc_move(stream, &state->unix_stream);
switch (state->auth_rep.level) {
- case 3:
- npas->file_type = state->auth_rep.info.info3.file_type;
- device_state = state->auth_rep.info.info3.device_state;
- allocation_size = state->auth_rep.info.info3.allocation_size;
+ case 4:
+ npas->file_type = state->auth_rep.info.info4.file_type;
+ device_state = state->auth_rep.info.info4.device_state;
+ allocation_size = state->auth_rep.info.info4.allocation_size;
break;
}
@@ -1086,9 +1080,7 @@ struct tstream_npa_accept_state {
char *client_name;
struct tsocket_address *server;
char *server_name;
- struct netr_SamInfo3 *info3;
- DATA_BLOB session_key;
- DATA_BLOB delegated_creds;
+ struct auth_session_info_transport *session_info;
};
static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
@@ -1238,7 +1230,7 @@ static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
tevent_req_data(req, struct tstream_npa_accept_state);
struct named_pipe_auth_req *pipe_request;
struct named_pipe_auth_rep pipe_reply;
- struct named_pipe_auth_req_info3 i3;
+ struct named_pipe_auth_req_info4 i4;
enum ndr_err_code ndr_err;
DATA_BLOB out;
int sys_errno;
@@ -1283,70 +1275,62 @@ static void tstream_npa_accept_existing_reply(struct tevent_req *subreq)
NDR_PRINT_DEBUG(named_pipe_auth_req, pipe_request);
}
- ZERO_STRUCT(i3);
+ ZERO_STRUCT(i4);
- if (pipe_request->level != 3) {
+ if (pipe_request->level != 4) {
DEBUG(0, ("Unknown level %u\n", pipe_request->level));
pipe_reply.level = 0;
pipe_reply.status = NT_STATUS_INVALID_LEVEL;
goto reply;
}
- pipe_reply.level = 3;
+ pipe_reply.level = 4;
pipe_reply.status = NT_STATUS_OK;
- pipe_reply.info.info3.file_type = state->file_type;
- pipe_reply.info.info3.device_state = state->device_state;
- pipe_reply.info.info3.allocation_size = state->alloc_size;
+ pipe_reply.info.info4.file_type = state->file_type;
+ pipe_reply.info.info4.device_state = state->device_state;
+ pipe_reply.info.info4.allocation_size = state->alloc_size;
- i3 = pipe_request->info.info3;
- if (i3.server_addr == NULL) {
+ i4 = pipe_request->info.info4;
+ if (i4.server_addr == NULL) {
pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
DEBUG(2, ("Missing server address\n"));
goto reply;
}
- if (i3.client_addr == NULL) {
+ if (i4.client_addr == NULL) {
pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
DEBUG(2, ("Missing client address\n"));
goto reply;
}
state->server_name = discard_const_p(char,
- talloc_move(state, &i3.server_name));
+ talloc_move(state, &i4.server_name));
ret = tsocket_address_inet_from_strings(state, "ip",
- i3.server_addr,
- i3.server_port,
+ i4.server_addr,
+ i4.server_port,
&state->server);
if (ret != 0) {
DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
- i3.server_addr, i3.server_port,
+ i4.server_addr, i4.server_port,
strerror(errno)));
pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
goto reply;
}
state->client_name = discard_const_p(char,
- talloc_move(state, &i3.client_name));
+ talloc_move(state, &i4.client_name));
ret = tsocket_address_inet_from_strings(state, "ip",
- i3.client_addr,
- i3.client_port,
+ i4.client_addr,
+ i4.client_port,
&state->client);
if (ret != 0) {
DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
- i3.client_addr, i3.client_port,
+ i4.client_addr, i4.client_port,
strerror(errno)));
pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
goto reply;
}
- state->info3 = talloc_move(state, &i3.sam_info3);
- state->session_key.data = talloc_move(state, &i3.session_key);
- state->session_key.length = i3.session_key_length;
-
- state->delegated_creds.data =
- talloc_move(state, &i3.gssapi_delegated_creds);
- state->delegated_creds.length =
- i3.gssapi_delegated_creds_length;
-
+ state->session_info = talloc_move(state, &i4.session_info);
reply:
/* create the output */
ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
@@ -1406,9 +1390,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
char **_client_name,
struct tsocket_address **server,
char **server_name,
- struct netr_SamInfo3 **info3,
- DATA_BLOB *session_key,
- DATA_BLOB *delegated_creds,
+ struct auth_session_info_transport **session_info,
const char *location)
{
struct tstream_npa_accept_state *state =
@@ -1457,11 +1439,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
*_client_name = talloc_move(mem_ctx, &state->client_name);
*server = talloc_move(mem_ctx, &state->server);
*server_name = talloc_move(mem_ctx, &state->server_name);
- *info3 = talloc_move(mem_ctx, &state->info3);
- *session_key = state->session_key;
- talloc_steal(mem_ctx, state->session_key.data);
- *delegated_creds = state->delegated_creds;
- talloc_steal(mem_ctx, state->delegated_creds.data);
+ *session_info = talloc_move(mem_ctx, &state->session_info);
tevent_req_received(req);
return 0;
diff --git a/libcli/named_pipe_auth/npa_tstream.h b/libcli/named_pipe_auth/npa_tstream.h
index 63845bed6a..f2223170f0 100644
--- a/libcli/named_pipe_auth/npa_tstream.h
+++ b/libcli/named_pipe_auth/npa_tstream.h
@@ -22,19 +22,17 @@
struct tevent_req;
struct tevent_context;
-struct netr_SamInfo3;
+struct auth_session_info_transport;
struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- const char *directory,
- const char *npipe,
- const struct tsocket_address *client,
- const char *client_name_in,
- const struct tsocket_address *server,
- const char *server_name,
- const struct netr_SamInfo3 *info3,
- DATA_BLOB session_key,
- DATA_BLOB delegated_creds);
+ struct tevent_context *ev,
+ const char *directory,
+ const char *npipe,
+ const struct tsocket_address *client,
+ const char *client_name_in,
+ const struct tsocket_address *server,
+ const char *server_name,
+ const struct auth_session_info_transport *session_info);
int _tstream_npa_connect_recv(struct tevent_req *req,
int *perrno,
TALLOC_CTX *mem_ctx,
@@ -101,25 +99,21 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct tstream_context **stream,
struct tsocket_address **client,
- char **client_name,
+ char **_client_name,
struct tsocket_address **server,
char **server_name,
- struct netr_SamInfo3 **info3,
- DATA_BLOB *session_key,
- DATA_BLOB *delegated_creds,
+ struct auth_session_info_transport **session_info,
const char *location);
#define tstream_npa_accept_existing_recv(req, perrno, \
mem_ctx, stream, \
client, client_name, \
server, server_name, \
- info3, session_key, \
- delegated_creds) \
+ session_info) \
_tstream_npa_accept_existing_recv(req, perrno, \
mem_ctx, stream, \
client, client_name, \
server, server_name, \
- info3, session_key, \
- delegated_creds, \
+ session_info, \
__location__)
#endif /* NPA_TSTREAM_H */
diff --git a/librpc/idl/named_pipe_auth.idl b/librpc/idl/named_pipe_auth.idl
index de89588664..721667eef9 100644
--- a/librpc/idl/named_pipe_auth.idl
+++ b/librpc/idl/named_pipe_auth.idl
@@ -3,7 +3,7 @@
miscellaneous IDL structures
*/
-import "netlogon.idl";
+import "netlogon.idl", "security.idl", "auth.idl";
[
pointer_default(unique)
@@ -19,16 +19,11 @@ interface named_pipe_auth
[charset(UTF8),string] uint8 *server_name;
[charset(DOS),string] uint8 *server_addr;
uint16 server_port;
- netr_SamInfo3 *sam_info3;
- uint32 session_key_length;
- [size_is(session_key_length)] uint8 *session_key;
- uint32 gssapi_delegated_creds_length;
- [size_is(gssapi_delegated_creds_length)]
- uint8 *gssapi_delegated_creds;
- } named_pipe_auth_req_info3;
+ auth_session_info_transport *session_info;
+ } named_pipe_auth_req_info4;
typedef [switch_type(uint32)] union {
- [case(3)] named_pipe_auth_req_info3 info3;
+ [case(4)] named_pipe_auth_req_info4 info4;
} named_pipe_auth_req_info;
typedef [public,gensize] struct {
@@ -44,10 +39,10 @@ interface named_pipe_auth
uint16 file_type;
uint16 device_state;
hyper allocation_size;
- } named_pipe_auth_rep_info3;
+ } named_pipe_auth_rep_info4;
typedef [switch_type(uint32)] union {
- [case(3)] named_pipe_auth_rep_info3 info3;
+ [case(4)] named_pipe_auth_rep_info4 info4;
} named_pipe_auth_rep_info;
typedef [public,gensize] struct {
diff --git a/librpc/wscript_build b/librpc/wscript_build
index d15e8b225d..706977c45d 100644
--- a/librpc/wscript_build
+++ b/librpc/wscript_build
@@ -8,9 +8,14 @@ bld.SAMBA_SUBSYSTEM('NDR_AUDIOSRV',
public_deps='ndr'
)
+bld.SAMBA_SUBSYSTEM('NDR_AUTH',
+ source='gen_ndr/ndr_auth.c',
+ public_deps='ndr NDR_SECURITY'
+ )
+
bld.SAMBA_SUBSYSTEM('NDR_NAMED_PIPE_AUTH',
source='gen_ndr/ndr_named_pipe_auth.c',
- public_deps='ndr'
+ public_deps='ndr NDR_AUTH'
)
bld.SAMBA_SUBSYSTEM('NDR_DNSSERVER',
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 15d854eb15..3012caa7d3 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -709,7 +709,8 @@ RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog_nt.o \
$(LIB_EVENTLOG_OBJ) librpc/gen_ndr/srv_eventlog.o
NPA_TSTREAM_OBJ = ../libcli/named_pipe_auth/npa_tstream.o \
- librpc/gen_ndr/ndr_named_pipe_auth.o
+ librpc/gen_ndr/ndr_named_pipe_auth.o \
+ ../auth/auth_sam_reply.o librpc/gen_ndr/ndr_auth.o
RPC_NCACN_NP = rpc_server/srv_pipe_register.o rpc_server/rpc_ncacn_np.o \
rpc_server/rpc_handles.o
diff --git a/source3/rpc_server/rpc_ncacn_np.c b/source3/rpc_server/rpc_ncacn_np.c
index af21ec2aad..c35fa847ad 100644
--- a/source3/rpc_server/rpc_ncacn_np.c
+++ b/source3/rpc_server/rpc_ncacn_np.c
@@ -26,6 +26,8 @@
#include "../libcli/named_pipe_auth/npa_tstream.h"
#include "rpc_server/rpc_ncacn_np.h"
#include "librpc/gen_ndr/netlogon.h"
+#include "librpc/gen_ndr/auth.h"
+#include "../auth/auth_sam_reply.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
@@ -594,7 +596,9 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
const char *socket_dir;
struct tevent_context *ev;
struct tevent_req *subreq;
- struct netr_SamInfo3 *info3;
+ struct auth_session_info_transport *session_info;
+ struct auth_user_info_dc *user_info_dc;
+ union netr_Validation val;
NTSTATUS status;
bool ok;
int ret;
@@ -637,20 +641,31 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
goto fail;
}
- info3 = talloc_zero(talloc_tos(), struct netr_SamInfo3);
- if (info3 == NULL) {
+ session_info = talloc_zero(talloc_tos(), struct auth_session_info_transport);
+ if (session_info == NULL) {
DEBUG(0, ("talloc failed\n"));
goto fail;
}
- status = serverinfo_to_SamInfo3(server_info, NULL, 0, info3);
+ /* Send the named_pipe_auth server the user's full token */
+ session_info->security_token = server_info->ptok;
+ session_info->session_key = server_info->user_session_key;
+
+ val.sam3 = server_info->info3;
+
+ /* Convert into something we can build a struct
+ * auth_session_info_transport from. Most of the work here
+ * will be to convert the SIDS, which we will then ignore, but
+ * this is the easier way to handle it */
+ status = make_user_info_dc_netlogon_validation(talloc_tos(), "", 3, &val, &user_info_dc);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(info3);
- DEBUG(0, ("serverinfo_to_SamInfo3 failed: %s\n",
- nt_errstr(status)));
+ DEBUG(0, ("conversion of info3 into user_info_dc failed!\n"));
goto fail;
}
+ session_info->info = talloc_move(session_info, &user_info_dc->info);
+ talloc_free(user_info_dc);
+
become_root();
subreq = tstream_npa_connect_send(talloc_tos(), ev,
socket_np_dir,
@@ -659,15 +674,13 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
NULL, /* client_name */
local_address, /* server_addr */
NULL, /* server_name */
- info3,
- server_info->user_session_key,
- data_blob_null /* delegated_creds */);
+ session_info);
if (subreq == NULL) {
unbecome_root();
DEBUG(0, ("tstream_npa_connect_send to %s for pipe %s and "
"user %s\\%s failed\n",
- socket_np_dir, pipe_name, info3->base.domain.string,
- info3->base.account_name.string));
+ socket_np_dir, pipe_name, session_info->info->domain_name,
+ session_info->info->account_name));
goto fail;
}
ok = tevent_req_poll(subreq, ev);
@@ -675,8 +688,8 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
if (!ok) {
DEBUG(0, ("tevent_req_poll to %s for pipe %s and user %s\\%s "
"failed for tstream_npa_connect: %s\n",
- socket_np_dir, pipe_name, info3->base.domain.string,
- info3->base.account_name.string,
+ socket_np_dir, pipe_name, session_info->info->domain_name,
+ session_info->info->account_name,
strerror(errno)));
goto fail;
@@ -691,8 +704,8 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
if (ret != 0) {
DEBUG(0, ("tstream_npa_connect_recv to %s for pipe %s and "
"user %s\\%s failed: %s\n",
- socket_np_dir, pipe_name, info3->base.domain.string,
- info3->base.account_name.string,
+ socket_np_dir, pipe_name, session_info->info->domain_name,
+ session_info->info->account_name,
strerror(sys_errno)));
goto fail;
}
diff --git a/source3/rpc_server/rpc_server.c b/source3/rpc_server/rpc_server.c
index 229096e463..a0da354fd3 100644
--- a/source3/rpc_server/rpc_server.c
+++ b/source3/rpc_server/rpc_server.c
@@ -21,9 +21,11 @@
#include "rpc_server/rpc_server.h"
#include "rpc_dce.h"
#include "librpc/gen_ndr/netlogon.h"
+#include "librpc/gen_ndr/auth.h"
#include "registry/reg_parse_prs.h"
#include "lib/tsocket/tsocket.h"
#include "libcli/named_pipe_auth/npa_tstream.h"
+#include "../auth/auth_sam_reply.h"
/* Creates a pipes_struct and initializes it with the information
* sent from the client */
@@ -31,10 +33,12 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
const char *pipe_name,
const struct ndr_syntax_id id,
const char *client_address,
- struct netr_SamInfo3 *info3,
+ struct auth_session_info_transport *session_info,
struct pipes_struct **_p,
int *perrno)
{
+ struct netr_SamInfo3 *info3;
+ struct auth_user_info_dc *auth_user_info_dc;
struct pipes_struct *p;
NTSTATUS status;
bool ok;
@@ -67,6 +71,30 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
p->endian = RPC_LITTLE_ENDIAN;
+ /* Fake up an auth_user_info_dc for now, to make an info3, to make the server_info structure */
+ auth_user_info_dc = talloc_zero(p, struct auth_user_info_dc);
+ if (!auth_user_info_dc) {
+ TALLOC_FREE(p);
+ *perrno = ENOMEM;
+ return -1;
+ }
+
+ auth_user_info_dc->num_sids = session_info->security_token->num_sids;
+ auth_user_info_dc->sids = session_info->security_token->sids;
+ auth_user_info_dc->info = session_info->info;
+ auth_user_info_dc->user_session_key = session_info->session_key;
+
+ /* This creates the input structure that make_server_info_info3 is looking for */
+ status = auth_convert_user_info_dc_saminfo3(p, auth_user_info_dc,
+ &info3);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to convert auth_user_info_dc into netr_SamInfo3\n"));
+ TALLOC_FREE(p);
+ *perrno = EINVAL;
+ return -1;
+ }
+
status = make_server_info_info3(p,
info3->base.account_name.string,
info3->base.domain.string,
@@ -90,6 +118,15 @@ static int make_server_pipes_struct(TALLOC_CTX *mem_ctx,
return -1;
}
+ /* Now override the server_info->ptok with the exact
+ * security_token we were given from the other side,
+ * regardless of what we just calculated */
+ p->server_info->ptok = talloc_move(p->server_info, &session_info->security_token);
+
+ /* Also set the session key to the correct value */
+ p->server_info->user_session_key = session_info->session_key;
+ p->server_info->user_session_key.data = talloc_move(p->server_info, &session_info->session_key.data);
+
p->client_id = talloc_zero(p, struct client_address);
if (!p->client_id) {
TALLOC_FREE(p);
@@ -318,9 +355,7 @@ struct named_pipe_client {
char *client_name;
struct tsocket_address *server;
char *server_name;
- struct netr_SamInfo3 *info3;
- DATA_BLOB session_key;
- DATA_BLOB delegated_creds;
+ struct auth_session_info_transport *session_info;
struct pipes_struct *p;
@@ -410,9 +445,7 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
&npc->client_name,
&npc->server,
&npc->server_name,
- &npc->info3,
- &npc->session_key,
- &npc->delegated_creds);
+ &npc->session_info);
TALLOC_FREE(subreq);
if (ret != 0) {
DEBUG(2, ("Failed to accept named pipe connection! (%s)\n",
@@ -434,7 +467,7 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
ret = make_server_pipes_struct(npc,
npc->pipe_name, npc->pipe_id,
- cli_addr, npc->info3,
+ cli_addr, npc->session_info,
&npc->p, &error);
if (ret != 0) {
DEBUG(2, ("Failed to create pipes_struct! (%s)\n",
diff --git a/source4/auth/session.c b/source4/auth/session.c
index a6b8b2688c..cf5514cbf7 100644
--- a/source4/auth/session.c
+++ b/source4/auth/session.c
@@ -24,10 +24,14 @@
#include "includes.h"
#include "auth/auth.h"
#include "auth/auth_sam.h"
+#include "auth/credentials/credentials.h"
+#include "auth/credentials/credentials_krb5.h"
#include "libcli/security/security.h"
#include "libcli/auth/libcli_auth.h"
#include "dsdb/samdb/samdb.h"
#include "auth/session_proto.h"
+#include "system/kerberos.h"
+#include <gssapi/gssapi.h>
_PUBLIC_ struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx,
struct loadparm_context *lp_ctx)
@@ -151,6 +155,149 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+/* Create a session_info structure from the
+ * auth_session_info_transport we were forwarded over named pipe
+ * forwarding.
+ *
+ * NOTE: The stucture members of session_info_transport are stolen
+ * with talloc_move() into auth_session_info for long term use
+ */
+struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
+ struct auth_session_info_transport *session_info_transport,
+ struct loadparm_context *lp_ctx,
+ const char **reason)
+{
+ struct auth_session_info *session_info;
+ session_info = talloc_zero(mem_ctx, struct auth_session_info);
+ if (!session_info) {
+ *reason = "failed to allocate session_info";
+ return NULL;
+ }
+
+ session_info->security_token = talloc_move(session_info, &session_info_transport->security_token);
+ session_info->info = talloc_move(session_info, &session_info_transport->info);
+ session_info->session_key = session_info_transport->session_key;
+ session_info->session_key.data = talloc_move(session_info, &session_info_transport->session_key.data);
+
+ if (session_info_transport->exported_gssapi_credentials.length) {
+ struct cli_credentials *creds;
+ OM_uint32 minor_status;
+ gss_buffer_desc cred_token;
+ gss_cred_id_t cred_handle;
+ const char *error_string;
+ int ret;
+
+ DEBUG(10, ("Delegated credentials supplied by client\n"));
+
+ cred_token.value = session_info_transport->exported_gssapi_credentials.data;
+ cred_token.length = session_info_transport->exported_gssapi_credentials.length;
+
+ ret = gss_import_cred(&minor_status,
+ &cred_token,
+ &cred_handle);
+ if (ret != GSS_S_COMPLETE) {
+ *reason = "Internal error in gss_import_cred()";
+ return NULL;
+ }
+
+ creds = cli_credentials_init(session_info);
+ if (!creds) {
+ *reason = "Out of memory in cli_credentials_init()";
+ return NULL;
+ }
+ session_info->credentials = creds;
+
+ cli_credentials_set_conf(creds, lp_ctx);
+ /* Just so we don't segfault trying to get at a username */
+ cli_credentials_set_anonymous(creds);
+
+ ret = cli_credentials_set_client_gss_creds(creds,
+ lp_ctx,
+ cred_handle,
+ CRED_SPECIFIED,
+ &error_string);
+ if (ret) {
+ *reason = talloc_asprintf(mem_ctx,
+ "Failed to set pipe forwarded"
+ "creds: %s\n", error_string);
+ return NULL;
+ }
+
+ /* This credential handle isn't useful for password
+ * authentication, so ensure nobody tries to do that */
+ cli_credentials_set_kerberos_state(creds,
+ CRED_MUST_USE_KERBEROS);
+
+ }
+
+ return session_info;
+}
+
+
+/* Create a auth_session_info_transport from an auth_session_info.
+ *
+ * NOTE: Members of the auth_session_info_transport structure are not talloc_referenced, but simply assigned. They are only valid for the lifetime of the struct auth_session_info
+ *
+ * This isn't normally an issue, as the auth_session_info has a very long typical life
+ */
+NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
+ struct auth_session_info *session_info,
+ struct tevent_context *event_ctx,
+ struct loadparm_context *lp_ctx,
+ struct auth_session_info_transport **transport_out)
+{
+
+ struct auth_session_info_transport *session_info_transport = talloc_zero(mem_ctx, struct auth_session_info_transport);
+ session_info_transport->security_token = talloc_reference(session_info, session_info->security_token);
+ NT_STATUS_HAVE_NO_MEMORY(session_info_transport->security_token);
+
+ session_info_transport->info = talloc_reference(session_info, session_info->info);
+ NT_STATUS_HAVE_NO_MEMORY(session_info_transport->info);
+
+ session_info_transport->session_key = session_info->session_key;
+ session_info_transport->session_key.data = talloc_reference(session_info, session_info->session_key.data);
+ if (!session_info_transport->session_key.data && session_info->session_key.length) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (session_info->credentials) {
+ struct gssapi_creds_container *gcc;
+ OM_uint32 gret;
+ OM_uint32 minor_status;
+ gss_buffer_desc cred_token;
+ const char *error_string;
+ int ret;
+
+ ret = cli_credentials_get_client_gss_creds(session_info->credentials,
+ event_ctx,
+ lp_ctx,
+ &gcc, &error_string);
+ if (ret != 0) {
+ *transport_out = session_info_transport;
+ return NT_STATUS_OK;
+ }
+
+ gret = gss_export_cred(&minor_status,
+ gcc->creds,
+ &cred_token);
+ if (gret != GSS_S_COMPLETE) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ if (cred_token.length) {
+ session_info_transport->exported_gssapi_credentials
+ = data_blob_talloc(session_info_transport,
+ cred_token.value,
+ cred_token.length);
+ gss_release_buffer(&minor_status, &cred_token);
+ NT_STATUS_HAVE_NO_MEMORY(session_info_transport->exported_gssapi_credentials.data);
+ }
+ }
+ *transport_out = session_info_transport;
+ return NT_STATUS_OK;
+}
+
+
/* Produce a session_info for an arbitary DN or principal in the local
* DB, assuming the local DB holds all the groups
*
diff --git a/source4/auth/session.h b/source4/auth/session.h
index d8c00a39a4..795497ea8f 100644
--- a/source4/auth/session.h
+++ b/source4/auth/session.h
@@ -52,6 +52,16 @@ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx,
struct loadparm_context *lp_ctx,
struct auth_session_info **session_info);
+struct auth_session_info *auth_session_info_from_transport(TALLOC_CTX *mem_ctx,
+ struct auth_session_info_transport *session_info_transport,
+ struct loadparm_context *lp_ctx,
+ const char **reason);
+NTSTATUS auth_session_info_transport_from_session(TALLOC_CTX *mem_ctx,
+ struct auth_session_info *session_info,
+ struct tevent_context *event_ctx,
+ struct loadparm_context *lp_ctx,
+ struct auth_session_info_transport **transport_out);
+
/* Produce a session_info for an arbitary DN or principal in the local
* DB, assuming the local DB holds all the groups
*
diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c
index 19127a29bc..185e72cfb0 100644
--- a/source4/ntvfs/ipc/vfs_ipc.c
+++ b/source4/ntvfs/ipc/vfs_ipc.c
@@ -217,7 +217,7 @@ struct ipc_open_state {
struct pipe_state *p;
struct ntvfs_request *req;
union smb_open *oi;
- struct netr_SamInfo3 *info3;
+ struct auth_session_info_transport *session_info_transport;
};
static void ipc_open_done(struct tevent_req *subreq);
@@ -253,9 +253,6 @@ static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
const char *directory;
const struct tsocket_address *client_addr;
const struct tsocket_address *server_addr;
- int ret;
- DATA_BLOB delegated_creds = data_blob_null;
- struct auth_user_info_dc user_info_dc;
switch (oi->generic.level) {
case RAW_OPEN_NTCREATEX:
@@ -310,54 +307,17 @@ static NTSTATUS ipc_open(struct ntvfs_module_context *ntvfs,
state->req = req;
state->oi = oi;
- /* Disgusting hack to recreate the user_info_dc that should
- * not be used that this layer in this way */
- ZERO_STRUCT(user_info_dc);
- user_info_dc.info = req->session_info->info;
- user_info_dc.num_sids = req->session_info->torture->num_dc_sids;
- user_info_dc.sids = req->session_info->torture->dc_sids;
+ status = auth_session_info_transport_from_session(state,
+ req->session_info,
+ ipriv->ntvfs->ctx->event_ctx,
+ ipriv->ntvfs->ctx->lp_ctx,
+ &state->session_info_transport);
- status = auth_convert_user_info_dc_saminfo3(state,
- &user_info_dc,
- &state->info3);
NT_STATUS_NOT_OK_RETURN(status);
client_addr = ntvfs_get_local_address(ipriv->ntvfs);
server_addr = ntvfs_get_remote_address(ipriv->ntvfs);
- if (req->session_info->credentials) {
- struct gssapi_creds_container *gcc;
- OM_uint32 gret;
- OM_uint32 minor_status;
- gss_buffer_desc cred_token;
- const char *error_string;
-
- ret = cli_credentials_get_client_gss_creds(req->session_info->credentials,
- ipriv->ntvfs->ctx->event_ctx,
- ipriv->ntvfs->ctx->lp_ctx,
- &gcc, &error_string);
- if (ret) {
- goto skip;
- }
-
- gret = gss_export_cred(&minor_status,
- gcc->creds,
- &cred_token);
- if (gret != GSS_S_COMPLETE) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- if (cred_token.length) {
- delegated_creds = data_blob_talloc(req,
- cred_token.value,
- cred_token.length);
- gss_release_buffer(&minor_status, &cred_token);
- NT_STATUS_HAVE_NO_MEMORY(delegated_creds.data);
- }
- }
-
-skip:
-
subreq = tstream_npa_connect_send(p,
ipriv->ntvfs->ctx->event_ctx,
directory,
@@ -366,9 +326,7 @@ skip:
NULL,
server_addr,
NULL,
- state->info3,
- req->session_info->session_key,
- delegated_creds);
+ state->session_info_transport);
NT_STATUS_HAVE_NO_MEMORY(subreq);
tevent_req_set_callback(subreq, ipc_open_done, state);
diff --git a/source4/smbd/service_named_pipe.c b/source4/smbd/service_named_pipe.c
index 148d4fdf80..086a037b69 100644
--- a/source4/smbd/service_named_pipe.c
+++ b/source4/smbd/service_named_pipe.c
@@ -33,8 +33,7 @@
#include "system/passwd.h"
#include "system/network.h"
#include "libcli/raw/smb.h"
-#include "auth/credentials/credentials.h"
-#include "auth/credentials/credentials_krb5.h"
+#include "auth/session.h"
#include "libcli/security/security.h"
#include "libcli/named_pipe_auth/npa_tstream.h"
@@ -93,18 +92,9 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
char *client_name;
struct tsocket_address *server;
char *server_name;
- struct netr_SamInfo3 *info3;
- DATA_BLOB session_key;
- DATA_BLOB delegated_creds;
-
- union netr_Validation val;
- struct auth_user_info_dc *user_info_dc;
- struct auth_context *auth_context;
- uint32_t session_flags = 0;
- struct dom_sid *anonymous_sid;
+ struct auth_session_info_transport *session_info_transport;
const char *reason = NULL;
TALLOC_CTX *tmp_ctx;
- NTSTATUS status;
int error;
int ret;
@@ -115,14 +105,12 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
}
ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx,
- &conn->tstream,
- &client,
- &client_name,
- &server,
- &server_name,
- &info3,
- &session_key,
- &delegated_creds);
+ &conn->tstream,
+ &client,
+ &client_name,
+ &server,
+ &server_name,
+ &session_info_transport);
TALLOC_FREE(subreq);
if (ret != 0) {
reason = talloc_asprintf(conn,
@@ -137,111 +125,11 @@ static void named_pipe_accept_done(struct tevent_req *subreq)
client_name, tsocket_address_string(client, tmp_ctx),
server_name, tsocket_address_string(server, tmp_ctx)));
- if (info3) {
- val.sam3 = info3;
-
- status = make_user_info_dc_netlogon_validation(conn,
- val.sam3->base.account_name.string,
- 3, &val, &user_info_dc);
- if (!NT_STATUS_IS_OK(status)) {
- reason = talloc_asprintf(conn,
- "make_user_info_dc_netlogon_validation "
- "returned: %s", nt_errstr(status));
- goto out;
- }
-
- status = auth_context_create(conn, conn->event.ctx,
- conn->msg_ctx, conn->lp_ctx,
- &auth_context);
- if (!NT_STATUS_IS_OK(status)) {
- reason = talloc_asprintf(conn,
- "auth_context_create returned: %s",
- nt_errstr(status));
- goto out;
- }
-
- anonymous_sid = dom_sid_parse_talloc(auth_context,
- SID_NT_ANONYMOUS);
- if (anonymous_sid == NULL) {
- talloc_free(auth_context);
- reason = "Failed to parse Anonymous SID ";
- goto out;
- }
-
- session_flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
- if (user_info_dc->num_sids > 1 && !dom_sid_equal(anonymous_sid, &user_info_dc->sids[0])) {
- session_flags |= AUTH_SESSION_INFO_AUTHENTICATED;
- }
-
-
- /* setup the session_info on the connection */
- status = auth_context->generate_session_info(conn,
- auth_context,
- user_info_dc,
- session_flags,
- &conn->session_info);
- talloc_free(auth_context);
- if (!NT_STATUS_IS_OK(status)) {
- reason = talloc_asprintf(conn,
- "auth_generate_session_info "
- "returned: %s", nt_errstr(status));
- goto out;
- }
- }
-
- if (session_key.length) {
- conn->session_info->session_key = session_key;
- talloc_steal(conn->session_info, session_key.data);
- }
-
- if (delegated_creds.length) {
- struct cli_credentials *creds;
- OM_uint32 minor_status;
- gss_buffer_desc cred_token;
- gss_cred_id_t cred_handle;
- const char *error_string;
-
- DEBUG(10, ("Delegated credentials supplied by client\n"));
-
- cred_token.value = delegated_creds.data;
- cred_token.length = delegated_creds.length;
-
- ret = gss_import_cred(&minor_status,
- &cred_token,
- &cred_handle);
- if (ret != GSS_S_COMPLETE) {
- reason = "Internal error in gss_import_cred()";
- goto out;
- }
-
- creds = cli_credentials_init(conn->session_info);
- if (!creds) {
- reason = "Out of memory in cli_credentials_init()";
- goto out;
- }
- conn->session_info->credentials = creds;
-
- cli_credentials_set_conf(creds, conn->lp_ctx);
- /* Just so we don't segfault trying to get at a username */
- cli_credentials_set_anonymous(creds);
-
- ret = cli_credentials_set_client_gss_creds(creds,
- conn->lp_ctx,
- cred_handle,
- CRED_SPECIFIED,
- &error_string);
- if (ret) {
- reason = talloc_asprintf(conn,
- "Failed to set pipe forwarded"
- "creds: %s\n", error_string);
- goto out;
- }
-
- /* This credential handle isn't useful for password
- * authentication, so ensure nobody tries to do that */
- cli_credentials_set_kerberos_state(creds,
- CRED_MUST_USE_KERBEROS);
-
+ conn->session_info = auth_session_info_from_transport(conn, session_info_transport,
+ conn->lp_ctx,
+ &reason);
+ if (!conn->session_info) {
+ goto out;
}
/*