ctdb-daemon: Schedule running of callback if there are no event scripts
[Samba.git] / source4 / ldap_server / ldap_bind.c
blobc7715de14198d9ea92e739285c71477aea2384f0
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP server
4 Copyright (C) Stefan Metzmacher 2004
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.
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.
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/>.
20 #include "includes.h"
21 #include "ldap_server/ldap_server.h"
22 #include "auth/auth.h"
23 #include "smbd/service.h"
24 #include <ldb.h>
25 #include <ldb_errors.h>
26 #include "dsdb/samdb/samdb.h"
27 #include "auth/gensec/gensec.h"
28 #include "auth/gensec/gensec_tstream.h"
29 #include "param/param.h"
30 #include "../lib/util/tevent_ntstatus.h"
32 static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
34 struct ldap_BindRequest *req = &call->request->r.BindRequest;
35 struct ldapsrv_reply *reply;
36 struct ldap_BindResponse *resp;
38 int result;
39 const char *errstr;
40 const char *nt4_domain, *nt4_account;
42 struct auth_session_info *session_info;
44 NTSTATUS status;
46 DEBUG(10, ("BindSimple dn: %s\n",req->dn));
48 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
49 if (!reply) {
50 return NT_STATUS_NO_MEMORY;
53 if (req->dn != NULL &&
54 strlen(req->dn) != 0 &&
55 call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
56 call->conn->sockets.active != call->conn->sockets.tls)
58 status = NT_STATUS_NETWORK_ACCESS_DENIED;
59 result = LDAP_STRONG_AUTH_REQUIRED;
60 errstr = talloc_asprintf(reply,
61 "BindSimple: Transport encryption required.");
62 goto do_reply;
65 status = crack_auto_name_to_nt4_name(call, call->conn->connection->event.ctx, call->conn->lp_ctx, req->dn, &nt4_domain, &nt4_account);
66 if (NT_STATUS_IS_OK(status)) {
67 status = authenticate_username_pw(call,
68 call->conn->connection->event.ctx,
69 call->conn->connection->msg_ctx,
70 call->conn->lp_ctx,
71 nt4_domain, nt4_account,
72 req->creds.password,
73 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
74 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
75 &session_info);
78 if (NT_STATUS_IS_OK(status)) {
79 result = LDAP_SUCCESS;
80 errstr = NULL;
82 talloc_unlink(call->conn, call->conn->session_info);
83 call->conn->session_info = talloc_steal(call->conn, session_info);
85 /* don't leak the old LDB */
86 talloc_unlink(call->conn, call->conn->ldb);
88 status = ldapsrv_backend_Init(call->conn);
90 if (!NT_STATUS_IS_OK(status)) {
91 result = LDAP_OPERATIONS_ERROR;
92 errstr = talloc_asprintf(reply, "Simple Bind: Failed to advise ldb new credentials: %s", nt_errstr(status));
94 } else {
95 status = nt_status_squash(status);
97 result = LDAP_INVALID_CREDENTIALS;
98 errstr = talloc_asprintf(reply, "Simple Bind Failed: %s", nt_errstr(status));
101 do_reply:
102 resp = &reply->msg->r.BindResponse;
103 resp->response.resultcode = result;
104 resp->response.errormessage = errstr;
105 resp->response.dn = NULL;
106 resp->response.referral = NULL;
107 resp->SASL.secblob = NULL;
109 ldapsrv_queue_reply(call, reply);
110 return NT_STATUS_OK;
113 struct ldapsrv_sasl_postprocess_context {
114 struct ldapsrv_connection *conn;
115 struct tstream_context *sasl;
118 struct ldapsrv_sasl_postprocess_state {
119 uint8_t dummy;
122 static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
123 struct tevent_context *ev,
124 void *private_data)
126 struct ldapsrv_sasl_postprocess_context *context =
127 talloc_get_type_abort(private_data,
128 struct ldapsrv_sasl_postprocess_context);
129 struct tevent_req *req;
130 struct ldapsrv_sasl_postprocess_state *state;
132 req = tevent_req_create(mem_ctx, &state,
133 struct ldapsrv_sasl_postprocess_state);
134 if (req == NULL) {
135 return NULL;
138 TALLOC_FREE(context->conn->sockets.sasl);
139 context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
140 context->conn->sockets.active = context->conn->sockets.sasl;
142 tevent_req_done(req);
143 return tevent_req_post(req, ev);
146 static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
148 return tevent_req_simple_recv_ntstatus(req);
151 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
153 struct ldap_BindRequest *req = &call->request->r.BindRequest;
154 struct ldapsrv_reply *reply;
155 struct ldap_BindResponse *resp;
156 struct ldapsrv_connection *conn;
157 int result = 0;
158 const char *errstr=NULL;
159 NTSTATUS status = NT_STATUS_OK;
161 DEBUG(10, ("BindSASL dn: %s\n",req->dn));
163 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
164 if (!reply) {
165 return NT_STATUS_NO_MEMORY;
167 resp = &reply->msg->r.BindResponse;
169 conn = call->conn;
172 * TODO: a SASL bind with a different mechanism
173 * should cancel an inprogress SASL bind.
174 * (see RFC 4513)
177 if (!conn->gensec) {
178 conn->session_info = NULL;
180 status = samba_server_gensec_start(conn,
181 conn->connection->event.ctx,
182 conn->connection->msg_ctx,
183 conn->lp_ctx,
184 conn->server_credentials,
185 "ldap",
186 &conn->gensec);
187 if (!NT_STATUS_IS_OK(status)) {
188 DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
189 result = LDAP_OPERATIONS_ERROR;
190 errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s",
191 nt_errstr(status));
192 } else {
194 gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
195 gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
196 gensec_want_feature(conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
197 gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);
199 status = gensec_start_mech_by_sasl_name(conn->gensec, req->creds.SASL.mechanism);
201 if (!NT_STATUS_IS_OK(status)) {
202 DEBUG(1, ("Failed to start GENSEC SASL[%s] server code: %s\n",
203 req->creds.SASL.mechanism, nt_errstr(status)));
204 result = LDAP_OPERATIONS_ERROR;
205 errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to start authentication backend: %s",
206 req->creds.SASL.mechanism, nt_errstr(status));
211 if (NT_STATUS_IS_OK(status)) {
212 DATA_BLOB input = data_blob(NULL, 0);
213 DATA_BLOB output = data_blob(NULL, 0);
215 if (req->creds.SASL.secblob) {
216 input = *req->creds.SASL.secblob;
219 status = gensec_update_ev(conn->gensec, reply, conn->connection->event.ctx,
220 input, &output);
222 /* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
223 resp->SASL.secblob = talloc(reply, DATA_BLOB);
224 NT_STATUS_HAVE_NO_MEMORY(resp->SASL.secblob);
225 *resp->SASL.secblob = output;
226 } else {
227 resp->SASL.secblob = NULL;
230 if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
231 result = LDAP_SASL_BIND_IN_PROGRESS;
232 errstr = NULL;
233 } else if (NT_STATUS_IS_OK(status)) {
234 struct ldapsrv_sasl_postprocess_context *context = NULL;
236 result = LDAP_SUCCESS;
237 errstr = NULL;
239 if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
240 gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
242 context = talloc(call, struct ldapsrv_sasl_postprocess_context);
244 if (!context) {
245 status = NT_STATUS_NO_MEMORY;
249 if (context && conn->sockets.tls) {
250 TALLOC_FREE(context);
251 status = NT_STATUS_NOT_SUPPORTED;
252 result = LDAP_UNWILLING_TO_PERFORM;
253 errstr = talloc_asprintf(reply,
254 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
255 req->creds.SASL.mechanism);
258 if (context && conn->sockets.sasl) {
259 TALLOC_FREE(context);
260 status = NT_STATUS_NOT_SUPPORTED;
261 result = LDAP_UNWILLING_TO_PERFORM;
262 errstr = talloc_asprintf(reply,
263 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
264 req->creds.SASL.mechanism);
267 if (context) {
268 context->conn = conn;
269 status = gensec_create_tstream(context,
270 context->conn->gensec,
271 context->conn->sockets.raw,
272 &context->sasl);
273 if (NT_STATUS_IS_OK(status)) {
274 if (!talloc_reference(context->sasl, conn->gensec)) {
275 status = NT_STATUS_NO_MEMORY;
278 } else {
279 switch (call->conn->require_strong_auth) {
280 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
281 break;
282 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
283 if (call->conn->sockets.active == call->conn->sockets.tls) {
284 break;
286 status = NT_STATUS_NETWORK_ACCESS_DENIED;
287 result = LDAP_STRONG_AUTH_REQUIRED;
288 errstr = talloc_asprintf(reply,
289 "SASL:[%s]: not allowed if TLS is used.",
290 req->creds.SASL.mechanism);
291 break;
292 case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
293 status = NT_STATUS_NETWORK_ACCESS_DENIED;
294 result = LDAP_STRONG_AUTH_REQUIRED;
295 errstr = talloc_asprintf(reply,
296 "SASL:[%s]: Sign or Seal are required.",
297 req->creds.SASL.mechanism);
298 break;
302 if (result != LDAP_SUCCESS) {
303 } else if (!NT_STATUS_IS_OK(status)) {
304 result = LDAP_OPERATIONS_ERROR;
305 errstr = talloc_asprintf(reply,
306 "SASL:[%s]: Failed to setup SASL socket: %s",
307 req->creds.SASL.mechanism, nt_errstr(status));
308 } else {
309 struct auth_session_info *old_session_info=NULL;
311 old_session_info = conn->session_info;
312 conn->session_info = NULL;
313 status = gensec_session_info(conn->gensec, conn, &conn->session_info);
314 if (!NT_STATUS_IS_OK(status)) {
315 conn->session_info = old_session_info;
316 result = LDAP_OPERATIONS_ERROR;
317 errstr = talloc_asprintf(reply,
318 "SASL:[%s]: Failed to get session info: %s",
319 req->creds.SASL.mechanism, nt_errstr(status));
320 } else {
321 talloc_unlink(conn, old_session_info);
323 /* don't leak the old LDB */
324 talloc_unlink(conn, conn->ldb);
326 status = ldapsrv_backend_Init(conn);
328 if (!NT_STATUS_IS_OK(status)) {
329 result = LDAP_OPERATIONS_ERROR;
330 errstr = talloc_asprintf(reply,
331 "SASL:[%s]: Failed to advise samdb of new credentials: %s",
332 req->creds.SASL.mechanism,
333 nt_errstr(status));
338 if (NT_STATUS_IS_OK(status) && context) {
339 call->postprocess_send = ldapsrv_sasl_postprocess_send;
340 call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
341 call->postprocess_private = context;
343 talloc_unlink(conn, conn->gensec);
344 conn->gensec = NULL;
345 } else {
346 status = nt_status_squash(status);
347 if (result == 0) {
348 result = LDAP_INVALID_CREDENTIALS;
349 errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status));
351 talloc_unlink(conn, conn->gensec);
352 conn->gensec = NULL;
355 resp->response.resultcode = result;
356 resp->response.dn = NULL;
357 resp->response.errormessage = errstr;
358 resp->response.referral = NULL;
360 ldapsrv_queue_reply(call, reply);
361 return NT_STATUS_OK;
364 NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
366 struct ldap_BindRequest *req = &call->request->r.BindRequest;
367 struct ldapsrv_reply *reply;
368 struct ldap_BindResponse *resp;
370 if (call->conn->pending_calls != NULL) {
371 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
372 if (!reply) {
373 return NT_STATUS_NO_MEMORY;
376 resp = &reply->msg->r.BindResponse;
377 resp->response.resultcode = LDAP_BUSY;
378 resp->response.dn = NULL;
379 resp->response.errormessage = talloc_asprintf(reply, "Pending requests on this LDAP session");
380 resp->response.referral = NULL;
381 resp->SASL.secblob = NULL;
383 ldapsrv_queue_reply(call, reply);
384 return NT_STATUS_OK;
388 * TODO: a simple bind should cancel an
389 * inprogress SASL bind.
390 * (see RFC 4513)
392 switch (req->mechanism) {
393 case LDAP_AUTH_MECH_SIMPLE:
394 return ldapsrv_BindSimple(call);
395 case LDAP_AUTH_MECH_SASL:
396 return ldapsrv_BindSASL(call);
399 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
400 if (!reply) {
401 return NT_STATUS_NO_MEMORY;
404 resp = &reply->msg->r.BindResponse;
405 resp->response.resultcode = LDAP_AUTH_METHOD_NOT_SUPPORTED;
406 resp->response.dn = NULL;
407 resp->response.errormessage = talloc_asprintf(reply, "Bad AuthenticationChoice [%d]", req->mechanism);
408 resp->response.referral = NULL;
409 resp->SASL.secblob = NULL;
411 ldapsrv_queue_reply(call, reply);
412 return NT_STATUS_OK;
415 NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
417 DEBUG(10, ("UnbindRequest\n"));
418 return NT_STATUS_OK;