named_pipe_auth: Rename client -> remote_client and server -> local_server
[samba.git] / libcli / named_pipe_auth / npa_tstream.c
index 0834c7dda68b140c4dbc6f3358da07c93c32fbb9..d333ce6ee229ed59747cac3b0d7d66a41ec3de60 100644 (file)
@@ -24,7 +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"
-#include "libcli/raw/smb.h"
+#include "../libcli/smb/smb_constants.h"
 
 static const struct tstream_context_ops tstream_npa_ops;
 
@@ -57,22 +57,22 @@ 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;
        struct tevent_req *subreq;
        int ret;
        enum ndr_err_code ndr_err;
+       char *lower_case_npipe;
+       struct named_pipe_auth_req_info4 *info4;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct tstream_npa_connect_state);
@@ -82,9 +82,15 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
 
        state->caller.ev = ev;
 
+       lower_case_npipe = strlower_talloc(state, npipe);
+       if (tevent_req_nomem(lower_case_npipe, req)) {
+               goto post;
+       }
+
        state->unix_path = talloc_asprintf(state, "%s/%s",
                                           directory,
-                                          npipe);
+                                          lower_case_npipe);
+       talloc_free(lower_case_npipe);
        if (tevent_req_nomem(state->unix_path, req)) {
                goto post;
        }
@@ -106,52 +112,41 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
        }
 
        ZERO_STRUCT(state->auth_req);
-       if (client) {
-               struct named_pipe_auth_req_info3 *info3;
 
-               if (!server) {
-                       tevent_req_error(req, EINVAL);
-                       goto post;
-               }
-
-               state->auth_req.level = 3;
-               info3 = &state->auth_req.info.info3;
-
-               info3->client_name = client_name_in;
-               info3->client_addr = tsocket_address_inet_addr_string(client, state);
-               if (!info3->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;
-               }
+       if (!local_server_addr) {
+               tevent_req_error(req, EINVAL);
+               goto post;
+       }
 
-               info3->server_addr = tsocket_address_inet_addr_string(server, state);
-               if (!info3->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;
-               }
+       state->auth_req.level = 4;
+       info4 = &state->auth_req.info.info4;
 
-               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->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;
+       }
+       info4->remote_client_port = tsocket_address_inet_port(remote_client_addr);
+       if (!info4->remote_client_name) {
+               info4->remote_client_name = info4->remote_client_addr;
+       }
 
-       } else if (sam_info3) {
-               state->auth_req.level = 1;
-               state->auth_req.info.info1 = *sam_info3;
-       } else {
-               state->auth_req.level = 0;
+       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;
        }
+       info4->local_server_port = tsocket_address_inet_port(local_server_addr);
+       if (!info4->local_server_name) {
+               info4->local_server_name = info4->local_server_addr;
+       }
+
+       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);
@@ -165,7 +160,7 @@ struct tevent_req *tstream_npa_connect_send(TALLOC_CTX *mem_ctx,
                goto post;
        }
 
