r11068: Fix pam_auth_crap, remove the sync code. I don't know what it was when I
[ira/wip.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 "lib/events/events.h"
36 #include "librpc/gen_ndr/ndr_netlogon.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 static void checkmachacc_recv_creds(struct composite_context *ctx);
83
84 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
85 {
86         struct composite_context *ctx;
87
88         DEBUG(5, ("wbsrv_samba3_check_machacc called\n"));
89
90         ctx = wb_cmd_checkmachacc_send(s3call->call);
91         NT_STATUS_HAVE_NO_MEMORY(ctx);
92
93         ctx->async.fn = checkmachacc_recv_creds;
94         ctx->async.private_data = s3call;
95         s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
96         return NT_STATUS_OK;
97 }
98         
99 static void checkmachacc_recv_creds(struct composite_context *ctx)
100 {
101         struct wbsrv_samba3_call *s3call =
102                 talloc_get_type(ctx->async.private_data,
103                                 struct wbsrv_samba3_call);
104         NTSTATUS status;
105
106         status = wb_cmd_checkmachacc_recv(ctx);
107         if (NT_STATUS_IS_OK(status)) {
108                 s3call->response.result = WINBINDD_OK;
109         } else {
110                 struct winbindd_response *resp = &s3call->response;
111                 resp->result = WINBINDD_ERROR;
112                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
113                                         nt_errstr(status));
114                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
115                                         nt_errstr(status));
116                 resp->data.auth.pam_error = nt_status_to_pam(status);
117         }
118         status = wbsrv_send_reply(s3call->call);
119         if (!NT_STATUS_IS_OK(status)) {
120                 wbsrv_terminate_connection(s3call->call->wbconn,
121                                            "wbsrv_queue_reply() failed");
122                 return;
123         }
124 }
125
126 static void lookupname_recv_sid(struct composite_context *ctx);
127
128 NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
129 {
130         struct composite_context *ctx;
131
132         DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
133
134         ctx = wb_cmd_lookupname_send(s3call->call,
135                                      s3call->request.data.name.name);
136         NT_STATUS_HAVE_NO_MEMORY(ctx);
137
138         /* setup the callbacks */
139         ctx->async.fn = lookupname_recv_sid;
140         ctx->async.private_data = s3call;
141         s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
142         return NT_STATUS_OK;
143 }
144
145 static void lookupname_recv_sid(struct composite_context *ctx)
146 {
147         struct wbsrv_samba3_call *s3call =
148                 talloc_get_type(ctx->async.private_data,
149                                 struct wbsrv_samba3_call);
150         struct wb_sid_object *sid;
151         NTSTATUS status;
152
153         status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
154         if (!NT_STATUS_IS_OK(status)) goto done;
155
156         s3call->response.result = WINBINDD_OK;
157         s3call->response.data.sid.type = sid->type;
158         WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid,
159                                 dom_sid_string(s3call, sid->sid));
160
161  done:
162         if (!NT_STATUS_IS_OK(status)) {
163                 struct winbindd_response *resp = &s3call->response;
164                 resp->result = WINBINDD_ERROR;
165                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
166                                         nt_errstr(status));
167                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
168                                         nt_errstr(status));
169                 resp->data.auth.pam_error = nt_status_to_pam(status);
170         }
171
172         status = wbsrv_send_reply(s3call->call);
173         if (!NT_STATUS_IS_OK(status)) {
174                 wbsrv_terminate_connection(s3call->call->wbconn,
175                                            "wbsrv_queue_reply() failed");
176                 return;
177         }
178 }
179
180 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
181 {
182         s3call->response.result                 = WINBINDD_ERROR;
183         return NT_STATUS_OK;
184 }
185
186 static BOOL samba3_parse_domuser(TALLOC_CTX *mem_ctx, const char *domuser,
187                                  char **domain, char **user)
188 {
189         char *p = strchr(domuser, *lp_winbind_separator());
190
191         if (p == NULL) {
192                 *domain = talloc_strdup(mem_ctx, lp_workgroup());
193         } else {
194                 *domain = talloc_strndup(mem_ctx, domuser,
195                                          PTR_DIFF(p, domuser));
196                 domuser = p+1;
197         }
198
199         *user = talloc_strdup(mem_ctx, domuser);
200
201         return ((*domain != NULL) && (*user != NULL));
202 }
203
204 static void pam_auth_crap_recv(struct composite_context *ctx);
205
206 NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
207 {
208         struct composite_context *ctx;
209
210         DATA_BLOB chal, nt_resp, lm_resp;
211         char *domain, *user;
212
213         DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
214
215         chal.data      = s3call->request.data.auth_crap.chal;
216         chal.length    = sizeof(s3call->request.data.auth_crap.chal);
217         nt_resp.data   = s3call->request.data.auth_crap.nt_resp;
218         nt_resp.length = s3call->request.data.auth_crap.nt_resp_len;
219         lm_resp.data   = s3call->request.data.auth_crap.lm_resp;
220         lm_resp.length = s3call->request.data.auth_crap.lm_resp_len;
221
222         if (!samba3_parse_domuser(s3call, s3call->request.data.auth_crap.user,
223                                   &domain, &user)) {
224                 return NT_STATUS_NO_MEMORY;
225         }
226
227         ctx = wb_cmd_pam_auth_crap_send(
228                 s3call->call, domain, user,
229                 s3call->request.data.auth_crap.workstation,
230                 chal, nt_resp, lm_resp);
231         NT_STATUS_HAVE_NO_MEMORY(ctx);
232
233         ctx->async.fn = pam_auth_crap_recv;
234         ctx->async.private_data = s3call;
235         s3call->call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
236         return NT_STATUS_OK;
237 }
238
239 static void pam_auth_crap_recv(struct composite_context *ctx)
240 {
241         struct wbsrv_samba3_call *s3call =
242                 talloc_get_type(ctx->async.private_data,
243                                 struct wbsrv_samba3_call);
244         struct winbindd_response *resp = &s3call->response;
245         NTSTATUS status;
246         DATA_BLOB info3;
247         struct netr_UserSessionKey user_session_key;
248         struct netr_LMSessionKey lm_key;
249
250         status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
251                                            &user_session_key, &lm_key);
252         if (!NT_STATUS_IS_OK(status)) goto done;
253
254         if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
255                 memcpy(s3call->response.data.auth.user_session_key, 
256                        &user_session_key.key,
257                        sizeof(s3call->response.data.auth.user_session_key));
258         }
259
260         if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
261                 s3call->response.extra_data = info3.data;
262                 s3call->response.length += info3.length;
263         }
264
265         if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
266                 memcpy(s3call->response.data.auth.first_8_lm_hash, 
267                        lm_key.key,
268                        sizeof(s3call->response.data.auth.first_8_lm_hash));
269         }
270         
271         resp->result = WINBINDD_OK;
272
273  done:
274         if (!NT_STATUS_IS_OK(status)) {
275                 resp->result = WINBINDD_ERROR;
276                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
277                                         nt_errstr(status));
278                 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
279                                         nt_errstr(status));
280                 resp->data.auth.pam_error = nt_status_to_pam(status);
281         }
282
283         status = wbsrv_send_reply(s3call->call);
284         if (!NT_STATUS_IS_OK(status)) {
285                 wbsrv_terminate_connection(s3call->call->wbconn,
286                                            "wbsrv_queue_reply() failed");
287                 return;
288         }
289 }