2 Unix SMB/CIFS implementation.
3 Main winbindd samba3 server routines
5 Copyright (C) Stefan Metzmacher 2005
6 Copyright (C) Volker Lendecke 2005
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.
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.
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.
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 "lib/events/events.h"
37 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
39 s3call->response.result = WINBINDD_OK;
40 s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
44 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
46 s3call->response.result = WINBINDD_OK;
47 s3call->response.data.info.winbind_separator = *lp_winbind_separator();
48 WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version, SAMBA_VERSION_STRING);
52 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
54 s3call->response.result = WINBINDD_OK;
55 WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name, lp_workgroup());
59 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
61 s3call->response.result = WINBINDD_OK;
62 WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name, lp_netbios_name());
66 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
68 s3call->response.result = WINBINDD_OK;
69 s3call->response.extra_data = smbd_tmp_path(s3call,
70 WINBINDD_SAMBA3_PRIVILEGED_SOCKET);
71 NT_STATUS_HAVE_NO_MEMORY(s3call->response.extra_data);
75 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
77 s3call->response.result = WINBINDD_OK;
81 #define null_no_memory_done(x) do { \
82 if ((x) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } \
85 struct check_machacc_state {
86 struct wb_finddcs *io;
87 struct smb_composite_connect *conn;
88 struct wb_get_schannel_creds *getcreds;
91 static void wbsrv_samba3_check_machacc_receive_creds(struct composite_context *action);
92 static void wbsrv_samba3_check_machacc_receive_tree(struct composite_context *action);
93 static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *action);
95 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
97 struct composite_context *resolve_req;
98 struct check_machacc_state *state;
99 struct wbsrv_service *service =
100 s3call->call->wbconn->listen_socket->service;
102 DEBUG(5, ("check_machacc called\n"));
104 if (service->netlogon != NULL) {
105 talloc_free(service->netlogon);
108 state = talloc(s3call, struct check_machacc_state);
109 NT_STATUS_HAVE_NO_MEMORY(state);
111 state->io = talloc(s3call, struct wb_finddcs);
112 NT_STATUS_HAVE_NO_MEMORY(state->io);
113 s3call->private_data = state;
115 state->io->in.msg_ctx = s3call->call->wbconn->conn->msg_ctx;
116 state->io->in.domain = lp_workgroup();
118 resolve_req = wb_finddcs_send(state->io, s3call->call->event_ctx);
119 NT_STATUS_HAVE_NO_MEMORY(resolve_req);
121 /* setup the callbacks */
122 resolve_req->async.fn = wbsrv_samba3_check_machacc_receive_dcs;
123 resolve_req->async.private_data = s3call;
125 /* tell the caller we reply later */
126 s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
130 static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *action)
132 struct wbsrv_samba3_call *s3call =
133 talloc_get_type(action->async.private_data,
134 struct wbsrv_samba3_call);
135 struct check_machacc_state *state =
136 talloc_get_type(s3call->private_data,
137 struct check_machacc_state);
138 struct composite_context *ctx;
141 status = wb_finddcs_recv(action, s3call);
143 s3call->response.data.auth.nt_status = NT_STATUS_V(status);
144 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
146 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
148 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
150 if (!NT_STATUS_IS_OK(status)) {
154 state->conn = talloc(state, struct smb_composite_connect);
155 if (state->conn == NULL) {
156 status = NT_STATUS_NO_MEMORY;
160 state->conn->in.dest_host = state->io->out.dcs[0].address;
161 state->conn->in.port = 0;
162 state->conn->in.called_name = state->io->out.dcs[0].name;
163 state->conn->in.service = "IPC$";
164 state->conn->in.service_type = "IPC";
165 state->conn->in.workgroup = lp_workgroup();
167 state->conn->in.credentials = cli_credentials_init(state->conn);
168 if (state->conn->in.credentials == NULL) {
169 status = NT_STATUS_NO_MEMORY;
172 cli_credentials_set_conf(state->conn->in.credentials);
173 cli_credentials_set_anonymous(state->conn->in.credentials);
175 ctx = smb_composite_connect_send(state->conn, state,
176 s3call->call->event_ctx);
178 status = NT_STATUS_NO_MEMORY;
182 ctx->async.fn = wbsrv_samba3_check_machacc_receive_tree;
183 ctx->async.private_data = s3call;
187 if (!NT_STATUS_IS_OK(status)) {
188 s3call->response.result = WINBINDD_ERROR;
191 status = wbsrv_send_reply(s3call->call);
192 if (!NT_STATUS_IS_OK(status)) {
193 wbsrv_terminate_connection(s3call->call->wbconn,
194 "wbsrv_queue_reply() failed");
199 static void wbsrv_samba3_check_machacc_receive_tree(struct composite_context *action)
201 struct wbsrv_samba3_call *s3call =
202 talloc_get_type(action->async.private_data,
203 struct wbsrv_samba3_call);
204 struct check_machacc_state *state =
205 talloc_get_type(s3call->private_data,
206 struct check_machacc_state);
207 struct composite_context *ctx;
209 struct cli_credentials *creds;
211 status = smb_composite_connect_recv(action, state);
212 if (!NT_STATUS_IS_OK(status)) {
213 DEBUG(5, ("Connect failed: %s\n", nt_errstr(status)));
217 state->getcreds = talloc(state, struct wb_get_schannel_creds);
218 null_no_memory_done(state->getcreds);
220 creds = cli_credentials_init(state);
221 null_no_memory_done(creds);
222 cli_credentials_set_conf(creds);
223 status = cli_credentials_set_machine_account(creds);
224 if (!NT_STATUS_IS_OK(status)) goto done;
226 state->getcreds->in.tree = state->conn->out.tree;
227 state->getcreds->in.creds = creds;
229 ctx = wb_get_schannel_creds_send(state->getcreds,
230 s3call->call->event_ctx);
231 null_no_memory_done(ctx);
233 ctx->async.fn = wbsrv_samba3_check_machacc_receive_creds;
234 ctx->async.private_data = s3call;
239 s3call->response.result = WINBINDD_OK;
241 if (!NT_STATUS_IS_OK(status)) {
242 s3call->response.result = WINBINDD_ERROR;
243 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
245 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
247 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
251 status = wbsrv_send_reply(s3call->call);
252 if (!NT_STATUS_IS_OK(status)) {
253 wbsrv_terminate_connection(s3call->call->wbconn,
254 "wbsrv_queue_reply() failed");
259 static void delete_pipe(struct event_context *ctx, struct timed_event *te,
260 struct timeval tv, void *p)
265 static void wbsrv_samba3_check_machacc_receive_creds(struct composite_context *action)
267 struct wbsrv_samba3_call *s3call =
268 talloc_get_type(action->async.private_data,
269 struct wbsrv_samba3_call);
270 struct check_machacc_state *state =
271 talloc_get_type(s3call->private_data,
272 struct check_machacc_state);
273 struct wbsrv_service *service =
274 s3call->call->wbconn->listen_socket->service;
278 status = wb_get_schannel_creds_recv(action, service);
280 talloc_unlink(state, state->conn->out.tree); /* The pipe owns it now */
281 state->conn->out.tree = NULL;
283 if (!NT_STATUS_IS_OK(status)) {
284 /* Nasty hack awaiting a proper fix. So far we can not
285 * delete a pipe from an async rpc callback which where we are
286 * in right now, so delete the pipe from an event handler.. */
287 event_add_timed(s3call->call->event_ctx, service,
289 delete_pipe, state->getcreds->out.netlogon);
290 service->netlogon = NULL;
294 service->netlogon = state->getcreds->out.netlogon;
295 s3call->response.result = WINBINDD_OK;
297 if (!NT_STATUS_IS_OK(status)) {
298 s3call->response.result = WINBINDD_ERROR;
299 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
301 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
303 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
307 status = wbsrv_send_reply(s3call->call);
308 if (!NT_STATUS_IS_OK(status)) {
309 wbsrv_terminate_connection(s3call->call->wbconn,
310 "wbsrv_queue_reply() failed");