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 "../libcli/auth/ntlmssp.h"
26 static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
28 struct ntlmssp_state *ntlmssp_state =
29 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
34 uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
36 frame = talloc_stackframe();
37 /* copy the data to the right location */
38 memcpy(dptr, buf, len);
40 /* create the signature and may encrypt the data */
41 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
42 nt_status = ntlmssp_seal_packet(ntlmssp_state,
48 nt_status = ntlmssp_sign_packet(ntlmssp_state,
54 status = ADS_ERROR_NT(nt_status);
55 if (!ADS_ERR_OK(status)) return status;
57 /* copy the signature to the right location */
58 memcpy(ads->ldap.out.buf + 4,
59 sig.data, NTLMSSP_SIG_SIZE);
63 /* set how many bytes must be written to the underlying socket */
64 ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
69 static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
71 struct ntlmssp_state *ntlmssp_state =
72 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
76 uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
77 uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
79 /* wrap the signature into a DATA_BLOB */
80 sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
82 /* verify the signature and maybe decrypt the data */
83 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
84 nt_status = ntlmssp_unseal_packet(ntlmssp_state,
89 nt_status = ntlmssp_check_packet(ntlmssp_state,
94 status = ADS_ERROR_NT(nt_status);
95 if (!ADS_ERR_OK(status)) return status;
97 /* set the amount of bytes for the upper layer and set the ofs to the data */
98 ads->ldap.in.left = dlen;
99 ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE;
104 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
106 struct ntlmssp_state *ntlmssp_state =
107 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
109 TALLOC_FREE(ntlmssp_state);
111 ads->ldap.wrap_ops = NULL;
112 ads->ldap.wrap_private_data = NULL;
115 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
117 .wrap = ads_sasl_ntlmssp_wrap,
118 .unwrap = ads_sasl_ntlmssp_unwrap,
119 .disconnect = ads_sasl_ntlmssp_disconnect
123 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
124 we fit on one socket??)
126 static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
128 DATA_BLOB msg1 = data_blob_null;
129 DATA_BLOB blob = data_blob_null;
130 DATA_BLOB blob_in = data_blob_null;
131 DATA_BLOB blob_out = data_blob_null;
132 struct berval cred, *scred = NULL;
139 struct ntlmssp_state *ntlmssp_state;
141 nt_status = ntlmssp_client_start(NULL,
144 lp_client_ntlmv2_auth(),
146 if (!NT_STATUS_IS_OK(nt_status)) {
147 return ADS_ERROR_NT(nt_status);
149 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
151 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
152 return ADS_ERROR_NT(nt_status);
154 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
155 return ADS_ERROR_NT(nt_status);
157 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
158 return ADS_ERROR_NT(nt_status);
161 switch (ads->ldap.wrap_type) {
162 case ADS_SASLWRAP_TYPE_SEAL:
163 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
165 case ADS_SASLWRAP_TYPE_SIGN:
166 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
167 features = NTLMSSP_FEATURE_SIGN;
170 * windows servers are broken with sign only,
171 * so we need to use seal here too
173 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
174 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
177 case ADS_SASLWRAP_TYPE_PLAIN:
181 ntlmssp_want_feature(ntlmssp_state, features);
183 blob_in = data_blob_null;
186 nt_status = ntlmssp_update(ntlmssp_state,
188 data_blob_free(&blob_in);
189 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
190 || NT_STATUS_IS_OK(nt_status))
191 && blob_out.length) {
193 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
194 /* and wrap it in a SPNEGO wrapper */
195 msg1 = spnego_gen_negTokenInit(OIDs_ntlm, &blob_out, NULL);
197 /* wrap it in SPNEGO */
198 msg1 = spnego_gen_auth(blob_out);
201 data_blob_free(&blob_out);
203 cred.bv_val = (char *)msg1.data;
204 cred.bv_len = msg1.length;
206 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
207 data_blob_free(&msg1);
208 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
213 TALLOC_FREE(ntlmssp_state);
214 return ADS_ERROR(rc);
217 blob = data_blob(scred->bv_val, scred->bv_len);
220 blob = data_blob_null;
225 TALLOC_FREE(ntlmssp_state);
226 data_blob_free(&blob_out);
227 return ADS_ERROR_NT(nt_status);
231 (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
232 DATA_BLOB tmp_blob = data_blob_null;
233 /* the server might give us back two challenges */
234 if (!spnego_parse_challenge(blob, &blob_in,
237 TALLOC_FREE(ntlmssp_state);
238 data_blob_free(&blob);
239 DEBUG(3,("Failed to parse challenges\n"));
240 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
242 data_blob_free(&tmp_blob);
243 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
244 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
247 TALLOC_FREE(ntlmssp_state);
248 data_blob_free(&blob);
249 DEBUG(3,("Failed to parse auth response\n"));
250 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
253 data_blob_free(&blob);
254 data_blob_free(&blob_out);
256 } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
258 /* we have a reference conter on ntlmssp_state, if we are signing
259 then the state will be kept by the signing engine */
261 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
262 ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
263 ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
264 ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
265 ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
266 status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
267 if (!ADS_ERR_OK(status)) {
268 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
269 ads_errstr(status)));
270 TALLOC_FREE(ntlmssp_state);
274 TALLOC_FREE(ntlmssp_state);
277 return ADS_ERROR(rc);
281 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
283 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
287 gss_buffer_desc unwrapped, wrapped;
288 int conf_req_flag, conf_state;
290 unwrapped.value = buf;
291 unwrapped.length = len;
293 /* for now request sign and seal */
294 conf_req_flag = (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL);
296 gss_rc = gss_wrap(&minor_status, context_handle,
297 conf_req_flag, GSS_C_QOP_DEFAULT,
298 &unwrapped, &conf_state,
300 status = ADS_ERROR_GSS(gss_rc, minor_status);
301 if (!ADS_ERR_OK(status)) return status;
303 if (conf_req_flag && conf_state == 0) {
304 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
307 if ((ads->ldap.out.size - 4) < wrapped.length) {
308 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
311 /* copy the wrapped blob to the right location */
312 memcpy(ads->ldap.out.buf + 4, wrapped.value, wrapped.length);
314 /* set how many bytes must be written to the underlying socket */
315 ads->ldap.out.left = 4 + wrapped.length;
317 gss_release_buffer(&minor_status, &wrapped);
322 static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
324 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
328 gss_buffer_desc unwrapped, wrapped;
331 wrapped.value = ads->ldap.in.buf + 4;
332 wrapped.length = ads->ldap.in.ofs - 4;
334 gss_rc = gss_unwrap(&minor_status, context_handle,
335 &wrapped, &unwrapped,
336 &conf_state, GSS_C_QOP_DEFAULT);
337 status = ADS_ERROR_GSS(gss_rc, minor_status);
338 if (!ADS_ERR_OK(status)) return status;
340 if (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
341 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
344 if (wrapped.length < unwrapped.length) {
345 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
348 /* copy the wrapped blob to the right location */
349 memcpy(ads->ldap.in.buf + 4, unwrapped.value, unwrapped.length);
351 /* set how many bytes must be written to the underlying socket */
352 ads->ldap.in.left = unwrapped.length;
353 ads->ldap.in.ofs = 4;
355 gss_release_buffer(&minor_status, &unwrapped);
360 static void ads_sasl_gssapi_disconnect(ADS_STRUCT *ads)
362 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
365 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
367 ads->ldap.wrap_ops = NULL;
368 ads->ldap.wrap_private_data = NULL;
371 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
373 .wrap = ads_sasl_gssapi_wrap,
374 .unwrap = ads_sasl_gssapi_unwrap,
375 .disconnect = ads_sasl_gssapi_disconnect
379 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
381 static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
387 gss_OID_desc krb5_mech_type =
388 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
389 gss_OID mech_type = &krb5_mech_type;
390 gss_OID actual_mech_type = GSS_C_NULL_OID;
391 const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
392 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
393 gss_buffer_desc input_token, output_token;
394 uint32 req_flags, ret_flags;
395 uint32 req_tmp, ret_tmp;
398 struct berval cred, *scred = NULL;
400 input_token.value = NULL;
401 input_token.length = 0;
403 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
404 switch (ads->ldap.wrap_type) {
405 case ADS_SASLWRAP_TYPE_SEAL:
406 req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
408 case ADS_SASLWRAP_TYPE_SIGN:
409 req_flags |= GSS_C_INTEG_FLAG;
411 case ADS_SASLWRAP_TYPE_PLAIN:
415 /* Note: here we explicit ask for the krb5 mech_type */
416 gss_rc = gss_init_sec_context(&minor_status,
429 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
430 status = ADS_ERROR_GSS(gss_rc, minor_status);
435 * As some gssapi krb5 mech implementations
436 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
437 * to req_flags internaly, it's not possible to
438 * use plain or signing only connection via
439 * the gssapi interface.
441 * Because of this we need to check it the ret_flags
442 * has more flags as req_flags and correct the value
443 * of ads->ldap.wrap_type.
445 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
446 * we need to give an error.
448 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
449 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
451 if (req_tmp == ret_tmp) {
452 /* everythings fine... */
454 } else if (req_flags & GSS_C_CONF_FLAG) {
456 * here we wanted sealing but didn't got it
457 * from the gssapi library
459 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
462 } else if ((req_flags & GSS_C_INTEG_FLAG) &&
463 !(ret_flags & GSS_C_INTEG_FLAG)) {
465 * here we wanted siging but didn't got it
466 * from the gssapi library
468 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
471 } else if (ret_flags & GSS_C_CONF_FLAG) {
473 * here we didn't want sealing
474 * but the gssapi library forces it
475 * so correct the needed wrap_type if
476 * the caller didn't forced siging only
478 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
479 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
483 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
484 req_flags = ret_flags;
486 } else if (ret_flags & GSS_C_INTEG_FLAG) {
488 * here we didn't want signing
489 * but the gssapi library forces it
490 * so correct the needed wrap_type if
491 * the caller didn't forced plain
493 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
494 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
498 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
499 req_flags = ret_flags;
502 * This could (should?) not happen
504 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
509 /* and wrap that in a shiny SPNEGO wrapper */
510 unwrapped = data_blob_const(output_token.value, output_token.length);
511 wrapped = spnego_gen_negTokenInit(spnego_mechs, &unwrapped, NULL);
512 gss_release_buffer(&minor_status, &output_token);
513 if (unwrapped.length > wrapped.length) {
514 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
518 cred.bv_val = (char *)wrapped.data;
519 cred.bv_len = wrapped.length;
521 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL,
523 data_blob_free(&wrapped);
524 if (rc != LDAP_SUCCESS) {
525 status = ADS_ERROR(rc);
530 wrapped = data_blob_const(scred->bv_val, scred->bv_len);
532 wrapped = data_blob_null;
535 ok = spnego_parse_auth_response(wrapped, NT_STATUS_OK,
538 if (scred) ber_bvfree(scred);
540 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
544 input_token.value = unwrapped.data;
545 input_token.length = unwrapped.length;
548 * As we asked for mutal authentication
549 * we need to pass the servers response
552 gss_rc = gss_init_sec_context(&minor_status,
565 data_blob_free(&unwrapped);
567 status = ADS_ERROR_GSS(gss_rc, minor_status);
571 gss_release_buffer(&minor_status, &output_token);
574 * If we the sign and seal options
575 * doesn't match after getting the response
576 * from the server, we don't want to use the connection
578 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
579 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
581 if (req_tmp != ret_tmp) {
582 /* everythings fine... */
583 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
587 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
588 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
590 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
591 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
593 max_msg_size, &ads->ldap.out.max_unwrapped);
595 status = ADS_ERROR_GSS(gss_rc, minor_status);
599 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
600 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
601 ads->ldap.in.max_wrapped = max_msg_size;
602 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
603 if (!ADS_ERR_OK(status)) {
604 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
605 ads_errstr(status)));
608 /* make sure we don't free context_handle */
609 context_handle = GSS_C_NO_CONTEXT;
612 status = ADS_SUCCESS;
615 if (context_handle != GSS_C_NO_CONTEXT)
616 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
620 #endif /* HAVE_GSSAPI */
623 struct ads_service_principal {
630 static void ads_free_service_principal(struct ads_service_principal *p)
632 SAFE_FREE(p->string);
637 gss_release_name(&minor_status, &p->name);
643 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
644 const char *given_principal,
645 struct ads_service_principal *p)
649 gss_buffer_desc input_name;
650 /* GSS_KRB5_NT_PRINCIPAL_NAME */
651 gss_OID_desc nt_principal =
652 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
659 /* I've seen a child Windows 2000 domain not send
660 the principal name back in the first round of
661 the SASL bind reply. So we guess based on server
662 name and realm. --jerry */
663 /* Also try best guess when we get the w2k8 ignore
664 principal back - gd */
666 if (!given_principal ||
667 strequal(given_principal, ADS_IGNORE_PRINCIPAL)) {
669 status = ads_guess_service_principal(ads, &p->string);
670 if (!ADS_ERR_OK(status)) {
674 p->string = SMB_STRDUP(given_principal);
676 return ADS_ERROR(LDAP_NO_MEMORY);
681 input_name.value = p->string;
682 input_name.length = strlen(p->string);
684 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name);
686 ads_free_service_principal(p);
687 return ADS_ERROR_GSS(gss_rc, minor_status);
695 perform a LDAP/SASL/SPNEGO/KRB5 bind
697 static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
699 DATA_BLOB blob = data_blob_null;
700 struct berval cred, *scred = NULL;
701 DATA_BLOB session_key = data_blob_null;
704 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
705 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
708 rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
709 &ads->auth.tgs_expire);
712 return ADS_ERROR_KRB5(rc);
715 /* now send the auth packet and we should be done */
716 cred.bv_val = (char *)blob.data;
717 cred.bv_len = blob.length;
719 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
721 data_blob_free(&blob);
722 data_blob_free(&session_key);
726 return ADS_ERROR(rc);
729 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
730 struct ads_service_principal *p)
734 * we only use the gsskrb5 based implementation
735 * when sasl sign or seal is requested.
737 * This has the following reasons:
738 * - it's likely that the gssapi krb5 mech implementation
739 * doesn't support to negotiate plain connections
740 * - the ads_sasl_spnego_rawkrb5_bind is more robust
741 * against clock skew errors
743 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
744 return ads_sasl_spnego_gsskrb5_bind(ads, p->name);
747 return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
749 #endif /* HAVE_KRB5 */
752 this performs a SASL/SPNEGO bind
754 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
756 struct berval *scred=NULL;
760 char *given_principal = NULL;
761 char *OIDs[ASN1_MAX_OIDS];
763 bool got_kerberos_mechanism = False;
766 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
768 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
769 status = ADS_ERROR(rc);
773 blob = data_blob(scred->bv_val, scred->bv_len);
778 file_save("sasl_spnego.dat", blob.data, blob.length);
781 /* the server sent us the first part of the SPNEGO exchange in the negprot
783 if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal, NULL)) {
784 data_blob_free(&blob);
785 status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
788 data_blob_free(&blob);
790 /* make sure the server understands kerberos */
791 for (i=0;OIDs[i];i++) {
792 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
794 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
795 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
796 got_kerberos_mechanism = True;
799 talloc_free(OIDs[i]);
801 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));
804 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
805 got_kerberos_mechanism)
807 struct ads_service_principal p;
809 status = ads_generate_service_principal(ads, given_principal, &p);
810 TALLOC_FREE(given_principal);
811 if (!ADS_ERR_OK(status)) {
815 status = ads_sasl_spnego_krb5_bind(ads, &p);
816 if (ADS_ERR_OK(status)) {
817 ads_free_service_principal(&p);
821 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
822 "calling kinit\n", ads_errstr(status)));
824 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
826 if (ADS_ERR_OK(status)) {
827 status = ads_sasl_spnego_krb5_bind(ads, &p);
828 if (!ADS_ERR_OK(status)) {
829 DEBUG(0,("kinit succeeded but "
830 "ads_sasl_spnego_krb5_bind failed: %s\n",
831 ads_errstr(status)));
835 ads_free_service_principal(&p);
837 /* only fallback to NTLMSSP if allowed */
838 if (ADS_ERR_OK(status) ||
839 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
845 TALLOC_FREE(given_principal);
848 /* lets do NTLMSSP ... this has the big advantage that we don't need
849 to sync clocks, and we don't rely on special versions of the krb5
850 library for HMAC_MD4 encryption */
851 return ads_sasl_spnego_ntlmssp_bind(ads);
858 #define MAX_GSS_PASSES 3
860 /* this performs a SASL/gssapi bind
861 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
862 is very dependent on correctly configured DNS whereas
863 this routine is much less fragile
864 see RFC2078 and RFC2222 for details
866 static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
869 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
870 gss_OID mech_type = GSS_C_NULL_OID;
871 gss_buffer_desc output_token, input_token;
872 uint32 req_flags, ret_flags;
875 struct berval *scred = NULL;
879 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
880 uint8 wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
883 input_token.value = NULL;
884 input_token.length = 0;
887 * Note: here we always ask the gssapi for sign and seal
888 * as this is negotiated later after the mutal
891 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
893 for (i=0; i < MAX_GSS_PASSES; i++) {
894 gss_rc = gss_init_sec_context(&minor_status,
911 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
912 status = ADS_ERROR_GSS(gss_rc, minor_status);
916 cred.bv_val = (char *)output_token.value;
917 cred.bv_len = output_token.length;
919 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
921 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
922 status = ADS_ERROR(rc);
926 if (output_token.value) {
927 gss_release_buffer(&minor_status, &output_token);
931 input_token.value = scred->bv_val;
932 input_token.length = scred->bv_len;
934 input_token.value = NULL;
935 input_token.length = 0;
938 if (gss_rc == 0) break;
941 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
948 status = ADS_ERROR_GSS(gss_rc, minor_status);
952 p = (uint8 *)output_token.value;
955 file_save("sasl_gssapi.dat", output_token.value, output_token.length);
959 wrap_type = CVAL(p,0);
961 max_msg_size = RIVAL(p,0);
964 gss_release_buffer(&minor_status, &output_token);
966 if (!(wrap_type & ads->ldap.wrap_type)) {
968 * the server doesn't supports the wrap
971 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
972 ads->ldap.wrap_type, wrap_type));
973 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
974 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
978 /* 0x58 is the minimum windows accepts */
979 if (max_msg_size < 0x58) {
983 output_token.length = 4;
984 output_token.value = SMB_MALLOC(output_token.length);
985 p = (uint8 *)output_token.value;
987 RSIVAL(p,0,max_msg_size);
988 SCVAL(p,0,ads->ldap.wrap_type);
991 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
992 * but using ads->config.bind_path is the wrong! It should be
993 * the DN of the user object!
995 * w2k3 gives an error when we send an incorrect DN, but sending nothing
996 * is ok and matches the information flow used in GSS-SPNEGO.
999 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
1000 &output_token, &conf_state,
1003 status = ADS_ERROR_GSS(gss_rc, minor_status);
1007 free(output_token.value);
1009 cred.bv_val = (char *)input_token.value;
1010 cred.bv_len = input_token.length;
1012 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
1014 gss_release_buffer(&minor_status, &input_token);
1015 status = ADS_ERROR(rc);
1016 if (!ADS_ERR_OK(status)) {
1020 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
1021 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
1022 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
1024 max_msg_size, &ads->ldap.out.max_unwrapped);
1026 status = ADS_ERROR_GSS(gss_rc, minor_status);
1030 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
1031 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
1032 ads->ldap.in.max_wrapped = max_msg_size;
1033 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
1034 if (!ADS_ERR_OK(status)) {
1035 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1036 ads_errstr(status)));
1039 /* make sure we don't free context_handle */
1040 context_handle = GSS_C_NO_CONTEXT;
1045 if (context_handle != GSS_C_NO_CONTEXT)
1046 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
1053 static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
1056 struct ads_service_principal p;
1058 status = ads_generate_service_principal(ads, NULL, &p);
1059 if (!ADS_ERR_OK(status)) {
1063 status = ads_sasl_gssapi_do_bind(ads, p.name);
1064 if (ADS_ERR_OK(status)) {
1065 ads_free_service_principal(&p);
1069 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1070 "calling kinit\n", ads_errstr(status)));
1072 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
1074 if (ADS_ERR_OK(status)) {
1075 status = ads_sasl_gssapi_do_bind(ads, p.name);
1078 ads_free_service_principal(&p);
1083 #endif /* HAVE_GSSAPI */
1085 /* mapping between SASL mechanisms and functions */
1088 ADS_STATUS (*fn)(ADS_STRUCT *);
1089 } sasl_mechanisms[] = {
1090 {"GSS-SPNEGO", ads_sasl_spnego_bind},
1092 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
1097 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
1099 const char *attrs[] = {"supportedSASLMechanisms", NULL};
1105 /* get a list of supported SASL mechanisms */
1106 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
1107 if (!ADS_ERR_OK(status)) return status;
1109 values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
1111 if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
1112 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
1113 } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
1114 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1116 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
1119 /* try our supported mechanisms in order */
1120 for (i=0;sasl_mechanisms[i].name;i++) {
1121 /* see if the server supports it */
1122 for (j=0;values && values[j];j++) {
1123 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
1124 DEBUG(4,("Found SASL mechanism %s\n", values[j]));
1126 status = sasl_mechanisms[i].fn(ads);
1127 if (status.error_type == ENUM_ADS_ERROR_LDAP &&
1128 status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
1129 ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
1131 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1132 "retrying with signing enabled\n"));
1133 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1136 ldap_value_free(values);
1143 ldap_value_free(values);
1145 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
1148 #endif /* HAVE_LDAP */