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