-       state->auth_req_iov.iov_base = state->auth_req_blob.data;
+       state->auth_req_iov.iov_base = (char *) state->auth_req_blob.data;
        state->auth_req_iov.iov_len = state->auth_req_blob.length;
 
        subreq = tstream_unix_connect_send(state,
@@ -306,7 +301,7 @@ static int tstream_npa_connect_next_vector(struct tstream_context *unix_stream,
        if (!vector) {
                return -1;
        }
-       vector[0].iov_base = state->auth_rep_blob.data + ofs;
+       vector[0].iov_base = (char *) (state->auth_rep_blob.data + ofs);
        vector[0].iov_len = state->auth_rep_blob.length - ofs;
        count = 1;
 
@@ -413,27 +408,18 @@ int _tstream_npa_connect_recv(struct tevent_req *req,
                                        struct tstream_npa,
                                        location);
        if (!stream) {
+               *perrno = ENOMEM;
+               tevent_req_received(req);
                return -1;
        }
        ZERO_STRUCTP(npas);
 
        npas->unix_stream = talloc_move(stream, &state->unix_stream);
        switch (state->auth_rep.level) {
-       case 0:
-       case 1:
-               npas->file_type = FILE_TYPE_BYTE_MODE_PIPE;
-               device_state = 0x00ff;
-               allocation_size = 2048;
-               break;
-       case 2:
-               npas->file_type = state->auth_rep.info.info2.file_type;
-               device_state = state->auth_rep.info.info2.device_state;
-               allocation_size = state->auth_rep.info.info2.allocation_size;
-               break;
-       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;
        }
 
@@ -566,7 +552,7 @@ static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
                                memcpy(base, pbase + ofs, left);
 
                                base += left;
-                               state->vector[0].iov_base = base;
+                               state->vector[0].iov_base = (char *) base;
                                state->vector[0].iov_len -= left;
 
                                ofs += left;
@@ -591,7 +577,7 @@ static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
 
                if (left > 0) {
                        memmove(pbase, pbase + ofs, left);
-                       npas->pending.iov_base = pbase;
+                       npas->pending.iov_base = (char *) pbase;
                        npas->pending.iov_len = left;
                        /*
                         * this cannot fail and even if it
@@ -599,7 +585,7 @@ static struct tevent_req *tstream_npa_readv_send(TALLOC_CTX *mem_ctx,
                         */
                        pbase = talloc_realloc(npas, pbase, uint8_t, left);
                        if (pbase) {
-                               npas->pending.iov_base = pbase;
+                               npas->pending.iov_base = (char *) pbase;
                        }
                        pbase = NULL;
                }
@@ -687,7 +673,7 @@ static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
                        return -1;
                }
                ZERO_STRUCT(state->hdr);
-               vector[0].iov_base = state->hdr;
+               vector[0].iov_base = (char *) state->hdr;
                vector[0].iov_len = sizeof(state->hdr);
 
                count = 1;
@@ -723,11 +709,11 @@ static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
                if (left < state->vector[0].iov_len) {
                        uint8_t *base;
                        base = (uint8_t *)state->vector[0].iov_base;
-                       vector[count].iov_base = base;
+                       vector[count].iov_base = (char *) base;
                        vector[count].iov_len = left;
                        count++;
                        base += left;
-                       state->vector[0].iov_base = base;
+                       state->vector[0].iov_base = (char *) base;
                        state->vector[0].iov_len -= left;
                        break;
                }
@@ -745,7 +731,7 @@ static int tstream_npa_readv_next_vector(struct tstream_context *unix_stream,
                 * into the pending buffer, where the next readv can
                 * be served from.
                 */
-               npas->pending.iov_base = talloc_array(npas, uint8_t, left);
+               npas->pending.iov_base = talloc_array(npas, char, left);
                if (!npas->pending.iov_base) {
                        return -1;
                }
@@ -856,7 +842,7 @@ static struct tevent_req *tstream_npa_writev_send(TALLOC_CTX *mem_ctx,
                if (tevent_req_nomem(new_vector, req)) {
                        goto post;
                }
-               new_vector[0].iov_base = state->hdr;
+               new_vector[0].iov_base = (char *) state->hdr;
                new_vector[0].iov_len = sizeof(state->hdr);
                memcpy(new_vector + 1, vector, sizeof(struct iovec)*count);
 
@@ -1090,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,
@@ -1229,7 +1213,7 @@ static int tstream_npa_accept_next_vector(struct tstream_context *unix_stream,
        if (!vector) {
                return -1;
        }
-       vector[0].iov_base = state->npa_blob.data + ofs;
+       vector[0].iov_base = (char *) (state->npa_blob.data + ofs);
        vector[0].iov_len = state->npa_blob.length - ofs;
        count = 1;
 
@@ -1246,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;
@@ -1291,128 +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);
-
-       switch (pipe_request->level) {
-       case 0:
-               pipe_reply.level = 0;
-               pipe_reply.status = NT_STATUS_OK;
-
-               /* we need to force byte mode in this level */
-               state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
-               break;
-
-       case 1:
-               pipe_reply.level = 1;
-               pipe_reply.status = NT_STATUS_OK;
-
-               /* We must copy net3_SamInfo3, so that
-                * info3 is an actual talloc pointer, then we steal
-                * pipe_request on info3 so that all the allocated memory
-                * pointed by the structrue members is preserved */
-               state->info3 = (struct netr_SamInfo3 *)talloc_memdup(state,
-                                               &pipe_request->info.info1,
-                                               sizeof(struct netr_SamInfo3));
-               if (!state->info3) {
-                       pipe_reply.status = NT_STATUS_NO_MEMORY;
-                       DEBUG(0, ("Out of memory!\n"));
-                       goto reply;
-               }
-               talloc_move(state->info3, &pipe_request);
-
-               /* we need to force byte mode in this level */
-               state->file_type = FILE_TYPE_BYTE_MODE_PIPE;
-               break;
-
-       case 2:
-               pipe_reply.level = 2;
-               pipe_reply.status = NT_STATUS_OK;
-               pipe_reply.info.info2.file_type = state->file_type;
-               pipe_reply.info.info2.device_state = state->device_state;
-               pipe_reply.info.info2.allocation_size = state->alloc_size;
-
-               i3.client_name = pipe_request->info.info2.client_name;
-               i3.client_addr = pipe_request->info.info2.client_addr;
-               i3.client_port = pipe_request->info.info2.client_port;
-               i3.server_name = pipe_request->info.info2.server_name;
-               i3.server_addr = pipe_request->info.info2.server_addr;
-               i3.server_port = pipe_request->info.info2.server_port;
-               i3.sam_info3 = pipe_request->info.info2.sam_info3;
-               i3.session_key_length =
-                               pipe_request->info.info2.session_key_length;
-               i3.session_key = pipe_request->info.info2.session_key;
-               break;
-
-       case 3:
-               pipe_reply.level = 3;
-               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;
-
-               i3 = pipe_request->info.info3;
-               break;
+       ZERO_STRUCT(i4);
 
-       default:
+       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;
        }
 
-       if (pipe_reply.level >=2) {
-
-               if (i3.server_addr == NULL) {
-                       pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
-                       DEBUG(2, ("Missing server address\n"));
-                       goto reply;
-               }
-               if (i3.client_addr == NULL) {
-                       pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
-                       DEBUG(2, ("Missing client address\n"));
-                       goto reply;
-               }
+       pipe_reply.level = 4;
+       pipe_reply.status = NT_STATUS_OK;
+       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;
 
-               state->server_name = discard_const_p(char,
-                                       talloc_move(state, &i3.server_name));
-               ret = tsocket_address_inet_from_strings(state, "ip",
-                                                       i3.server_addr,
-                                                       i3.server_port,
-                                                       &state->server);
-               if (ret != 0) {
-                       DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
-                                 i3.server_addr, i3.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));
-               ret = tsocket_address_inet_from_strings(state, "ip",
-                                                       i3.client_addr,
-                                                       i3.client_port,
-                                                       &state->client);
-               if (ret != 0) {
-                       DEBUG(2, ("Invalid server address[%s:%u] - %s\n",
-                                 i3.client_addr, i3.client_port,
-                                 strerror(errno)));
-                       pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
-                       goto reply;
-               }
+       i4 = pipe_request->info.info4;
+       if (i4.local_server_addr == NULL) {
+               pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
+               DEBUG(2, ("Missing local server address\n"));
+               goto reply;
+       }
+       if (i4.remote_client_addr == NULL) {
+               pipe_reply.status = NT_STATUS_INVALID_ADDRESS;
+               DEBUG(2, ("Missing remote client address\n"));
+               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->local_server_name = discard_const_p(char,
+                                                  talloc_move(state,
+                                                              &i4.local_server_name));
+       ret = tsocket_address_inet_from_strings(state, "ip",
+                                               i4.local_server_addr,
+                                               i4.local_server_port,
+                                               &state->local_server_addr);
+       if (ret != 0) {
+               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;
        }
 
-       if (pipe_reply.level >= 3) {
-               state->delegated_creds.data =
-                       talloc_move(state, &i3.gssapi_delegated_creds);
-               state->delegated_creds.length =
-                       i3.gssapi_delegated_creds_length;
+       state->remote_client_name = discard_const_p(char,
+                                                   talloc_move(state,
+                                                               &i4.remote_client_name));
+       ret = tsocket_address_inet_from_strings(state, "ip",
+                                               i4.remote_client_addr,
+                                               i4.remote_client_port,
+                                               &state->remote_client_addr);
+       if (ret != 0) {
+               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->session_info = talloc_move(state, &i4.session_info);
 reply:
        /* create the output */
        ndr_err = ndr_push_struct_blob(&out, state, &pipe_reply,
@@ -1433,7 +1353,7 @@ reply:
 
        state->accept_status = pipe_reply.status;
 
-       state->out_iov.iov_base = out.data;
+       state->out_iov.iov_base = (char *) out.data;
        state->out_iov.iov_len = out.length;
 
        subreq = tstream_writev_send(state, state->ev,
@@ -1468,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 =
@@ -1519,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_move(mem_ctx, &state->session_key.data);
-       *delegated_creds = state->delegated_creds;
-       talloc_move(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;
+       }
+}