r10683: Samba3's wbinfo -t should give the correct answer now.
[jelmer/samba4-debian.git] / source / winbind / wb_samba3_cmd.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main winbindd samba3 server routines
4
5    Copyright (C) Stefan Metzmacher      2005
6    Copyright (C) Volker Lendecke        2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "smbd/service_stream.h"
25 #include "nsswitch/winbind_nss_config.h"
26 #include "nsswitch/winbindd_nss.h"
27 #include "winbind/wb_server.h"
28 #include "winbind/wb_samba3_protocol.h"
29 #include "winbind/wb_async_helpers.h"
30 #include "librpc/gen_ndr/nbt.h"
31 #include "libcli/raw/libcliraw.h"
32 #include "libcli/composite/composite.h"
33 #include "libcli/smb_composite/smb_composite.h"
34 #include "include/version.h"
35 #include "librpc/rpc/dcerpc_composite.h"
36 #include "lib/events/events.h"
37
38 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
39 {
40         s3call->response.result                 = WINBINDD_OK;
41         s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
42         return NT_STATUS_OK;
43 }
44
45 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
46 {
47         s3call->response.result                 = WINBINDD_OK;
48         s3call->response.data.info.winbind_separator = *lp_winbind_separator();
49         WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version, SAMBA_VERSION_STRING);
50         return NT_STATUS_OK;
51 }
52
53 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
54 {
55         s3call->response.result                 = WINBINDD_OK;
56         WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name, lp_workgroup());
57         return NT_STATUS_OK;
58 }
59
60 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
61 {
62         s3call->response.result                 = WINBINDD_OK;
63         WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name, lp_netbios_name());
64         return NT_STATUS_OK;
65 }
66
67 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
68 {
69         s3call->response.result                 = WINBINDD_OK;
70         s3call->response.extra_data             = smbd_tmp_path(s3call,
71                                                   WINBINDD_SAMBA3_PRIVILEGED_SOCKET);
72         NT_STATUS_HAVE_NO_MEMORY(s3call->response.extra_data);
73         return NT_STATUS_OK;
74 }
75
76 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
77 {
78         s3call->response.result                 = WINBINDD_OK;
79         return NT_STATUS_OK;
80 }
81
82 #define null_no_memory_done(x) do { \
83         if ((x) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } \
84         } while (0)
85
86 struct check_machacc_state {
87         struct wb_finddcs *io;
88         struct smb_composite_connect *conn;
89         struct wb_get_schannel_creds *getcreds;
90 };
91
92 static void wbsrv_samba3_check_machacc_receive_creds(struct composite_context *action);
93 static void wbsrv_samba3_check_machacc_receive_tree(struct composite_context *action);
94 static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *action);
95
96 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
97 {
98         struct composite_context *resolve_req;
99         struct check_machacc_state *state;
100         struct wbsrv_service *service =
101                 s3call->call->wbconn->listen_socket->service;
102
103         DEBUG(5, ("check_machacc called\n"));
104
105         if (service->netlogon != NULL) {
106                 talloc_free(service->netlogon);
107         }
108
109         state = talloc(s3call, struct check_machacc_state);
110         NT_STATUS_HAVE_NO_MEMORY(state);
111
112         state->io = talloc(s3call, struct wb_finddcs);
113         NT_STATUS_HAVE_NO_MEMORY(state->io);
114         s3call->private_data = state;
115
116         state->io->in.msg_ctx = s3call->call->wbconn->conn->msg_ctx;
117         state->io->in.domain = lp_workgroup();
118
119         resolve_req = wb_finddcs_send(state->io, s3call->call->event_ctx);
120         NT_STATUS_HAVE_NO_MEMORY(resolve_req);
121
122         /* setup the callbacks */
123         resolve_req->async.fn = wbsrv_samba3_check_machacc_receive_dcs;
124         resolve_req->async.private_data = s3call;
125
126         /* tell the caller we reply later */
127         s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
128         return NT_STATUS_OK;
129 }
130
131 static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *action)
132 {
133         struct wbsrv_samba3_call *s3call =
134                 talloc_get_type(action->async.private_data,
135                                 struct wbsrv_samba3_call);
136         struct check_machacc_state *state =
137                 talloc_get_type(s3call->private_data,
138                                 struct check_machacc_state);
139         struct composite_context *ctx;
140         NTSTATUS status;
141
142         status = wb_finddcs_recv(action, s3call);
143
144         s3call->response.data.auth.nt_status = NT_STATUS_V(status);
145         WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
146                                 nt_errstr(status));
147         WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
148                                 nt_errstr(status));
149         s3call->response.data.auth.pam_error = nt_status_to_pam(status);
150
151         if (!NT_STATUS_IS_OK(status)) {
152                 goto done;
153         }
154
155         state->conn = talloc(state, struct smb_composite_connect);
156         if (state->conn == NULL) {
157                 status = NT_STATUS_NO_MEMORY;
158                 goto done;
159         }
160
161         state->conn->in.dest_host = state->io->out.dcs[0].address;
162         state->conn->in.port = 0;
163         state->conn->in.called_name = state->io->out.dcs[0].name;
164         state->conn->in.service = "IPC$";
165         state->conn->in.service_type = "IPC";
166         state->conn->in.workgroup = lp_workgroup();
167
168         state->conn->in.credentials = cli_credentials_init(state->conn);
169         if (state->conn->in.credentials == NULL) {
170                 status = NT_STATUS_NO_MEMORY;
171                 goto done;
172         }
173         cli_credentials_set_conf(state->conn->in.credentials);
174         cli_credentials_set_anonymous(state->conn->in.credentials);
175
176         ctx = smb_composite_connect_send(state->conn, state,
177                                          s3call->call->event_ctx);
178         if (ctx == NULL) {
179                 status = NT_STATUS_NO_MEMORY;
180                 goto done;
181         }
182
183         ctx->async.fn = wbsrv_samba3_check_machacc_receive_tree;
184         ctx->async.private_data = s3call;
185         return;
186
187  done:
188         if (!NT_STATUS_IS_OK(status)) {
189                 s3call->response.result = WINBINDD_ERROR;
190         }
191
192         status = wbsrv_send_reply(s3call->call);
193         if (!NT_STATUS_IS_OK(status)) {
194                 wbsrv_terminate_connection(s3call->call->wbconn,
195                                            "wbsrv_queue_reply() failed");
196                 return;
197         }
198 }
199
200 static void wbsrv_samba3_check_machacc_receive_tree(struct composite_context *action)
201 {
202         struct wbsrv_samba3_call *s3call =
203                 talloc_get_type(action->async.private_data,
204                                 struct wbsrv_samba3_call);
205         struct check_machacc_state *state =
206                 talloc_get_type(s3call->private_data,
207                                 struct check_machacc_state);
208         struct composite_context *ctx;
209         NTSTATUS status;
210         struct cli_credentials *creds;
211
212         status = smb_composite_connect_recv(action, state);
213         if (!NT_STATUS_IS_OK(status)) {
214                 DEBUG(5, ("Connect failed: %s\n", nt_errstr(status)));
215                 goto done;
216         }
217
218         state->getcreds = talloc(state, struct wb_get_schannel_creds);
219         null_no_memory_done(state->getcreds);
220
221         creds = cli_credentials_init(state);
222         null_no_memory_done(creds);
223         cli_credentials_set_conf(creds);
224         status = cli_credentials_set_machine_account(creds);
225         if (!NT_STATUS_IS_OK(status)) goto done;
226
227         state->getcreds->in.tree = state->conn->out.tree;
228         state->getcreds->in.creds = creds;
229
230         ctx = wb_get_schannel_creds_send(state->getcreds,
231                                          s3call->call->event_ctx);
232         null_no_memory_done(ctx);
233
234         ctx->async.fn = wbsrv_samba3_check_machacc_receive_creds;
235         ctx->async.private_data = s3call;
236
237         return;
238         
239  done:
240         s3call->response.result = WINBINDD_OK;
241
242         if (!NT_STATUS_IS_OK(status)) {
243                 s3call->response.result = WINBINDD_ERROR;
244                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
245                                         nt_errstr(status));
246                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
247                                         nt_errstr(status));
248                 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
249
250         }
251
252         status = wbsrv_send_reply(s3call->call);
253         if (!NT_STATUS_IS_OK(status)) {
254                 wbsrv_terminate_connection(s3call->call->wbconn,
255                                            "wbsrv_queue_reply() failed");
256                 return;
257         }
258 }
259
260 static void wbsrv_samba3_check_machacc_receive_creds(struct composite_context *action)
261 {
262         struct wbsrv_samba3_call *s3call =
263                 talloc_get_type(action->async.private_data,
264                                 struct wbsrv_samba3_call);
265         struct check_machacc_state *state =
266                 talloc_get_type(s3call->private_data,
267                                 struct check_machacc_state);
268         struct wbsrv_service *service =
269                 s3call->call->wbconn->listen_socket->service;
270         
271         NTSTATUS status;
272         
273         status = wb_get_schannel_creds_recv(action, service);
274         service->netlogon = state->getcreds->out.netlogon;
275
276         talloc_unlink(state, state->conn->out.tree); /* The pipe owns it now */
277         state->conn->out.tree = NULL;
278
279         if (!NT_STATUS_IS_OK(status)) goto done;
280
281         s3call->response.result = WINBINDD_OK;
282  done:
283         if (!NT_STATUS_IS_OK(status)) {
284                 s3call->response.result = WINBINDD_ERROR;
285                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
286                                         nt_errstr(status));
287                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
288                                         nt_errstr(status));
289                 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
290
291         }
292
293         status = wbsrv_send_reply(s3call->call);
294         if (!NT_STATUS_IS_OK(status)) {
295                 wbsrv_terminate_connection(s3call->call->wbconn,
296                                            "wbsrv_queue_reply() failed");
297                 return;
298         }
299 }