2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2001
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/>.
21 #include "../libcli/auth/spnego.h"
22 #include "auth/credentials/credentials.h"
23 #include "auth/gensec/gensec.h"
24 #include "auth_generic.h"
27 #include "system/gssapi.h"
28 #include "lib/param/loadparm.h"
32 static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
34 struct gensec_security *gensec_security =
35 talloc_get_type_abort(ads->ldap.wrap_private_data,
36 struct gensec_security);
38 DATA_BLOB unwrapped, wrapped;
39 TALLOC_CTX *frame = talloc_stackframe();
41 unwrapped = data_blob_const(buf, len);
43 nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped);
44 if (!NT_STATUS_IS_OK(nt_status)) {
46 return ADS_ERROR_NT(nt_status);
49 if ((ads->ldap.out.size - 4) < wrapped.length) {
51 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
54 /* copy the wrapped blob to the right location */
55 memcpy(ads->ldap.out.buf + 4, wrapped.data, wrapped.length);
57 /* set how many bytes must be written to the underlying socket */
58 ads->ldap.out.left = 4 + wrapped.length;
65 static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads)
67 struct gensec_security *gensec_security =
68 talloc_get_type_abort(ads->ldap.wrap_private_data,
69 struct gensec_security);
71 DATA_BLOB unwrapped, wrapped;
72 TALLOC_CTX *frame = talloc_stackframe();
74 wrapped = data_blob_const(ads->ldap.in.buf + 4, ads->ldap.in.ofs - 4);
76 nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
77 if (!NT_STATUS_IS_OK(nt_status)) {
79 return ADS_ERROR_NT(nt_status);
82 if (wrapped.length < unwrapped.length) {
84 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
87 /* copy the wrapped blob to the right location */
88 memcpy(ads->ldap.in.buf + 4, unwrapped.data, unwrapped.length);
90 /* set how many bytes must be written to the underlying socket */
91 ads->ldap.in.left = unwrapped.length;
99 static void ads_sasl_gensec_disconnect(ADS_STRUCT *ads)
101 struct gensec_security *gensec_security =
102 talloc_get_type_abort(ads->ldap.wrap_private_data,
103 struct gensec_security);
105 TALLOC_FREE(gensec_security);
107 ads->ldap.wrap_ops = NULL;
108 ads->ldap.wrap_private_data = NULL;
111 static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
113 .wrap = ads_sasl_gensec_wrap,
114 .unwrap = ads_sasl_gensec_unwrap,
115 .disconnect = ads_sasl_gensec_disconnect
119 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
120 we fit on one socket??)
122 static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
124 enum credentials_use_kerberos krb5_state,
125 const char *target_service,
126 const char *target_hostname,
127 const DATA_BLOB server_blob)
129 DATA_BLOB blob_in = data_blob_null;
130 DATA_BLOB blob_out = data_blob_null;
134 struct auth_generic_state *auth_generic_state;
135 bool use_spnego_principal = lp_client_use_spnego_principal();
136 const char *sasl_list[] = { sasl, NULL };
138 nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
139 if (!NT_STATUS_IS_OK(nt_status)) {
140 return ADS_ERROR_NT(nt_status);
143 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
144 return ADS_ERROR_NT(nt_status);
146 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
147 return ADS_ERROR_NT(nt_status);
149 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
150 return ADS_ERROR_NT(nt_status);
153 if (server_blob.length == 0) {
154 use_spnego_principal = false;
157 if (krb5_state == CRED_DONT_USE_KERBEROS) {
158 use_spnego_principal = false;
161 cli_credentials_set_kerberos_state(auth_generic_state->credentials,
164 if (target_service != NULL) {
165 nt_status = gensec_set_target_service(
166 auth_generic_state->gensec_security,
168 if (!NT_STATUS_IS_OK(nt_status)) {
169 return ADS_ERROR_NT(nt_status);
173 if (target_hostname != NULL) {
174 nt_status = gensec_set_target_hostname(
175 auth_generic_state->gensec_security,
177 if (!NT_STATUS_IS_OK(nt_status)) {
178 return ADS_ERROR_NT(nt_status);
182 if (target_service != NULL && target_hostname != NULL) {
183 use_spnego_principal = false;
186 switch (ads->ldap.wrap_type) {
187 case ADS_SASLWRAP_TYPE_SEAL:
188 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
189 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
191 case ADS_SASLWRAP_TYPE_SIGN:
192 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
193 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
196 * windows servers are broken with sign only,
197 * so we let the NTLMSSP backend to seal here,
198 * via GENSEC_FEATURE_LDAP_STYLE.
200 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
201 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
204 case ADS_SASLWRAP_TYPE_PLAIN:
208 nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
210 if (!NT_STATUS_IS_OK(nt_status)) {
211 return ADS_ERROR_NT(nt_status);
214 rc = LDAP_SASL_BIND_IN_PROGRESS;
215 nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
216 if (use_spnego_principal) {
217 blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
218 if (blob_in.length == 0) {
219 TALLOC_FREE(auth_generic_state);
220 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
223 blob_in = data_blob_null;
225 blob_out = data_blob_null;
228 struct berval cred, *scred = NULL;
230 nt_status = gensec_update(auth_generic_state->gensec_security,
231 talloc_tos(), blob_in, &blob_out);
232 data_blob_free(&blob_in);
233 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
234 && !NT_STATUS_IS_OK(nt_status))
236 TALLOC_FREE(auth_generic_state);
237 data_blob_free(&blob_out);
238 return ADS_ERROR_NT(nt_status);
241 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
245 cred.bv_val = (char *)blob_out.data;
246 cred.bv_len = blob_out.length;
248 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
249 data_blob_free(&blob_out);
250 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
255 TALLOC_FREE(auth_generic_state);
256 return ADS_ERROR(rc);
259 blob_in = data_blob_talloc(talloc_tos(),
262 if (blob_in.length != scred->bv_len) {
264 TALLOC_FREE(auth_generic_state);
265 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
269 blob_in = data_blob_null;
271 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
276 data_blob_free(&blob_in);
277 data_blob_free(&blob_out);
279 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
280 size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
281 ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);
283 ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
284 ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
285 ads->ldap.in.max_wrapped = max_wrapped;
286 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security);
287 if (!ADS_ERR_OK(status)) {
288 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
289 ads_errstr(status)));
290 TALLOC_FREE(auth_generic_state);
293 /* Only keep the gensec_security element around long-term */
294 talloc_steal(NULL, auth_generic_state->gensec_security);
296 TALLOC_FREE(auth_generic_state);
298 return ADS_ERROR(rc);
302 static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred)
306 krb5_error_code kerr;
307 krb5_ccache kccache = NULL;
310 *cred = GSS_C_NO_CREDENTIAL;
312 if (!ads->auth.ccache_name) {
316 kerr = krb5_init_context(&kctx);
318 return ADS_ERROR_KRB5(kerr);
321 #ifdef HAVE_GSS_KRB5_IMPORT_CRED
322 kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache);
324 status = ADS_ERROR_KRB5(kerr);
328 maj = gss_krb5_import_cred(&min, kccache, NULL, NULL, cred);
329 if (maj != GSS_S_COMPLETE) {
330 status = ADS_ERROR_GSS(maj, min);
334 /* We need to fallback to overriding the default creds.
335 * This operation is not thread safe as it changes the process
336 * environment variable, but we do not have any better option
337 * with older kerberos libraries */
339 const char *oldccname = NULL;
341 oldccname = getenv("KRB5CCNAME");
342 setenv("KRB5CCNAME", ads->auth.ccache_name, 1);
344 maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
345 NULL, GSS_C_INITIATE, cred, NULL, NULL);
348 setenv("KRB5CCNAME", oldccname, 1);
350 unsetenv("KRB5CCNAME");
353 if (maj != GSS_S_COMPLETE) {
354 status = ADS_ERROR_GSS(maj, min);
360 status = ADS_SUCCESS;
363 if (!ADS_ERR_OK(status) && kccache != NULL) {
364 krb5_cc_close(kctx, kccache);
366 krb5_free_context(kctx);
370 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
372 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
375 uint32_t minor_status;
376 gss_buffer_desc unwrapped, wrapped;
377 int conf_req_flag, conf_state;
379 unwrapped.value = buf;
380 unwrapped.length = len;
382 /* for now request sign and seal */
383 conf_req_flag = (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL);
385 gss_rc = gss_wrap(&minor_status, context_handle,
386 conf_req_flag, GSS_C_QOP_DEFAULT,
387 &unwrapped, &conf_state,
389 status = ADS_ERROR_GSS(gss_rc, minor_status);
390 if (!ADS_ERR_OK(status)) return status;
392 if (conf_req_flag && conf_state == 0) {
393 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
396 if ((ads->ldap.out.size - 4) < wrapped.length) {
397 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
400 /* copy the wrapped blob to the right location */
401 memcpy(ads->ldap.out.buf + 4, wrapped.value, wrapped.length);
403 /* set how many bytes must be written to the underlying socket */
404 ads->ldap.out.left = 4 + wrapped.length;
406 gss_release_buffer(&minor_status, &wrapped);
411 static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
413 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
416 uint32_t minor_status;
417 gss_buffer_desc unwrapped, wrapped;
420 wrapped.value = ads->ldap.in.buf + 4;
421 wrapped.length = ads->ldap.in.ofs - 4;
423 gss_rc = gss_unwrap(&minor_status, context_handle,
424 &wrapped, &unwrapped,
425 &conf_state, GSS_C_QOP_DEFAULT);
426 status = ADS_ERROR_GSS(gss_rc, minor_status);
427 if (!ADS_ERR_OK(status)) return status;
429 if (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
430 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
433 if (wrapped.length < unwrapped.length) {
434 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
437 /* copy the wrapped blob to the right location */
438 memcpy(ads->ldap.in.buf + 4, unwrapped.value, unwrapped.length);
440 /* set how many bytes must be written to the underlying socket */
441 ads->ldap.in.left = unwrapped.length;
442 ads->ldap.in.ofs = 4;
444 gss_release_buffer(&minor_status, &unwrapped);
449 static void ads_sasl_gssapi_disconnect(ADS_STRUCT *ads)
451 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
452 uint32_t minor_status;
454 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
456 ads->ldap.wrap_ops = NULL;
457 ads->ldap.wrap_private_data = NULL;
460 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
462 .wrap = ads_sasl_gssapi_wrap,
463 .unwrap = ads_sasl_gssapi_unwrap,
464 .disconnect = ads_sasl_gssapi_disconnect
468 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
470 static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
474 uint32_t minor_status;
476 gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
477 gss_OID_desc krb5_mech_type =
478 {9, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
479 gss_OID mech_type = &krb5_mech_type;
480 gss_OID actual_mech_type = GSS_C_NULL_OID;
481 const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
482 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
483 gss_buffer_desc input_token, output_token;
484 uint32_t req_flags, ret_flags;
485 uint32_t req_tmp, ret_tmp;
488 struct berval cred, *scred = NULL;
489 uint32_t context_validity = 0;
490 time_t context_endtime = 0;
492 status = ads_init_gssapi_cred(ads, &gss_cred);
493 if (!ADS_ERR_OK(status)) {
497 input_token.value = NULL;
498 input_token.length = 0;
500 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
501 switch (ads->ldap.wrap_type) {
502 case ADS_SASLWRAP_TYPE_SEAL:
503 req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
505 case ADS_SASLWRAP_TYPE_SIGN:
506 req_flags |= GSS_C_INTEG_FLAG;
508 case ADS_SASLWRAP_TYPE_PLAIN:
512 /* Note: here we explicit ask for the krb5 mech_type */
513 gss_rc = gss_init_sec_context(&minor_status,
526 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
527 status = ADS_ERROR_GSS(gss_rc, minor_status);
532 * As some gssapi krb5 mech implementations
533 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
534 * to req_flags internaly, it's not possible to
535 * use plain or signing only connection via
536 * the gssapi interface.
538 * Because of this we need to check it the ret_flags
539 * has more flags as req_flags and correct the value
540 * of ads->ldap.wrap_type.
542 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
543 * we need to give an error.
545 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
546 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
548 if (req_tmp == ret_tmp) {
549 /* everythings fine... */
551 } else if (req_flags & GSS_C_CONF_FLAG) {
553 * here we wanted sealing but didn't got it
554 * from the gssapi library
556 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
559 } else if ((req_flags & GSS_C_INTEG_FLAG) &&
560 !(ret_flags & GSS_C_INTEG_FLAG)) {
562 * here we wanted siging but didn't got it
563 * from the gssapi library
565 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
568 } else if (ret_flags & GSS_C_CONF_FLAG) {
570 * here we didn't want sealing
571 * but the gssapi library forces it
572 * so correct the needed wrap_type if
573 * the caller didn't forced siging only
575 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
576 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
580 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
581 req_flags = ret_flags;
583 } else if (ret_flags & GSS_C_INTEG_FLAG) {
585 * here we didn't want signing
586 * but the gssapi library forces it
587 * so correct the needed wrap_type if
588 * the caller didn't forced plain
590 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
591 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
595 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
596 req_flags = ret_flags;
599 * This could (should?) not happen
601 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
606 /* and wrap that in a shiny SPNEGO wrapper */
607 unwrapped = data_blob_const(output_token.value, output_token.length);
608 wrapped = spnego_gen_negTokenInit(talloc_tos(),
609 spnego_mechs, &unwrapped, NULL);
610 gss_release_buffer(&minor_status, &output_token);
611 if (unwrapped.length > wrapped.length) {
612 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
616 cred.bv_val = (char *)wrapped.data;
617 cred.bv_len = wrapped.length;
619 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL,
621 data_blob_free(&wrapped);
622 if (rc != LDAP_SUCCESS) {
623 status = ADS_ERROR(rc);
628 wrapped = data_blob_const(scred->bv_val, scred->bv_len);
630 wrapped = data_blob_null;
633 ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK,
636 if (scred) ber_bvfree(scred);
638 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
642 input_token.value = unwrapped.data;
643 input_token.length = unwrapped.length;
646 * As we asked for mutal authentication
647 * we need to pass the servers response
650 gss_rc = gss_init_sec_context(&minor_status,
663 data_blob_free(&unwrapped);
665 status = ADS_ERROR_GSS(gss_rc, minor_status);
669 gss_release_buffer(&minor_status, &output_token);
672 * If we the sign and seal options
673 * doesn't match after getting the response
674 * from the server, we don't want to use the connection
676 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
677 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
679 if (req_tmp != ret_tmp) {
680 /* everythings fine... */
681 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
686 gss_context_time(&minor_status, context_handle, &context_validity);
687 if (gss_rc == GSS_S_COMPLETE) {
688 if (context_validity != 0) {
689 context_endtime = time(NULL) + context_validity;
690 DEBUG(10, ("context (service ticket) valid for "
694 DEBUG(10, ("context (service ticket) expired\n"));
697 DEBUG(1, ("gss_context_time failed (%d,%u) -"
698 " this will be a one-time context\n",
699 gss_rc, minor_status));
700 if (gss_rc == GSS_S_CONTEXT_EXPIRED) {
701 DEBUG(10, ("context (service ticket) expired\n"));
705 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
706 uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
708 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
709 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
711 max_msg_size, &ads->ldap.out.max_unwrapped);
713 status = ADS_ERROR_GSS(gss_rc, minor_status);
717 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
718 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
719 ads->ldap.in.max_wrapped = max_msg_size;
720 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
721 if (!ADS_ERR_OK(status)) {
722 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
723 ads_errstr(status)));
726 /* make sure we don't free context_handle */
727 context_handle = GSS_C_NO_CONTEXT;
730 ads->auth.tgs_expire = context_endtime;
731 status = ADS_SUCCESS;
734 if (gss_cred != GSS_C_NO_CREDENTIAL)
735 gss_release_cred(&minor_status, &gss_cred);
736 if (context_handle != GSS_C_NO_CONTEXT)
737 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
741 #endif /* HAVE_KRB5 */
744 struct ads_service_principal {
751 static void ads_free_service_principal(struct ads_service_principal *p)
753 SAFE_FREE(p->string);
757 uint32_t minor_status;
758 gss_release_name(&minor_status, &p->name);
765 static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
766 char **returned_principal)
768 ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
775 frame = talloc_stackframe();
777 return ADS_ERROR(LDAP_NO_MEMORY);
780 if (ads->server.realm && ads->server.ldap_server) {
781 server = strlower_talloc(frame, ads->server.ldap_server);
782 if (server == NULL) {
786 realm = strupper_talloc(frame, ads->server.realm);
792 * If we got a name which is bigger than a NetBIOS name,
793 * but isn't a FQDN, create one.
795 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
798 dnsdomain = strlower_talloc(frame, ads->server.realm);
799 if (dnsdomain == NULL) {
803 server = talloc_asprintf(frame,
806 if (server == NULL) {
810 } else if (ads->config.realm && ads->config.ldap_server_name) {
811 server = strlower_talloc(frame, ads->config.ldap_server_name);
812 if (server == NULL) {
816 realm = strupper_talloc(frame, ads->config.realm);
822 * If we got a name which is bigger than a NetBIOS name,
823 * but isn't a FQDN, create one.
825 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
828 dnsdomain = strlower_talloc(frame, ads->server.realm);
829 if (dnsdomain == NULL) {
833 server = talloc_asprintf(frame,
836 if (server == NULL) {
842 if (server == NULL || realm == NULL) {
846 rc = asprintf(&princ, "ldap/%s@%s", server, realm);
847 if (rc == -1 || princ == NULL) {
848 status = ADS_ERROR(LDAP_PARAM_ERROR);
852 *returned_principal = princ;
854 status = ADS_SUCCESS;
860 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
861 struct ads_service_principal *p)
865 gss_buffer_desc input_name;
866 /* GSS_KRB5_NT_PRINCIPAL_NAME */
867 gss_OID_desc nt_principal =
868 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
869 uint32_t minor_status;
875 status = ads_guess_service_principal(ads, &p->string);
876 if (!ADS_ERR_OK(status)) {
881 input_name.value = p->string;
882 input_name.length = strlen(p->string);
884 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name);
886 ads_free_service_principal(p);
887 return ADS_ERROR_GSS(gss_rc, minor_status);
895 perform a LDAP/SASL/SPNEGO/KRB5 bind
897 static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
899 DATA_BLOB blob = data_blob_null;
900 struct berval cred, *scred = NULL;
901 DATA_BLOB session_key = data_blob_null;
904 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
905 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
908 rc = spnego_gen_krb5_negTokenInit(talloc_tos(), principal,
909 ads->auth.time_offset, &blob, &session_key, 0,
910 ads->auth.ccache_name,
911 &ads->auth.tgs_expire);
914 return ADS_ERROR_KRB5(rc);
917 /* now send the auth packet and we should be done */
918 cred.bv_val = (char *)blob.data;
919 cred.bv_len = blob.length;
921 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
923 data_blob_free(&blob);
924 data_blob_free(&session_key);
928 return ADS_ERROR(rc);
931 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
932 struct ads_service_principal *p)
936 * we only use the gsskrb5 based implementation
937 * when sasl sign or seal is requested.
939 * This has the following reasons:
940 * - it's likely that the gssapi krb5 mech implementation
941 * doesn't support to negotiate plain connections
942 * - the ads_sasl_spnego_rawkrb5_bind is more robust
943 * against clock skew errors
945 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
946 return ads_sasl_spnego_gsskrb5_bind(ads, p->name);
949 return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
951 #endif /* HAVE_KRB5 */
954 this performs a SASL/SPNEGO bind
956 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
958 struct berval *scred=NULL;
962 char *given_principal = NULL;
963 char *OIDs[ASN1_MAX_OIDS];
965 bool got_kerberos_mechanism = False;
968 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
970 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
971 status = ADS_ERROR(rc);
975 blob = data_blob(scred->bv_val, scred->bv_len);
980 file_save("sasl_spnego.dat", blob.data, blob.length);
983 /* the server sent us the first part of the SPNEGO exchange in the negprot
985 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
987 data_blob_free(&blob);
988 status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
991 data_blob_free(&blob);
992 TALLOC_FREE(given_principal);
994 /* make sure the server understands kerberos */
995 for (i=0;OIDs[i];i++) {
996 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
998 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
999 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
1000 got_kerberos_mechanism = True;
1003 talloc_free(OIDs[i]);
1007 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
1008 got_kerberos_mechanism)
1010 struct ads_service_principal p;
1012 status = ads_generate_service_principal(ads, &p);
1013 if (!ADS_ERR_OK(status)) {
1017 status = ads_sasl_spnego_krb5_bind(ads, &p);
1018 if (ADS_ERR_OK(status)) {
1019 ads_free_service_principal(&p);
1023 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
1024 "calling kinit\n", ads_errstr(status)));
1026 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
1028 if (ADS_ERR_OK(status)) {
1029 status = ads_sasl_spnego_krb5_bind(ads, &p);
1030 if (!ADS_ERR_OK(status)) {
1031 DEBUG(0,("kinit succeeded but "
1032 "ads_sasl_spnego_krb5_bind failed: %s\n",
1033 ads_errstr(status)));
1037 ads_free_service_principal(&p);
1039 /* only fallback to NTLMSSP if allowed */
1040 if (ADS_ERR_OK(status) ||
1041 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
1047 /* lets do NTLMSSP ... this has the big advantage that we don't need
1048 to sync clocks, and we don't rely on special versions of the krb5
1049 library for HMAC_MD4 encryption */
1050 return ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
1051 CRED_DONT_USE_KERBEROS,
1060 #define MAX_GSS_PASSES 3
1062 /* this performs a SASL/gssapi bind
1063 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
1064 is very dependent on correctly configured DNS whereas
1065 this routine is much less fragile
1066 see RFC2078 and RFC2222 for details
1068 static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
1070 uint32_t minor_status;
1071 gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
1072 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
1073 gss_OID mech_type = GSS_C_NULL_OID;
1074 gss_buffer_desc output_token, input_token;
1075 uint32_t req_flags, ret_flags;
1078 struct berval *scred = NULL;
1082 uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
1083 uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
1086 input_token.value = NULL;
1087 input_token.length = 0;
1089 status = ads_init_gssapi_cred(ads, &gss_cred);
1090 if (!ADS_ERR_OK(status)) {
1095 * Note: here we always ask the gssapi for sign and seal
1096 * as this is negotiated later after the mutal
1099 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
1101 for (i=0; i < MAX_GSS_PASSES; i++) {
1102 gss_rc = gss_init_sec_context(&minor_status,
1119 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
1120 status = ADS_ERROR_GSS(gss_rc, minor_status);
1124 cred.bv_val = (char *)output_token.value;
1125 cred.bv_len = output_token.length;
1127 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
1129 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
1130 status = ADS_ERROR(rc);
1134 if (output_token.value) {
1135 gss_release_buffer(&minor_status, &output_token);
1139 input_token.value = scred->bv_val;
1140 input_token.length = scred->bv_len;
1142 input_token.value = NULL;
1143 input_token.length = 0;
1146 if (gss_rc == 0) break;
1149 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
1156 status = ADS_ERROR_GSS(gss_rc, minor_status);
1160 p = (uint8_t *)output_token.value;
1163 file_save("sasl_gssapi.dat", output_token.value, output_token.length);
1167 wrap_type = CVAL(p,0);
1169 max_msg_size = RIVAL(p,0);
1172 gss_release_buffer(&minor_status, &output_token);
1174 if (!(wrap_type & ads->ldap.wrap_type)) {
1176 * the server doesn't supports the wrap
1179 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
1180 ads->ldap.wrap_type, wrap_type));
1181 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
1182 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
1186 /* 0x58 is the minimum windows accepts */
1187 if (max_msg_size < 0x58) {
1188 max_msg_size = 0x58;
1191 output_token.length = 4;
1192 output_token.value = SMB_MALLOC(output_token.length);
1193 if (!output_token.value) {
1194 output_token.length = 0;
1195 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
1198 p = (uint8_t *)output_token.value;
1200 RSIVAL(p,0,max_msg_size);
1201 SCVAL(p,0,ads->ldap.wrap_type);
1204 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
1205 * but using ads->config.bind_path is the wrong! It should be
1206 * the DN of the user object!
1208 * w2k3 gives an error when we send an incorrect DN, but sending nothing
1209 * is ok and matches the information flow used in GSS-SPNEGO.
1212 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
1213 &output_token, /* used as *input* here. */
1215 &input_token); /* Used as *output* here. */
1217 status = ADS_ERROR_GSS(gss_rc, minor_status);
1218 output_token.length = 0;
1219 SAFE_FREE(output_token.value);
1223 /* We've finished with output_token. */
1224 SAFE_FREE(output_token.value);
1225 output_token.length = 0;
1227 cred.bv_val = (char *)input_token.value;
1228 cred.bv_len = input_token.length;
1230 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
1232 gss_release_buffer(&minor_status, &input_token);
1233 status = ADS_ERROR(rc);
1234 if (!ADS_ERR_OK(status)) {
1238 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
1239 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
1240 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
1242 max_msg_size, &ads->ldap.out.max_unwrapped);
1244 status = ADS_ERROR_GSS(gss_rc, minor_status);
1248 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
1249 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
1250 ads->ldap.in.max_wrapped = max_msg_size;
1251 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
1252 if (!ADS_ERR_OK(status)) {
1253 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1254 ads_errstr(status)));
1257 /* make sure we don't free context_handle */
1258 context_handle = GSS_C_NO_CONTEXT;
1262 if (gss_cred != GSS_C_NO_CREDENTIAL)
1263 gss_release_cred(&minor_status, &gss_cred);
1264 if (context_handle != GSS_C_NO_CONTEXT)
1265 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
1272 static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
1275 struct ads_service_principal p;
1277 status = ads_generate_service_principal(ads, &p);
1278 if (!ADS_ERR_OK(status)) {
1282 status = ads_sasl_gssapi_do_bind(ads, p.name);
1283 if (ADS_ERR_OK(status)) {
1284 ads_free_service_principal(&p);
1288 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1289 "calling kinit\n", ads_errstr(status)));
1291 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
1293 if (ADS_ERR_OK(status)) {
1294 status = ads_sasl_gssapi_do_bind(ads, p.name);
1297 ads_free_service_principal(&p);
1302 #endif /* HAVE_KRB5 */
1304 /* mapping between SASL mechanisms and functions */
1307 ADS_STATUS (*fn)(ADS_STRUCT *);
1308 } sasl_mechanisms[] = {
1309 {"GSS-SPNEGO", ads_sasl_spnego_bind},
1311 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
1316 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
1318 const char *attrs[] = {"supportedSASLMechanisms", NULL};
1324 /* get a list of supported SASL mechanisms */
1325 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
1326 if (!ADS_ERR_OK(status)) return status;
1328 values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
1330 if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
1331 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
1332 } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
1333 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1335 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
1338 /* try our supported mechanisms in order */
1339 for (i=0;sasl_mechanisms[i].name;i++) {
1340 /* see if the server supports it */
1341 for (j=0;values && values[j];j++) {
1342 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
1343 DEBUG(4,("Found SASL mechanism %s\n", values[j]));
1345 status = sasl_mechanisms[i].fn(ads);
1346 if (status.error_type == ENUM_ADS_ERROR_LDAP &&
1347 status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
1348 ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
1350 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1351 "retrying with signing enabled\n"));
1352 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1355 ldap_value_free(values);
1362 ldap_value_free(values);
1364 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
1367 #endif /* HAVE_LDAP */