libcli/security: fix handling of deny type ACEs in access_check_max_allowed()
[bbaumbach/samba-autobuild/.git] / libcli / named_pipe_auth / npa_tstream.c
index ace90d666480b5bf49164e5a2bb6056fd5dc8e06..8ec52ed9b8597faa7ee25ea20861d7030da627d3 100644 (file)
@@ -24,9 +24,7 @@
 #include "../lib/tsocket/tsocket_internal.h"
 #include "../librpc/gen_ndr/ndr_named_pipe_auth.h"
 #include "../libcli/named_pipe_auth/npa_tstream.h"
-#if _SAMBA_BUILD_ == 4
-#include "libcli/raw/smb.h"
-#endif
+#include "../libcli/smb/smb_constants.h"
 
 static const struct tstream_context_ops tstream_npa_ops;
 
@@ -59,16 +57,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 *remote_client_addr,
+                                           const char *remote_client_name_in,
+                                           const struct tsocket_address *local_server_addr,
+                                           const char *local_server_name,
+                                           const struct auth_session_info_transport *session_info)
 {
        struct tevent_req *req;
        struct tstream_npa_connect_state *state;
@@ -76,7 +72,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);
@@ -117,42 +113,40 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
 
        ZERO_STRUCT(state->auth_req);
 
