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 0 : 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 0 : struct libnetapi_private_ctx *priv_ctx;
69 172 : struct cli_state *cli_ipc = NULL;
70 0 : struct client_ipc_connection *p;
71 0 : NTSTATUS status;
72 172 : const char *username = NULL;
73 172 : const char *password = NULL;
74 0 : NET_API_STATUS rc;
75 0 : 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 87 : if (username != NULL && username[0] != '\0' &&
106 87 : 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 1025 : WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
144 : {
145 1025 : struct libnetapi_private_ctx *priv_ctx =
146 : (struct libnetapi_private_ctx *)ctx->private_data;
147 0 : struct client_ipc_connection *p;
148 :
149 1112 : for (p = priv_ctx->ipc_connections; p; p = p->next) {
150 87 : cli_shutdown(p->cli);
151 : }
152 :
153 1025 : 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 0 : struct client_pipe_connection *p;
164 :
165 172 : for (p = ipc->pipe_connections; p; p = p->next) {
166 0 : 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 0 : struct client_pipe_connection *p;
194 0 : 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 0 : NTSTATUS status;
238 0 : 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 0 : struct rpc_pipe_client *pipe_cli;
272 0 : 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 : }
|