LCOV - code coverage report
Current view: top level - source3/lib/netapi - cm.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 75 94 79.8 %
Date: 2021-09-23 10:06:22 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  NetApi Support
       4             :  *  Copyright (C) Guenther Deschner 2008
       5             :  *
       6             :  *  This program is free software; you can redistribute it and/or modify
       7             :  *  it under the terms of the GNU General Public License as published by
       8             :  *  the Free Software Foundation; either version 3 of the License, or
       9             :  *  (at your option) any later version.
      10             :  *
      11             :  *  This program is distributed in the hope that it will be useful,
      12             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  *  GNU General Public License for more details.
      15             :  *
      16             :  *  You should have received a copy of the GNU General Public License
      17             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : 
      22             : #include "lib/netapi/netapi.h"
      23             : #include "lib/netapi/netapi_private.h"
      24             : #include "libsmb/libsmb.h"
      25             : #include "rpc_client/cli_pipe.h"
      26             : #include "../libcli/smb/smbXcli_base.h"
      27             : 
      28             : /********************************************************************
      29             : ********************************************************************/
      30             : 
      31             : struct client_ipc_connection {
      32             :         struct client_ipc_connection *prev, *next;
      33             :         struct cli_state *cli;
      34             :         struct client_pipe_connection *pipe_connections;
      35             : };
      36             : 
      37             : struct client_pipe_connection {
      38             :         struct client_pipe_connection *prev, *next;
      39             :         struct rpc_pipe_client *pipe;
      40             : };
      41             : 
      42             : /********************************************************************
      43             : ********************************************************************/
      44             : 
      45         172 : static struct client_ipc_connection *ipc_cm_find(
      46             :         struct libnetapi_private_ctx *priv_ctx, const char *server_name)
      47             : {
      48             :         struct client_ipc_connection *p;
      49             : 
      50         172 :         for (p = priv_ctx->ipc_connections; p; p = p->next) {
      51          85 :                 const char *remote_name = smbXcli_conn_remote_name(p->cli->conn);
      52             : 
      53          85 :                 if (strequal(remote_name, server_name)) {
      54          85 :                         return p;
      55             :                 }
      56             :         }
      57             : 
      58          87 :         return NULL;
      59             : }
      60             : 
      61             : /********************************************************************
      62             : ********************************************************************/
      63             : 
      64         172 : static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
      65             :                                             const char *server_name,
      66             :                                             struct client_ipc_connection **pp)
      67             : {
      68             :         struct libnetapi_private_ctx *priv_ctx;
      69         172 :         struct cli_state *cli_ipc = NULL;
      70             :         struct client_ipc_connection *p;
      71             :         NTSTATUS status;
      72         172 :         const char *username = NULL;
      73         172 :         const char *password = NULL;
      74             :         NET_API_STATUS rc;
      75             :         enum credentials_use_kerberos krb5_state;
      76             : 
      77         172 :         if (!ctx || !pp || !server_name) {
      78           0 :                 return WERR_INVALID_PARAMETER;
      79             :         }
      80             : 
      81         172 :         priv_ctx = (struct libnetapi_private_ctx *)ctx->private_data;
      82             : 
      83         172 :         p = ipc_cm_find(priv_ctx, server_name);
      84         172 :         if (p) {
      85          85 :                 *pp = p;
      86          85 :                 return WERR_OK;
      87             :         }
      88             : 
      89          87 :         rc = libnetapi_get_username(ctx, &username);
      90          87 :         if (rc != 0) {
      91           0 :                 return WERR_INTERNAL_ERROR;
      92             :         }
      93             : 
      94          87 :         rc = libnetapi_get_password(ctx, &password);
      95          87 :         if (rc != 0) {
      96           0 :                 return WERR_INTERNAL_ERROR;
      97             :         }
      98             : 
      99          87 :         if (password == NULL) {
     100           0 :                 cli_credentials_set_cmdline_callbacks(ctx->creds);
     101             :         }
     102             : 
     103          87 :         krb5_state = cli_credentials_get_kerberos_state(ctx->creds);
     104             : 
     105         132 :         if (username != NULL && username[0] != '\0' &&
     106         132 :             password != NULL && password[0] != '\0' &&
     107             :             krb5_state == CRED_USE_KERBEROS_REQUIRED) {
     108           0 :                 cli_credentials_set_kerberos_state(ctx->creds,
     109             :                                                    CRED_USE_KERBEROS_DESIRED,
     110             :                                                    CRED_SPECIFIED);
     111             :         }
     112             : 
     113          87 :         status = cli_cm_open(ctx, NULL,
     114             :                              server_name, "IPC$",
     115             :                              ctx->creds,
     116             :                              NULL, 0, 0x20, &cli_ipc);
     117          87 :         if (!NT_STATUS_IS_OK(status)) {
     118           0 :                 cli_ipc = NULL;
     119             :         }
     120             : 
     121          87 :         if (!cli_ipc) {
     122           0 :                 libnetapi_set_error_string(ctx,
     123             :                         "Failed to connect to IPC$ share on %s", server_name);
     124           0 :                 return WERR_CAN_NOT_COMPLETE;
     125             :         }
     126             : 
     127          87 :         p = talloc_zero(ctx, struct client_ipc_connection);
     128          87 :         if (p == NULL) {
     129           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     130             :         }
     131             : 
     132          87 :         p->cli = cli_ipc;
     133          87 :         DLIST_ADD(priv_ctx->ipc_connections, p);
     134             : 
     135          87 :         *pp = p;
     136             : 
     137          87 :         return WERR_OK;
     138             : }
     139             : 
     140             : /********************************************************************
     141             : ********************************************************************/
     142             : 
     143         987 : WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
     144             : {
     145         987 :         struct libnetapi_private_ctx *priv_ctx =
     146             :                 (struct libnetapi_private_ctx *)ctx->private_data;
     147             :         struct client_ipc_connection *p;
     148             : 
     149        1074 :         for (p = priv_ctx->ipc_connections; p; p = p->next) {
     150          87 :                 cli_shutdown(p->cli);
     151             :         }
     152             : 
     153         987 :         return WERR_OK;
     154             : }
     155             : 
     156             : /********************************************************************
     157             : ********************************************************************/
     158             : 
     159         172 : static NTSTATUS pipe_cm_find(struct client_ipc_connection *ipc,
     160             :                              const struct ndr_interface_table *table,
     161             :                              struct rpc_pipe_client **presult)
     162             : {
     163             :         struct client_pipe_connection *p;
     164             : 
     165         172 :         for (p = ipc->pipe_connections; p; p = p->next) {
     166             :                 const char *ipc_remote_name;
     167             : 
     168          85 :                 if (!rpccli_is_connected(p->pipe)) {
     169           0 :                         return NT_STATUS_PIPE_EMPTY;
     170             :                 }
     171             : 
     172          85 :                 ipc_remote_name = smbXcli_conn_remote_name(ipc->cli->conn);
     173             : 
     174          85 :                 if (strequal(ipc_remote_name, p->pipe->desthost)
     175          85 :                     && ndr_syntax_id_equal(&p->pipe->abstract_syntax,
     176             :                                            &table->syntax_id)) {
     177          85 :                         *presult = p->pipe;
     178          85 :                         return NT_STATUS_OK;
     179             :                 }
     180             :         }
     181             : 
     182          87 :         return NT_STATUS_PIPE_NOT_AVAILABLE;
     183             : }
     184             : 
     185             : /********************************************************************
     186             : ********************************************************************/
     187             : 
     188          87 : static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
     189             :                                 struct client_ipc_connection *ipc,
     190             :                                 const struct ndr_interface_table *table,
     191             :                                 struct rpc_pipe_client **presult)
     192             : {
     193             :         struct client_pipe_connection *p;
     194             :         NTSTATUS status;
     195             : 
     196          87 :         p = talloc_zero_array(mem_ctx, struct client_pipe_connection, 1);
     197          87 :         if (!p) {
     198           0 :                 return NT_STATUS_NO_MEMORY;
     199             :         }
     200             : 
     201          87 :         status = cli_rpc_pipe_open_noauth(ipc->cli, table, &p->pipe);
     202          87 :         if (!NT_STATUS_IS_OK(status)) {
     203           0 :                 TALLOC_FREE(p);
     204           0 :                 return status;
     205             :         }
     206             : 
     207          87 :         DLIST_ADD(ipc->pipe_connections, p);
     208             : 
     209          87 :         *presult = p->pipe;
     210          87 :         return NT_STATUS_OK;
     211             : }
     212             : 
     213             : /********************************************************************
     214             : ********************************************************************/
     215             : 
     216         172 : static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx,
     217             :                              struct client_ipc_connection *ipc,
     218             :                              const struct ndr_interface_table *table,
     219             :                              struct rpc_pipe_client **presult)
     220             : {
     221         172 :         if (NT_STATUS_IS_OK(pipe_cm_find(ipc, table, presult))) {
     222          85 :                 return NT_STATUS_OK;
     223             :         }
     224             : 
     225          87 :         return pipe_cm_connect(ctx, ipc, table, presult);
     226             : }
     227             : 
     228             : /********************************************************************
     229             : ********************************************************************/
     230             : 
     231         172 : WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
     232             :                            const char *server_name,
     233             :                            const struct ndr_interface_table *table,
     234             :                            struct rpc_pipe_client **presult)
     235             : {
     236         172 :         struct rpc_pipe_client *result = NULL;
     237             :         NTSTATUS status;
     238             :         WERROR werr;
     239         172 :         struct client_ipc_connection *ipc = NULL;
     240             : 
     241         172 :         if (!presult) {
     242           0 :                 return WERR_INVALID_PARAMETER;
     243             :         }
     244             : 
     245         172 :         werr = libnetapi_open_ipc_connection(ctx, server_name, &ipc);
     246         172 :         if (!W_ERROR_IS_OK(werr)) {
     247           0 :                 return werr;
     248             :         }
     249             : 
     250         172 :         status = pipe_cm_open(ctx, ipc, table, &result);
     251         172 :         if (!NT_STATUS_IS_OK(status)) {
     252           0 :                 libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s",
     253           0 :                         table->name,
     254             :                         get_friendly_nt_error_msg(status));
     255           0 :                 return WERR_NERR_DESTNOTFOUND;
     256             :         }
     257             : 
     258         172 :         *presult = result;
     259             : 
     260         172 :         return WERR_OK;
     261             : }
     262             : 
     263             : /********************************************************************
     264             : ********************************************************************/
     265             : 
     266          15 : WERROR libnetapi_get_binding_handle(struct libnetapi_ctx *ctx,
     267             :                                     const char *server_name,
     268             :                                     const struct ndr_interface_table *table,
     269             :                                     struct dcerpc_binding_handle **binding_handle)
     270             : {
     271             :         struct rpc_pipe_client *pipe_cli;
     272             :         WERROR result;
     273             : 
     274          15 :         *binding_handle = NULL;
     275             : 
     276          15 :         result = libnetapi_open_pipe(ctx, server_name, table, &pipe_cli);
     277          15 :         if (!W_ERROR_IS_OK(result)) {
     278           0 :                 return result;
     279             :         }
     280             : 
     281          15 :         *binding_handle = pipe_cli->binding_handle;
     282             : 
     283          15 :         return WERR_OK;
     284             : }

Generated by: LCOV version 1.13