s3-popt: Only include popt-common.h when needed.
[amitay/samba.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 "popt_common.h"
22
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25
26 /********************************************************************
27 ********************************************************************/
28
29 static WERROR libnetapi_open_ipc_connection(struct libnetapi_ctx *ctx,
30                                             const char *server_name,
31                                             struct cli_state **cli)
32 {
33         struct user_auth_info *auth_info = NULL;
34         struct cli_state *cli_ipc = NULL;
35
36         if (!ctx || !cli || !server_name) {
37                 return WERR_INVALID_PARAM;
38         }
39
40         auth_info = user_auth_info_init(NULL);
41         if (!auth_info) {
42                 return WERR_NOMEM;
43         }
44         auth_info->signing_state = Undefined;
45         set_cmdline_auth_info_use_kerberos(auth_info, ctx->use_kerberos);
46         set_cmdline_auth_info_username(auth_info, ctx->username);
47         if (ctx->password) {
48                 set_cmdline_auth_info_password(auth_info, ctx->password);
49         } else {
50                 set_cmdline_auth_info_getpass(auth_info);
51         }
52
53         if (ctx->username && ctx->username[0] &&
54             ctx->password && ctx->password[0] &&
55             ctx->use_kerberos) {
56                 set_cmdline_auth_info_fallback_after_kerberos(auth_info, true);
57         }
58
59         if (ctx->use_ccache) {
60                 set_cmdline_auth_info_use_ccache(auth_info, true);
61         }
62
63         cli_ipc = cli_cm_open(ctx, NULL,
64                                 server_name, "IPC$",
65                                 auth_info,
66                                 false, false,
67                                 PROTOCOL_NT1,
68                                 0, 0x20);
69         if (cli_ipc) {
70                 cli_set_username(cli_ipc, ctx->username);
71                 cli_set_password(cli_ipc, ctx->password);
72                 cli_set_domain(cli_ipc, ctx->workgroup);
73         }
74         TALLOC_FREE(auth_info);
75
76         if (!cli_ipc) {
77                 libnetapi_set_error_string(ctx,
78                         "Failed to connect to IPC$ share on %s", server_name);
79                 return WERR_CAN_NOT_COMPLETE;
80         }
81
82         *cli = cli_ipc;
83
84         return WERR_OK;
85 }
86
87 /********************************************************************
88 ********************************************************************/
89
90 struct client_pipe_connection {
91         struct client_pipe_connection *prev, *next;
92         struct rpc_pipe_client *pipe;
93         struct cli_state *cli;
94 };
95
96 static struct client_pipe_connection *pipe_connections;
97
98 /********************************************************************
99 ********************************************************************/
100
101 WERROR libnetapi_shutdown_cm(struct libnetapi_ctx *ctx)
102 {
103         struct client_pipe_connection *p;
104
105         for (p = pipe_connections; p; p = p->next) {
106                 cli_shutdown(p->cli);
107         }
108
109         return WERR_OK;
110 }
111
112 /********************************************************************
113 ********************************************************************/
114
115 static NTSTATUS pipe_cm_find(struct cli_state *cli,
116                              const struct ndr_syntax_id *interface,
117                              struct rpc_pipe_client **presult)
118 {
119         struct client_pipe_connection *p;
120
121         for (p = pipe_connections; p; p = p->next) {
122
123                 if (!rpc_pipe_np_smb_conn(p->pipe)) {
124                         return NT_STATUS_PIPE_EMPTY;
125                 }
126
127                 if (strequal(cli->desthost, p->pipe->desthost)
128                     && ndr_syntax_id_equal(&p->pipe->abstract_syntax,
129                                            interface)) {
130                         *presult = p->pipe;
131                         return NT_STATUS_OK;
132                 }
133         }
134
135         return NT_STATUS_PIPE_NOT_AVAILABLE;
136 }
137
138 /********************************************************************
139 ********************************************************************/
140
141 static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
142                                 struct cli_state *cli,
143                                 const struct ndr_syntax_id *interface,
144                                 struct rpc_pipe_client **presult)
145 {
146         struct client_pipe_connection *p;
147         NTSTATUS status;
148
149         p = TALLOC_ZERO_ARRAY(mem_ctx, struct client_pipe_connection, 1);
150         if (!p) {
151                 return NT_STATUS_NO_MEMORY;
152         }
153
154         status = cli_rpc_pipe_open_noauth(cli, interface, &p->pipe);
155         if (!NT_STATUS_IS_OK(status)) {
156                 TALLOC_FREE(p);
157                 return status;
158         }
159
160         p->cli = cli;
161         DLIST_ADD(pipe_connections, p);
162
163         *presult = p->pipe;
164         return NT_STATUS_OK;
165 }
166
167 /********************************************************************
168 ********************************************************************/
169
170 static NTSTATUS pipe_cm_open(TALLOC_CTX *ctx,
171                              struct cli_state *cli,
172                              const struct ndr_syntax_id *interface,
173                              struct rpc_pipe_client **presult)
174 {
175         if (NT_STATUS_IS_OK(pipe_cm_find(cli, interface, presult))) {
176                 return NT_STATUS_OK;
177         }
178
179         return pipe_cm_connect(ctx, cli, interface, presult);
180 }
181
182 /********************************************************************
183 ********************************************************************/
184
185 WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx,
186                            const char *server_name,
187                            const struct ndr_syntax_id *interface,
188                            struct rpc_pipe_client **presult)
189 {
190         struct rpc_pipe_client *result = NULL;
191         NTSTATUS status;
192         WERROR werr;
193         struct cli_state *cli = NULL;
194
195         if (!presult) {
196                 return WERR_INVALID_PARAM;
197         }
198
199         werr = libnetapi_open_ipc_connection(ctx, server_name, &cli);
200         if (!W_ERROR_IS_OK(werr)) {
201                 return werr;
202         }
203
204         status = pipe_cm_open(ctx, cli, interface, &result);
205         if (!NT_STATUS_IS_OK(status)) {
206                 libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s",
207                         get_pipe_name_from_syntax(talloc_tos(), interface),
208                         get_friendly_nt_error_msg(status));
209                 return WERR_DEST_NOT_FOUND;
210         }
211
212         *presult = result;
213
214         return WERR_OK;
215 }