ldb: Free memory when repacking database
[garming/samba-autobuild/.git] / source3 / lib / netapi / cm.c
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 #include "auth_info.h"
22
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "libsmb/libsmb.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "../libcli/smb/smbXcli_base.h"
28
29 /********************************************************************
30 ********************************************************************/
31
32 struct client_ipc_connection {
33         struct client_ipc_connection *prev, *next;
34         struct cli_state *cli;
35         struct client_pipe_connection *pipe_connections;
36 };
37
38 struct client_pipe_connection {
39         struct client_pipe_connection *prev, *next;
40         struct rpc_pipe_client *pipe;
41 };
42
43 /********************************************************************
44 ********************************************************************/
45
46 static struct client_ipc_connection *ipc_cm_find(
47         struct libnetapi_private_ctx *priv_ctx, const char *server_name)
48 {
49         struct client_ipc_connection *p;
50
51         for (p = priv_ctx->ipc_connections; p; p = p->next) {
52                 const char *remote_name = smbXcli_conn_remote_name(p->cli->conn);
53
54                 if (strequal(remote_name, server_name)) {
55                         return p;
56                 }
57         }
58
59         return NULL;
60 }
61
62 /********************************************************************
63 ********************************************************************/
64
65 static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
66                                             const char *server_name,
67                                             struct client_ipc_connection **pp)
68 {
69         struct libnetapi_private_ctx *priv_ctx;
70         struct user_auth_info *auth_info = NULL;
71         struct cli_state *cli_ipc = NULL;
72         struct client_ipc_connection *p;
73         NTSTATUS status;
74
75         if (!ctx || !pp || !server_name) {
76                 return WERR_INVALID_PARAMETER;
77         }
78
79         priv_ctx = (struct libnetapi_private_ctx *)ctx->private_data;
80
81         p = ipc_cm_find(priv_ctx, server_name);
82         if (p) {
83                 *pp = p;
84                 return WERR_OK;
85         }
86
87         auth_info = user_auth_info_init(ctx);
88         if (!auth_info) {
89                 return WERR_NOT_ENOUGH_MEMORY;
90         }
91         set_cmdline_auth_info_signing_state_raw(auth_info, SMB_SIGNING_IPC_DEFAULT);
92         set_cmdline_auth_info_use_kerberos(auth_info, ctx->use_kerberos);
93         set_cmdline_auth_info_username(auth_info, ctx->username);
94         if (ctx->password) {
95                 set_cmdline_auth_info_password(auth_info, ctx->password);
96         } else {
97                 set_cmdline_auth_info_getpass(auth_info);
98         }
99
100         if (ctx->username && ctx->username[0] &&
101             ctx->password && ctx->password[0] &&
102             ctx->use_kerberos) {
103                 set_cmdline_auth_info_fallback_after_kerberos(auth_info, true);
104         }
105
106         if (ctx->use_ccache) {
107                 set_cmdline_auth_info_use_ccache(auth_info, true);
108         }
109
110         status = cli_cm_open(ctx, NULL,
111                              server_name, "IPC$",
112                              auth_info,
113                              false,
114                              lp_client_ipc_max_protocol(),
115                              0, 0x20, &cli_ipc);
116         if (!NT_STATUS_IS_OK(status)) {
117                 cli_ipc = NULL;
118         }
119         TALLOC_FREE(auth_info);
120
121         if (!cli_ipc) {
122                 libnetapi_set_error_string(ctx,
123                         "Failed to connect to IPC$ share on %s", server_name);
124                 return WERR_CAN_NOT_COMPLETE;
125         }
126
127         p = talloc_zero(ctx, struct client_ipc_connection);
128         if (p == NULL) {
129                 return WERR_NOT_ENOUGH_MEMORY;
130         }
131
132         p->cli = cli_ipc;
133         DLIST_ADD(priv_ctx->ipc_connections, p);
134
135         *pp = p;
136
137         return WERR_OK;
138 }
139
140 /********************************************************************
141 ********************************************************************/
142
143 WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
144 {
145         struct libnetapi_private_ctx *priv_ctx =
146                 (struct libnetapi_private_ctx *)ctx->private_data;
147         struct client_ipc_connection *p;
148
149         for (p = priv_ctx->ipc_connections; p; p = p->next) {
150                 cli_shutdown(p->cli);
151         }
152
153         return WERR_OK;
154 }
155
156 /********************************************************************
157 ********************************************************************/
158
159 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         for (p = ipc->pipe_connections; p; p = p->next) {
166                 const char *ipc_remote_name;
167
168                 if (!rpccli_is_connected(p->pipe)) {
169                         return NT_STATUS_PIPE_EMPTY;
170                 }
171
172                 ipc_remote_name = smbXcli_conn_remote_name(ipc->cli->conn);
173
174                 if (strequal(ipc_remote_name, p->pipe->desthost)
175                     && ndr_syntax_id_equal(&p->pipe->abstract_syntax,
176                                            &table->syntax_id)) {
177                         *presult = p->pipe;
178                         return NT_STATUS_OK;
179                 }
180         }
181
182         return NT_STATUS_PIPE_NOT_AVAILABLE;
183 }
184
185 /********************************************************************
186 ********************************************************************/
187
188 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         p = talloc_zero_array(mem_ctx, struct client_pipe_connection, 1);
197         if (!p) {
198                 return NT_STATUS_NO_MEMORY;
199         }
200
201         status = cli_rpc_pipe_open_noauth(ipc->cli, table, &p->pipe);
202         if (!NT_STATUS_IS_OK(status)) {
203                 TALLOC_FREE(p);
204                 return status;
205         }
206
207         DLIST_ADD(ipc->pipe_connections, p);
208
209         *presult = p->pipe;
210         return NT_STATUS_OK;
211 }
212
213 /********************************************************************
214 ********************************************************************/
215
216 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         if (NT_STATUS_IS_OK(pipe_cm_find(ipc, table, presult))) {
222                 return NT_STATUS_OK;
223         }
224
225         return pipe_cm_connect(ctx, ipc, table, presult);
226 }
227
228 /********************************************************************
229 ********************************************************************/
230
231 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         struct rpc_pipe_client *result = NULL;
237         NTSTATUS status;
238         WERROR werr;
239         struct client_ipc_connection *ipc = NULL;
240
241         if (!presult) {
242                 return WERR_INVALID_PARAMETER;
243         }
244
245         werr = libnetapi_open_ipc_connection(ctx, server_name, &ipc);
246         if (!W_ERROR_IS_OK(werr)) {
247                 return werr;
248         }
249
250         status = pipe_cm_open(ctx, ipc, table, &result);
251         if (!NT_STATUS_IS_OK(status)) {
252                 libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s",
253                         table->name,
254                         get_friendly_nt_error_msg(status));
255                 return WERR_NERR_DESTNOTFOUND;
256         }
257
258         *presult = result;
259
260         return WERR_OK;
261 }
262
263 /********************************************************************
264 ********************************************************************/
265
266 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         *binding_handle = NULL;
275
276         result = libnetapi_open_pipe(ctx, server_name, table, &pipe_cli);
277         if (!W_ERROR_IS_OK(result)) {
278                 return result;
279         }
280
281         *binding_handle = pipe_cli->binding_handle;
282
283         return WERR_OK;
284 }