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 "librpc/rpc/dcerpc_composite.h"
36 #include "lib/events/events.h"
38 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
40 s3call->response.result = WINBINDD_OK;
41 s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
45 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
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);
53 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
55 s3call->response.result = WINBINDD_OK;
56 WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name, lp_workgroup());
60 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
62 s3call->response.result = WINBINDD_OK;
63 WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name, lp_netbios_name());
67 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
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);
76 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
78 s3call->response.result = WINBINDD_OK;
82 #define null_no_memory_done(x) do { \
83 if ((x) == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } \
86 struct check_machacc_state {
87 struct wb_finddcs *io;
88 struct smb_composite_connect *conn;
89 struct wb_get_schannel_creds *getcreds;
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);
96 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
98 struct composite_context *resolve_req;
99 struct check_machacc_state *state;
100 struct wbsrv_service *service =
101 s3call->call->wbconn->listen_socket->service;
103 DEBUG(5, ("check_machacc called\n"));
105 if (service->netlogon != NULL) {
106 talloc_free(service->netlogon);
109 state = talloc(s3call, struct check_machacc_state);
110 NT_STATUS_HAVE_NO_MEMORY(state);
112 state->io = talloc(s3call, struct wb_finddcs);
113 NT_STATUS_HAVE_NO_MEMORY(state->io);
114 s3call->private_data = state;
116 state->io->in.msg_ctx = s3call->call->wbconn->conn->msg_ctx;
117 state->io->in.domain = lp_workgroup();
119 resolve_req = wb_finddcs_send(state->io, s3call->call->event_ctx);
120 NT_STATUS_HAVE_NO_MEMORY(resolve_req);
122 /* setup the callbacks */
123 resolve_req->async.fn = wbsrv_samba3_check_machacc_receive_dcs;
124 resolve_req->async.private_data = s3call;
126 /* tell the caller we reply later */
127 s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
131 static void wbsrv_samba3_check_machacc_receive_dcs(struct composite_context *action)
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;
142 status = wb_finddcs_recv(action, s3call);
144 s3call->response.data.auth.nt_status = NT_STATUS_V(status);
145 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
147 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
149 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
151 if (!NT_STATUS_IS_OK(status)) {
155 state->conn = talloc(state, struct smb_composite_connect);
156 if (state->conn == NULL) {
157 status = NT_STATUS_NO_MEMORY;
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();
168 state->conn->in.credentials = cli_credentials_init(state->conn);
169 if (state->conn->in.credentials == NULL) {
170 status = NT_STATUS_NO_MEMORY;
173 cli_credentials_set_conf(state->conn->in.credentials);
174 cli_credentials_set_anonymous(state->conn->in.credentials);
176 ctx = smb_composite_connect_send(state->conn, state,
177 s3call->call->event_ctx);
179 status = NT_STATUS_NO_MEMORY;
183 ctx->async.fn = wbsrv_samba3_check_machacc_receive_tree;
184 ctx->async.private_data = s3call;
188 if (!NT_STATUS_IS_OK(status)) {
189 s3call->response.result = WINBINDD_ERROR;
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");
200 static void wbsrv_samba3_check_machacc_receive_tree(struct composite_context *action)
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;
210 struct cli_credentials *creds;
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)));
218 state->getcreds = talloc(state, struct wb_get_schannel_creds);
219 null_no_memory_done(state->getcreds);
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;
227 state->getcreds->in.tree = state->conn->out.tree;
228 state->getcreds->in.creds = creds;
230 ctx = wb_get_schannel_creds_send(state->getcreds,
231 s3call->call->event_ctx);
232 null_no_memory_done(ctx);
234 ctx->async.fn = wbsrv_samba3_check_machacc_receive_creds;
235 ctx->async.private_data = s3call;
240 s3call->response.result = WINBINDD_OK;
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,
246 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
248 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
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");
260 static void delete_pipe(struct event_context *ctx, struct timed_event *te,
261 struct timeval tv, void *p)
266 static void wbsrv_samba3_check_machacc_receive_creds(struct composite_context *action)
268 struct wbsrv_samba3_call *s3call =
269 talloc_get_type(action->async.private_data,
270 struct wbsrv_samba3_call);
271 struct check_machacc_state *state =
272 talloc_get_type(s3call->private_data,
273 struct check_machacc_state);
274 struct wbsrv_service *service =
275 s3call->call->wbconn->listen_socket->service;
279 status = wb_get_schannel_creds_recv(action, service);
281 talloc_unlink(state, state->conn->out.tree); /* The pipe owns it now */
282 state->conn->out.tree = NULL;
284 if (!NT_STATUS_IS_OK(status)) {
285 /* Nasty hack awaiting a proper fix. So far we can not
286 * delete a pipe from an async rpc callback which where we are
287 * in right now, so delete the pipe from an event handler.. */
288 event_add_timed(s3call->call->event_ctx, service,
290 delete_pipe, state->getcreds->out.netlogon);
291 service->netlogon = NULL;
295 service->netlogon = state->getcreds->out.netlogon;
296 s3call->response.result = WINBINDD_OK;
298 if (!NT_STATUS_IS_OK(status)) {
299 s3call->response.result = WINBINDD_ERROR;
300 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string,
302 WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string,
304 s3call->response.data.auth.pam_error = nt_status_to_pam(status);
308 status = wbsrv_send_reply(s3call->call);
309 if (!NT_STATUS_IS_OK(status)) {
310 wbsrv_terminate_connection(s3call->call->wbconn,
311 "wbsrv_queue_reply() failed");