-       if (!server) {
+       if (!local_server_addr) {
                tevent_req_error(req, EINVAL);
                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->remote_client_name = remote_client_name_in;
+       info4->remote_client_addr = tsocket_address_inet_addr_string(remote_client_addr,
+                                                                    state);
+       if (!info4->remote_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->remote_client_port = tsocket_address_inet_port(remote_client_addr);
+       if (!info4->remote_client_name) {
+               info4->remote_client_name = info4->remote_client_addr;
        }
 
-       info3->server_addr = tsocket_address_inet_addr_string(server, state);
-       if (!info3->server_addr) {
+       info4->local_server_addr = tsocket_address_inet_addr_string(local_server_addr,
+                                                                   state);
+       if (!info4->local_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->local_server_port = tsocket_address_inet_port(local_server_addr);
+       if (!info4->local_server_name) {
+               info4->local_server_name = info4->local_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;
        }
 
@@ -1082,13 +1076,11 @@ struct tstream_npa_accept_state {
 
        /* results */
        NTSTATUS accept_status;
-       struct tsocket_address *client;
-       char *client_name;
-       struct tsocket_address *server;
-       char *server_name;
-       struct netr_SamInfo3 *info3;
-       DATA_BLOB session_key;
-       DATA_BLOB delegated_creds;
+       struct tsocket_address *remote_client_addr;
+       char *remote_client_name;
+       struct tsocket_address *local_server_addr;
+       char *local_server_name;
+       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,64 @@ 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.local_server_addr == NULL) {
                pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
-               DEBUG(2, ("Missing server address\n"));
+               DEBUG(2, ("Missing local server address\n"));
                goto reply;
        }
-       if (i3.client_addr == NULL) {
+       if (i4.remote_client_addr == NULL) {
                pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
-               DEBUG(2, ("Missing client address\n"));
+               DEBUG(2, ("Missing remote client address\n"));
                goto reply;
        }
 
-       state->server_name = discard_const_p(char,
-                                            talloc_move(state, &i3.server_name));
+       state->local_server_name = discard_const_p(char,
+                                                  talloc_move(state,
+                                                              &i4.local_server_name));
        ret = tsocket_address_inet_from_strings(state, "ip",
-                                               i3.server_addr,
-                                               i3.server_port,
-                                               &state->server);
+                                               i4.local_server_addr,
+                                               i4.local_server_port,
+                                               &state->local_server_addr);
        if (ret != 0) {
-               DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
-                         i3.server_addr, i3.server_port,
+               DEBUG(2, ("Invalid local server address[%s:%u] - %s\n",
+                         i4.local_server_addr, i4.local_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));
+       state->remote_client_name = discard_const_p(char,
+                                                   talloc_move(state,
+                                                               &i4.remote_client_name));
        ret = tsocket_address_inet_from_strings(state, "ip",
-                                               i3.client_addr,
-                                               i3.client_port,
-                                               &state->client);
+                                               i4.remote_client_addr,
+                                               i4.remote_client_port,
+                                               &state->remote_client_addr);
        if (ret != 0) {
-               DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
-                         i3.client_addr, i3.client_port,
+               DEBUG(2, ("Invalid remote client address[%s:%u] - %s\n",
+                         i4.remote_client_addr, i4.remote_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,
@@ -1402,13 +1388,11 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
                                      int *perrno,
                                      TALLOC_CTX *mem_ctx,
                                      struct tstream_context **stream,
-                                     struct tsocket_address **client,
-                                     char **_client_name,
-                                     struct tsocket_address **server,
-                                     char **server_name,
-                                     struct netr_SamInfo3 **info3,
-                                     DATA_BLOB *session_key,
-                                     DATA_BLOB *delegated_creds,
+                                     struct tsocket_address **remote_client_addr,
+                                     char **_remote_client_name,
+                                     struct tsocket_address **local_server_addr,
+                                     char **local_server_name,
+                                     struct auth_session_info_transport **session_info,
                                      const char *location)
 {
        struct tstream_npa_accept_state *state =
@@ -1418,7 +1402,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
 
        ret = tsocket_simple_int_recv(req, perrno);
        if (ret != 0) {
-               DEBUG(2, ("Failed to accept named pipe conection: %s\n",
+               DEBUG(2, ("Failed to accept named pipe connection: %s\n",
                          strerror(*perrno)));
                tevent_req_received(req);
                return -1;
@@ -1432,7 +1416,7 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
 #else
                *perrno = EINVAL;
 #endif
-               DEBUG(2, ("Failed to accept named pipe conection: %s => %s\n",
+               DEBUG(2, ("Failed to accept named pipe connection: %s => %s\n",
                          nt_errstr(state->accept_status),
                          strerror(*perrno)));
                tevent_req_received(req);
@@ -1453,16 +1437,95 @@ int _tstream_npa_accept_existing_recv(struct tevent_req *req,
        npas->unix_stream = state->plain;
        npas->file_type = state->file_type;
 
-       *client = talloc_move(mem_ctx, &state->client);
-       *_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);
+       *remote_client_addr = talloc_move(mem_ctx, &state->remote_client_addr);
+       *_remote_client_name = talloc_move(mem_ctx, &state->remote_client_name);
+       *local_server_addr = talloc_move(mem_ctx, &state->local_server_addr);
+       *local_server_name = talloc_move(mem_ctx, &state->local_server_name);
+       *session_info = talloc_move(mem_ctx, &state->session_info);
 
        tevent_req_received(req);
        return 0;
 }
+
+
+/* SOCKETPAIR for internal rpc communication */
+
+/* file_type is FILE_TYPE_BYTE_MODE_PIPE or FILE_TYPE_MESSAGE_MODE_PIPE */
+int _tstream_npa_socketpair(uint16_t file_type,
+                           TALLOC_CTX *mem_ctx1,
+                           struct tstream_context **pstream1,
+                           TALLOC_CTX *mem_ctx2,
+                           struct tstream_context **pstream2,
+                           const char *location)
+{
+       struct tstream_context *stream1 = NULL;
+       struct tstream_context *stream2 = NULL;
+       int fds[2];
+       int fd1;
+       int fd2;
+       int rc;
+       bool ok;
+
+       rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+       if (rc == -1) {
+               return -1;
+       }
+       fd1 = fds[0];
+       fd2 = fds[1];
+
+       ok = smb_set_close_on_exec(fd1);
+       if (!ok) {
+               goto close_fail;
+       }
+
+       ok = smb_set_close_on_exec(fd2);
+       if (!ok) {
+               goto close_fail;
+       }
+
+       rc = set_blocking(fd1, false);
+       if (rc == -1) {
+               goto close_fail;
+       }
+
+       rc = set_blocking(fd2, false);
+       if (rc == -1) {
+               goto close_fail;
+       }
+
+       rc = _tstream_npa_existing_socket(mem_ctx1,
+                                         fd1,
+                                         file_type,
+                                         &stream1,
+                                         location);
+       if (rc == -1) {
+               goto close_fail;
+       }
+
+       rc = _tstream_npa_existing_socket(mem_ctx2,
+                                         fd2,
+                                         file_type,
+                                         &stream2,
+                                         location);
+       if (rc == -1) {
+               int sys_errno = errno;
+               talloc_free(stream1);
+               close(fd2);
+               errno = sys_errno;
+               return -1;
+       }
+
+       *pstream1 = stream1;
+       *pstream2 = stream2;
+
+       return 0;
+
+close_fail:
+       {
+               int sys_errno = errno;
+               close(fd1);
+               close(fd2);
+               errno = sys_errno;
+               return -1;
+       }
+}