LCOV - code coverage report
Current view: top level - source4/samba - service_named_pipe.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 51 85 60.0 %
Date: 2021-09-23 10:06:22 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    helper functions for NAMED PIPE servers
       5             : 
       6             :    Copyright (C) Stefan (metze) Metzmacher      2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include <tevent.h>
      24             : #include "samba/service.h"
      25             : #include "param/param.h"
      26             : #include "auth/auth.h"
      27             : #include "auth/session.h"
      28             : #include "auth/auth_sam_reply.h"
      29             : #include "lib/socket/socket.h"
      30             : #include "lib/tsocket/tsocket.h"
      31             : #include "libcli/util/tstream.h"
      32             : #include "librpc/gen_ndr/ndr_named_pipe_auth.h"
      33             : #include "system/passwd.h"
      34             : #include "system/network.h"
      35             : #include "libcli/raw/smb.h"
      36             : #include "auth/session.h"
      37             : #include "libcli/security/security.h"
      38             : #include "libcli/named_pipe_auth/npa_tstream.h"
      39             : 
      40             : struct named_pipe_socket {
      41             :         const char *pipe_name;
      42             :         const char *pipe_path;
      43             :         const struct stream_server_ops *ops;
      44             :         void *private_data;
      45             : };
      46             : 
      47             : static void named_pipe_accept_done(struct tevent_req *subreq);
      48             : 
      49        7018 : static void named_pipe_accept(struct stream_connection *conn)
      50             : {
      51             :         struct tstream_context *plain_tstream;
      52             :         int fd;
      53             :         struct tevent_req *subreq;
      54             :         int ret;
      55             : 
      56             :         /* Let tstream take over fd operations */
      57             : 
      58        7018 :         fd = socket_get_fd(conn->socket);
      59        7018 :         socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);
      60        7018 :         TALLOC_FREE(conn->event.fde);
      61        7018 :         TALLOC_FREE(conn->socket);
      62             : 
      63        7018 :         ret = tstream_bsd_existing_socket(conn, fd, &plain_tstream);
      64        7018 :         if (ret != 0) {
      65           0 :                 stream_terminate_connection(conn,
      66             :                                 "named_pipe_accept: out of memory");
      67           0 :                 return;
      68             :         }
      69             : 
      70        7018 :         subreq = tstream_npa_accept_existing_send(conn, conn->event.ctx,
      71             :                                                   plain_tstream,
      72             :                                                   FILE_TYPE_MESSAGE_MODE_PIPE,
      73             :                                                   0xff | 0x0400 | 0x0100,
      74             :                                                   4096);
      75        7018 :         if (subreq == NULL) {
      76           0 :                 stream_terminate_connection(conn,
      77             :                         "named_pipe_accept: "
      78             :                         "no memory for tstream_npa_accept_existing_send");
      79           0 :                 return;
      80             :         }
      81        7018 :         tevent_req_set_callback(subreq, named_pipe_accept_done, conn);
      82             : }
      83             : 
      84        7018 : static void named_pipe_accept_done(struct tevent_req *subreq)
      85             : {
      86        7018 :         struct stream_connection *conn = tevent_req_callback_data(subreq,
      87             :                                                 struct stream_connection);
      88        4857 :         struct named_pipe_socket *pipe_sock =
      89        7018 :                                 talloc_get_type(conn->private_data,
      90             :                                                 struct named_pipe_socket);
      91             :         struct tsocket_address *remote_client_addr;
      92             :         char *remote_client_name;
      93             :         struct tsocket_address *local_server_addr;
      94             :         char *local_server_name;
      95             :         struct auth_session_info_transport *session_info_transport;
      96        7018 :         const char *reason = NULL;
      97             :         TALLOC_CTX *tmp_ctx;
      98             :         int error;
      99             :         int ret;
     100             : 
     101        7018 :         tmp_ctx = talloc_new(conn);
     102        7018 :         if (!tmp_ctx) {
     103           0 :                 reason = "Out of memory!\n";
     104           0 :                 goto out;
     105             :         }
     106             : 
     107        7018 :         ret = tstream_npa_accept_existing_recv(subreq, &error, tmp_ctx,
     108             :                                                &conn->tstream,
     109             :                                                NULL,
     110             :                                                &remote_client_addr,
     111             :                                                &remote_client_name,
     112             :                                                &local_server_addr,
     113             :                                                &local_server_name,
     114             :                                                &session_info_transport);
     115        7018 :         TALLOC_FREE(subreq);
     116        7018 :         if (ret != 0) {
     117           0 :                 reason = talloc_asprintf(conn,
     118             :                                          "tstream_npa_accept_existing_recv()"
     119             :                                          " failed: %s", strerror(error));
     120           0 :                 goto out;
     121             :         }
     122             : 
     123        7018 :         conn->local_address = talloc_move(conn, &local_server_addr);
     124        7018 :         conn->remote_address = talloc_move(conn, &remote_client_addr);
     125             : 
     126        7018 :         DBG_DEBUG("Accepted npa connection from %s. "
     127             :                   "Client: %s (%s). Server: %s (%s)\n",
     128             :                   tsocket_address_string(conn->remote_address, tmp_ctx),
     129             :                   local_server_name,
     130             :                   tsocket_address_string(local_server_addr, tmp_ctx),
     131             :                   remote_client_name,
     132             :                   tsocket_address_string(remote_client_addr, tmp_ctx));
     133             : 
     134        7018 :         conn->session_info = auth_session_info_from_transport(conn, session_info_transport,
     135             :                                                               conn->lp_ctx,
     136             :                                                               &reason);
     137        7018 :         if (!conn->session_info) {
     138           0 :                 goto out;
     139             :         }
     140             : 
     141             :         /*
     142             :          * hand over to the real pipe implementation,
     143             :          * now that we have setup the transport session_info
     144             :          */
     145        7018 :         conn->ops = pipe_sock->ops;
     146        7018 :         conn->private_data = pipe_sock->private_data;
     147        7018 :         conn->ops->accept_connection(conn);
     148             : 
     149        7018 :         DBG_DEBUG("named pipe connection [%s] established\n", conn->ops->name);
     150             : 
     151        7018 :         talloc_free(tmp_ctx);
     152        7018 :         return;
     153             : 
     154           0 : out:
     155           0 :         talloc_free(tmp_ctx);
     156           0 :         if (!reason) {
     157           0 :                 reason = "Internal error";
     158             :         }
     159           0 :         stream_terminate_connection(conn, reason);
     160             : }
     161             : 
     162             : /*
     163             :   called when a pipe socket becomes readable
     164             : */
     165           0 : static void named_pipe_recv(struct stream_connection *conn, uint16_t flags)
     166             : {
     167           0 :         stream_terminate_connection(conn, "named_pipe_recv: called");
     168           0 : }
     169             : 
     170             : /*
     171             :   called when a pipe socket becomes writable
     172             : */
     173           0 : static void named_pipe_send(struct stream_connection *conn, uint16_t flags)
     174             : {
     175           0 :         stream_terminate_connection(conn, "named_pipe_send: called");
     176           0 : }
     177             : 
     178             : static const struct stream_server_ops named_pipe_stream_ops = {
     179             :         .name                   = "named_pipe",
     180             :         .accept_connection      = named_pipe_accept,
     181             :         .recv_handler           = named_pipe_recv,
     182             :         .send_handler           = named_pipe_send,
     183             : };
     184             : 
     185         840 : NTSTATUS tstream_setup_named_pipe(TALLOC_CTX *mem_ctx,
     186             :                                   struct tevent_context *event_context,
     187             :                                   struct loadparm_context *lp_ctx,
     188             :                                   const struct model_ops *model_ops,
     189             :                                   const struct stream_server_ops *stream_ops,
     190             :                                   const char *pipe_name,
     191             :                                   void *private_data,
     192             :                                   void *process_context)
     193             : {
     194             :         char *dirname;
     195             :         struct named_pipe_socket *pipe_sock;
     196         840 :         NTSTATUS status = NT_STATUS_NO_MEMORY;;
     197             : 
     198         840 :         pipe_sock = talloc(mem_ctx, struct named_pipe_socket);
     199         840 :         if (pipe_sock == NULL) {
     200           0 :                 goto fail;
     201             :         }
     202             : 
     203             :         /* remember the details about the pipe */
     204         840 :         pipe_sock->pipe_name = strlower_talloc(pipe_sock, pipe_name);
     205         840 :         if (pipe_sock->pipe_name == NULL) {
     206           0 :                 goto fail;
     207             :         }
     208             : 
     209         840 :         if (!directory_create_or_exist(lpcfg_ncalrpc_dir(lp_ctx), 0755)) {
     210           0 :                 status = map_nt_error_from_unix_common(errno);
     211           0 :                 DBG_ERR("Failed to create ncalrpc pipe directory '%s' - %s\n",
     212             :                         lpcfg_ncalrpc_dir(lp_ctx), nt_errstr(status));
     213           0 :                 goto fail;
     214             :         }
     215             : 
     216         840 :         dirname = talloc_asprintf(pipe_sock, "%s/np", lpcfg_ncalrpc_dir(lp_ctx));
     217         840 :         if (dirname == NULL) {
     218           0 :                 goto fail;
     219             :         }
     220             : 
     221         840 :         if (!directory_create_or_exist_strict(dirname, geteuid(), 0700)) {
     222           0 :                 status = map_nt_error_from_unix_common(errno);
     223           0 :                 DBG_ERR("Failed to create stream pipe directory '%s' - %s\n",
     224             :                         dirname, nt_errstr(status));
     225           0 :                 goto fail;
     226             :         }
     227             : 
     228         840 :         if (strncmp(pipe_name, "\\pipe\\", 6) == 0) {
     229         840 :                 pipe_name += 6;
     230             :         }
     231             : 
     232         840 :         pipe_sock->pipe_path = talloc_asprintf(pipe_sock, "%s/%s", dirname,
     233             :                                                pipe_name);
     234         840 :         if (pipe_sock->pipe_path == NULL) {
     235           0 :                 goto fail;
     236             :         }
     237             : 
     238         840 :         talloc_free(dirname);
     239             : 
     240         840 :         pipe_sock->ops = stream_ops;
     241         840 :         pipe_sock->private_data      = private_data;
     242             : 
     243         840 :         status = stream_setup_socket(pipe_sock,
     244             :                                      event_context,
     245             :                                      lp_ctx,
     246             :                                      model_ops,
     247             :                                      &named_pipe_stream_ops,
     248             :                                      "unix",
     249             :                                      pipe_sock->pipe_path,
     250             :                                      NULL,
     251             :                                      NULL,
     252             :                                      pipe_sock,
     253             :                                      process_context);
     254         840 :         if (!NT_STATUS_IS_OK(status)) {
     255           0 :                 goto fail;
     256             :         }
     257         840 :         return NT_STATUS_OK;
     258             : 
     259           0 :  fail:
     260           0 :         talloc_free(pipe_sock);
     261           0 :         return status;
     262             : }

Generated by: LCOV version 1.13