Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : LDAP bind calls
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Volker Lendecke 2004
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 :
22 : */
23 :
24 : #include "includes.h"
25 : #include "libcli/ldap/libcli_ldap.h"
26 : #include "libcli/ldap/ldap_proto.h"
27 : #include "libcli/ldap/ldap_client.h"
28 : #include "lib/tls/tls.h"
29 : #include "auth/gensec/gensec.h"
30 : #include "source4/auth/gensec/gensec_tstream.h"
31 : #include "auth/credentials/credentials.h"
32 : #include "lib/stream/packet.h"
33 : #include "param/param.h"
34 : #include "param/loadparm.h"
35 : #include "librpc/gen_ndr/ads.h"
36 :
37 : struct ldap_simple_creds {
38 : const char *dn;
39 : const char *pw;
40 : };
41 :
42 0 : _PUBLIC_ NTSTATUS ldap_rebind(struct ldap_connection *conn)
43 : {
44 0 : NTSTATUS status;
45 0 : struct ldap_simple_creds *creds;
46 :
47 0 : switch (conn->bind.type) {
48 0 : case LDAP_BIND_SASL:
49 0 : status = ldap_bind_sasl(conn, (struct cli_credentials *)conn->bind.creds,
50 : conn->lp_ctx);
51 0 : break;
52 :
53 0 : case LDAP_BIND_SIMPLE:
54 0 : creds = (struct ldap_simple_creds *)conn->bind.creds;
55 :
56 0 : if (creds == NULL) {
57 0 : return NT_STATUS_UNSUCCESSFUL;
58 : }
59 :
60 0 : status = ldap_bind_simple(conn, creds->dn, creds->pw);
61 0 : break;
62 :
63 0 : default:
64 0 : return NT_STATUS_UNSUCCESSFUL;
65 : }
66 :
67 0 : return status;
68 : }
69 :
70 :
71 448 : static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn,
72 : const char *dn, const char *pw)
73 : {
74 0 : struct ldap_message *res;
75 :
76 448 : res = new_ldap_message(conn);
77 448 : if (!res) {
78 0 : return NULL;
79 : }
80 :
81 448 : res->type = LDAP_TAG_BindRequest;
82 448 : res->r.BindRequest.version = 3;
83 448 : res->r.BindRequest.dn = talloc_strdup(res, dn);
84 448 : res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SIMPLE;
85 448 : res->r.BindRequest.creds.password = talloc_strdup(res, pw);
86 448 : res->controls = NULL;
87 :
88 448 : return res;
89 : }
90 :
91 :
92 : /*
93 : perform a simple username/password bind
94 : */
95 448 : _PUBLIC_ NTSTATUS ldap_bind_simple(struct ldap_connection *conn,
96 : const char *userdn, const char *password)
97 : {
98 0 : struct ldap_request *req;
99 0 : struct ldap_message *msg;
100 0 : const char *dn, *pw;
101 0 : NTSTATUS status;
102 :
103 448 : if (conn == NULL) {
104 0 : return NT_STATUS_INVALID_CONNECTION;
105 : }
106 :
107 448 : if (userdn) {
108 447 : dn = userdn;
109 : } else {
110 1 : if (conn->auth_dn) {
111 0 : dn = conn->auth_dn;
112 : } else {
113 1 : dn = "";
114 : }
115 : }
116 :
117 448 : if (password) {
118 447 : pw = password;
119 : } else {
120 1 : if (conn->simple_pw) {
121 0 : pw = conn->simple_pw;
122 : } else {
123 1 : pw = "";
124 : }
125 : }
126 :
127 448 : msg = new_ldap_simple_bind_msg(conn, dn, pw);
128 448 : NT_STATUS_HAVE_NO_MEMORY(msg);
129 :
130 : /* send the request */
131 448 : req = ldap_request_send(conn, msg);
132 448 : talloc_free(msg);
133 448 : NT_STATUS_HAVE_NO_MEMORY(req);
134 :
135 : /* wait for replies */
136 448 : status = ldap_request_wait(req);
137 448 : if (!NT_STATUS_IS_OK(status)) {
138 0 : talloc_free(req);
139 0 : return status;
140 : }
141 :
142 : /* check its a valid reply */
143 448 : msg = req->replies[0];
144 448 : if (msg->type != LDAP_TAG_BindResponse) {
145 0 : talloc_free(req);
146 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
147 : }
148 :
149 448 : status = ldap_check_response(conn, &msg->r.BindResponse.response);
150 :
151 448 : talloc_free(req);
152 :
153 448 : if (NT_STATUS_IS_OK(status)) {
154 321 : struct ldap_simple_creds *creds = talloc(conn, struct ldap_simple_creds);
155 321 : if (creds == NULL) {
156 0 : return NT_STATUS_NO_MEMORY;
157 : }
158 321 : creds->dn = talloc_strdup(creds, dn);
159 321 : creds->pw = talloc_strdup(creds, pw);
160 321 : if (creds->dn == NULL || creds->pw == NULL) {
161 0 : return NT_STATUS_NO_MEMORY;
162 : }
163 321 : conn->bind.type = LDAP_BIND_SIMPLE;
164 321 : conn->bind.creds = creds;
165 : }
166 :
167 448 : return status;
168 : }
169 :
170 :
171 35314 : static struct ldap_message *new_ldap_sasl_bind_msg(struct ldap_connection *conn,
172 : const char *sasl_mechanism,
173 : DATA_BLOB *secblob)
174 : {
175 122 : struct ldap_message *res;
176 :
177 35314 : res = new_ldap_message(conn);
178 35314 : if (!res) {
179 0 : return NULL;
180 : }
181 :
182 35314 : res->type = LDAP_TAG_BindRequest;
183 35314 : res->r.BindRequest.version = 3;
184 35314 : res->r.BindRequest.dn = "";
185 35314 : res->r.BindRequest.mechanism = LDAP_AUTH_MECH_SASL;
186 35314 : res->r.BindRequest.creds.SASL.mechanism = talloc_strdup(res, sasl_mechanism);
187 35314 : if (secblob) {
188 35314 : res->r.BindRequest.creds.SASL.secblob = talloc(res, DATA_BLOB);
189 35314 : if (!res->r.BindRequest.creds.SASL.secblob) {
190 0 : talloc_free(res);
191 0 : return NULL;
192 : }
193 35314 : *res->r.BindRequest.creds.SASL.secblob = *secblob;
194 : } else {
195 0 : res->r.BindRequest.creds.SASL.secblob = NULL;
196 : }
197 35314 : res->controls = NULL;
198 :
199 35314 : return res;
200 : }
201 :
202 :
203 : /*
204 : perform a sasl bind using the given credentials
205 : */
206 26280 : _PUBLIC_ NTSTATUS ldap_bind_sasl(struct ldap_connection *conn,
207 : struct cli_credentials *creds,
208 : struct loadparm_context *lp_ctx)
209 : {
210 26280 : const char *sasl_mech = "GSS-SPNEGO";
211 122 : NTSTATUS status;
212 26280 : TALLOC_CTX *tmp_ctx = NULL;
213 26280 : DATA_BLOB input = data_blob(NULL, 0);
214 26280 : DATA_BLOB output = data_blob(NULL, 0);
215 26280 : bool first = true;
216 26280 : int wrap_flags = 0;
217 122 : uint32_t old_gensec_features;
218 26280 : unsigned int logon_retries = 0;
219 122 : size_t queue_length;
220 26280 : const DATA_BLOB *tls_cb = NULL;
221 26280 : bool use_channel_bound = lpcfg_parm_bool(lp_ctx,
222 : NULL,
223 : "ldap_testing",
224 : "channel_bound",
225 : true);
226 26280 : const char *forced_channel_binding = lpcfg_parm_string(lp_ctx,
227 : NULL,
228 : "ldap_testing",
229 : "forced_channel_binding");
230 26280 : DATA_BLOB forced_cb = data_blob_string_const(forced_channel_binding);
231 :
232 26280 : if (conn->sockets.active == NULL) {
233 0 : status = NT_STATUS_CONNECTION_DISCONNECTED;
234 0 : goto failed;
235 : }
236 :
237 26280 : queue_length = tevent_queue_length(conn->sockets.send_queue);
238 26280 : if (queue_length != 0) {
239 0 : status = NT_STATUS_INVALID_PARAMETER_MIX;
240 0 : DEBUG(1, ("SASL bind triggered with non empty send_queue[%zu]: %s\n",
241 : queue_length, nt_errstr(status)));
242 0 : goto failed;
243 : }
244 :
245 26280 : if (conn->pending != NULL) {
246 0 : status = NT_STATUS_INVALID_PARAMETER_MIX;
247 0 : DEBUG(1, ("SASL bind triggered with pending requests: %s\n",
248 : nt_errstr(status)));
249 0 : goto failed;
250 : }
251 :
252 26280 : tmp_ctx = talloc_new(conn);
253 26280 : if (tmp_ctx == NULL) {
254 0 : status = NT_STATUS_NO_MEMORY;
255 0 : goto failed;
256 : }
257 :
258 26280 : gensec_init();
259 :
260 26280 : if (conn->sockets.active == conn->sockets.tls) {
261 : /*
262 : * allow this for testing the old code:
263 : * ldap_testing:no_tls_channel_bindings = no
264 : */
265 163 : bool use_tls_cb = lpcfg_parm_bool(lp_ctx,
266 : NULL,
267 : "ldap_testing",
268 : "tls_channel_bindings",
269 : true);
270 :
271 : /*
272 : * require Kerberos SIGN/SEAL only if we don't use SSL
273 : * Windows seem not to like double encryption
274 : */
275 163 : wrap_flags = 0;
276 :
277 163 : if (use_tls_cb) {
278 123 : tls_cb = tstream_tls_channel_bindings(conn->sockets.tls);
279 : }
280 26117 : } else if (cli_credentials_is_anonymous(creds)) {
281 : /*
282 : * anonymous isn't protected
283 : */
284 0 : wrap_flags = 0;
285 : } else {
286 26117 : wrap_flags = lpcfg_client_ldap_sasl_wrapping(lp_ctx);
287 : }
288 :
289 26280 : if (forced_cb.length != 0) {
290 60 : tls_cb = &forced_cb;
291 : }
292 :
293 26280 : try_logon_again:
294 : /*
295 : we loop back here on a logon failure, and re-create the
296 : gensec session. The logon_retries counter ensures we don't
297 : loop forever.
298 : */
299 26436 : data_blob_free(&input);
300 26436 : TALLOC_FREE(conn->gensec);
301 :
302 26436 : status = gensec_client_start(conn, &conn->gensec,
303 : lpcfg_gensec_settings(conn, lp_ctx));
304 26436 : if (!NT_STATUS_IS_OK(status)) {
305 0 : DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
306 0 : goto failed;
307 : }
308 :
309 26436 : old_gensec_features = cli_credentials_get_gensec_features(creds);
310 26436 : if (wrap_flags == 0) {
311 324 : cli_credentials_set_gensec_features(creds,
312 : old_gensec_features & ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL),
313 : CRED_SPECIFIED);
314 : }
315 :
316 : /* this call also sets the gensec_want_features */
317 26436 : status = gensec_set_credentials(conn->gensec, creds);
318 26436 : if (!NT_STATUS_IS_OK(status)) {
319 0 : DEBUG(1, ("Failed to set GENSEC creds: %s\n",
320 : nt_errstr(status)));
321 0 : goto failed;
322 : }
323 :
324 : /* reset the original gensec_features (on the credentials
325 : * context, so we don't tattoo it ) */
326 26436 : cli_credentials_set_gensec_features(creds,
327 : old_gensec_features,
328 : CRED_SPECIFIED);
329 :
330 26436 : if (wrap_flags & ADS_AUTH_SASL_SEAL) {
331 25983 : gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
332 25983 : gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
333 : }
334 26436 : if (wrap_flags & ADS_AUTH_SASL_SIGN) {
335 129 : gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
336 : }
337 :
338 26436 : if (!use_channel_bound) {
339 94 : gensec_want_feature(conn->gensec, GENSEC_FEATURE_CB_OPTIONAL);
340 : }
341 :
342 : /*
343 : * This is an indication for the NTLMSSP backend to
344 : * also encrypt when only GENSEC_FEATURE_SIGN is requested
345 : * in gensec_[un]wrap().
346 : */
347 26436 : gensec_want_feature(conn->gensec, GENSEC_FEATURE_LDAP_STYLE);
348 :
349 26436 : if (conn->host) {
350 26436 : status = gensec_set_target_hostname(conn->gensec, conn->host);
351 26436 : if (!NT_STATUS_IS_OK(status)) {
352 0 : DEBUG(1, ("Failed to set GENSEC target hostname: %s\n",
353 : nt_errstr(status)));
354 0 : goto failed;
355 : }
356 : }
357 :
358 26436 : status = gensec_set_target_service(conn->gensec, "ldap");
359 26436 : if (!NT_STATUS_IS_OK(status)) {
360 0 : DEBUG(1, ("Failed to set GENSEC target service: %s\n",
361 : nt_errstr(status)));
362 0 : goto failed;
363 : }
364 :
365 26436 : if (tls_cb != NULL) {
366 163 : uint32_t initiator_addrtype = 0;
367 163 : const DATA_BLOB *initiator_address = NULL;
368 163 : uint32_t acceptor_addrtype = 0;
369 163 : const DATA_BLOB *acceptor_address = NULL;
370 163 : const DATA_BLOB *application_data = tls_cb;
371 :
372 163 : status = gensec_set_channel_bindings(conn->gensec,
373 : initiator_addrtype,
374 : initiator_address,
375 : acceptor_addrtype,
376 : acceptor_address,
377 : application_data);
378 163 : if (!NT_STATUS_IS_OK(status)) {
379 0 : DBG_WARNING("Failed to set GENSEC channel bindings: %s\n",
380 : nt_errstr(status));
381 0 : goto failed;
382 : }
383 : }
384 :
385 26436 : status = gensec_start_mech_by_sasl_name(conn->gensec, sasl_mech);
386 26436 : if (!NT_STATUS_IS_OK(status)) {
387 0 : DBG_WARNING("gensec_start_mech_by_sasl_name(%s): %s\n",
388 : sasl_mech, nt_errstr(status));
389 0 : goto failed;
390 : }
391 :
392 34895 : while (1) {
393 244 : NTSTATUS gensec_status;
394 244 : struct ldap_message *response;
395 244 : struct ldap_message *msg;
396 244 : struct ldap_request *req;
397 61331 : int result = LDAP_OTHER;
398 :
399 61331 : status = gensec_update(conn->gensec, tmp_ctx,
400 : input,
401 : &output);
402 : /* The status value here, from GENSEC is vital to the security
403 : * of the system. Even if the other end accepts, if GENSEC
404 : * claims 'MORE_PROCESSING_REQUIRED' then you must keep
405 : * feeding it blobs, or else the remote host/attacker might
406 : * avoid mutual authentication requirements.
407 : *
408 : * Likewise, you must not feed GENSEC too much (after the OK),
409 : * it doesn't like that either.
410 : *
411 : * For SASL/EXTERNAL, there is no data to send, but we still
412 : * must send the actual Bind request the first time around.
413 : * Otherwise, a result of NT_STATUS_OK with 0 output means the
414 : * end of a multi-step authentication, and no message must be
415 : * sent.
416 : */
417 :
418 61331 : gensec_status = status;
419 :
420 61331 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
421 26017 : !NT_STATUS_IS_OK(status)) {
422 280 : break;
423 : }
424 61051 : if (NT_STATUS_IS_OK(status) && output.length == 0) {
425 25737 : if (!first)
426 25615 : break;
427 : }
428 35314 : first = false;
429 :
430 35314 : msg = new_ldap_sasl_bind_msg(tmp_ctx,
431 : sasl_mech,
432 35314 : output.data != NULL ? &output : NULL);
433 35314 : if (msg == NULL) {
434 0 : status = NT_STATUS_NO_MEMORY;
435 0 : goto failed;
436 : }
437 :
438 35314 : req = ldap_request_send(conn, msg);
439 35314 : if (req == NULL) {
440 0 : status = NT_STATUS_NO_MEMORY;
441 0 : goto failed;
442 : }
443 35314 : talloc_reparent(conn, tmp_ctx, req);
444 :
445 35314 : status = ldap_result_n(req, 0, &response);
446 35314 : if (!NT_STATUS_IS_OK(status)) {
447 0 : goto failed;
448 : }
449 :
450 35314 : if (response->type != LDAP_TAG_BindResponse) {
451 0 : status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
452 0 : goto failed;
453 : }
454 :
455 35314 : result = response->r.BindResponse.response.resultcode;
456 :
457 35314 : if (result == LDAP_STRONG_AUTH_REQUIRED) {
458 123 : if (wrap_flags == 0) {
459 123 : wrap_flags = ADS_AUTH_SASL_SIGN;
460 156 : goto try_logon_again;
461 : }
462 : }
463 :
464 35191 : if (result == LDAP_INVALID_CREDENTIALS) {
465 : /*
466 : try a second time on invalid credentials, to
467 : give the user a chance to re-enter the
468 : password and to handle the case where our
469 : kerberos ticket is invalid as the server
470 : password has changed
471 : */
472 0 : const char *principal;
473 :
474 295 : principal = gensec_get_target_principal(conn->gensec);
475 295 : if (principal == NULL) {
476 295 : const char *hostname = gensec_get_target_hostname(conn->gensec);
477 295 : const char *service = gensec_get_target_service(conn->gensec);
478 295 : if (hostname != NULL && service != NULL) {
479 295 : principal = talloc_asprintf(tmp_ctx, "%s/%s", service, hostname);
480 : }
481 : }
482 :
483 557 : if (cli_credentials_failed_kerberos_login(creds, principal, &logon_retries) ||
484 262 : cli_credentials_wrong_password(creds)) {
485 : /*
486 : destroy our gensec session and loop
487 : back up to the top to retry,
488 : offering the user a chance to enter
489 : new credentials, or get a new ticket
490 : if using kerberos
491 : */
492 33 : goto try_logon_again;
493 : }
494 : }
495 :
496 35158 : if (result != LDAP_SUCCESS && result != LDAP_SASL_BIND_IN_PROGRESS) {
497 263 : status = ldap_check_response(conn,
498 263 : &response->r.BindResponse.response);
499 263 : break;
500 : }
501 :
502 : /* This is where we check if GENSEC wanted to be fed more data */
503 34895 : if (!NT_STATUS_EQUAL(gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
504 0 : break;
505 : }
506 34895 : if (response->r.BindResponse.SASL.secblob) {
507 34895 : input = *response->r.BindResponse.SASL.secblob;
508 : } else {
509 0 : input = data_blob(NULL, 0);
510 : }
511 : }
512 :
513 26280 : TALLOC_FREE(tmp_ctx);
514 :
515 26280 : if (!NT_STATUS_IS_OK(status)) {
516 543 : goto failed;
517 : }
518 :
519 25737 : conn->bind.type = LDAP_BIND_SASL;
520 25737 : conn->bind.creds = creds;
521 :
522 25737 : if (wrap_flags & ADS_AUTH_SASL_SEAL) {
523 25505 : if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
524 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
525 : }
526 :
527 25505 : if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
528 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
529 : }
530 232 : } else if (wrap_flags & ADS_AUTH_SASL_SIGN) {
531 129 : if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN)) {
532 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
533 : }
534 : }
535 :
536 25737 : if (!gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) &&
537 103 : !gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
538 103 : return NT_STATUS_OK;
539 : }
540 :
541 25634 : status = gensec_create_tstream(conn->sockets.raw,
542 : conn->gensec,
543 : conn->sockets.raw,
544 : &conn->sockets.sasl);
545 25634 : if (!NT_STATUS_IS_OK(status)) {
546 0 : goto failed;
547 : }
548 :
549 25634 : conn->sockets.active = conn->sockets.sasl;
550 :
551 25634 : return NT_STATUS_OK;
552 :
553 543 : failed:
554 543 : talloc_free(tmp_ctx);
555 543 : talloc_free(conn->gensec);
556 543 : conn->gensec = NULL;
557 543 : return status;
558 : }
|