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/>.
24 static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
26 struct ntlmssp_state *ntlmssp_state =
27 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
31 uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
33 /* copy the data to the right location */
34 memcpy(dptr, buf, len);
36 /* create the signature and may encrypt the data */
37 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
38 nt_status = ntlmssp_seal_packet(ntlmssp_state,
43 nt_status = ntlmssp_sign_packet(ntlmssp_state,
48 status = ADS_ERROR_NT(nt_status);
49 if (!ADS_ERR_OK(status)) return status;
51 /* copy the signature to the right location */
52 memcpy(ads->ldap.out.buf + 4,
53 sig.data, NTLMSSP_SIG_SIZE);
57 /* set how many bytes must be written to the underlying socket */
58 ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
63 static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
65 struct ntlmssp_state *ntlmssp_state =
66 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
70 uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
71 uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
73 /* wrap the signature into a DATA_BLOB */
74 sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
76 /* verify the signature and maybe decrypt the data */
77 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
78 nt_status = ntlmssp_unseal_packet(ntlmssp_state,
83 nt_status = ntlmssp_check_packet(ntlmssp_state,
88 status = ADS_ERROR_NT(nt_status);
89 if (!ADS_ERR_OK(status)) return status;
91 /* set the amount of bytes for the upper layer and set the ofs to the data */
92 ads->ldap.in.left = dlen;
93 ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE;
98 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
100 struct ntlmssp_state *ntlmssp_state =
101 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
103 ntlmssp_end(&ntlmssp_state);
105 ads->ldap.wrap_ops = NULL;
106 ads->ldap.wrap_private_data = NULL;
109 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
111 .wrap = ads_sasl_ntlmssp_wrap,
112 .unwrap = ads_sasl_ntlmssp_unwrap,
113 .disconnect = ads_sasl_ntlmssp_disconnect
117 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
118 we fit on one socket??)
120 static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
122 DATA_BLOB msg1 = data_blob_null;
123 DATA_BLOB blob = data_blob_null;
124 DATA_BLOB blob_in = data_blob_null;
125 DATA_BLOB blob_out = data_blob_null;
126 struct berval cred, *scred = NULL;
133 struct ntlmssp_state *ntlmssp_state;
135 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
136 return ADS_ERROR_NT(nt_status);
138 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
140 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
141 return ADS_ERROR_NT(nt_status);
143 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
144 return ADS_ERROR_NT(nt_status);
146 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
147 return ADS_ERROR_NT(nt_status);
150 switch (ads->ldap.wrap_type) {
151 case ADS_SASLWRAP_TYPE_SEAL:
152 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
154 case ADS_SASLWRAP_TYPE_SIGN:
155 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
156 features = NTLMSSP_FEATURE_SIGN;
159 * windows servers are broken with sign only,
160 * so we need to use seal here too
162 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
163 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
166 case ADS_SASLWRAP_TYPE_PLAIN:
170 ntlmssp_want_feature(ntlmssp_state, features);
172 blob_in = data_blob_null;
175 nt_status = ntlmssp_update(ntlmssp_state,
177 data_blob_free(&blob_in);
178 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
179 || NT_STATUS_IS_OK(nt_status))
180 && blob_out.length) {
182 /* and wrap it in a SPNEGO wrapper */
183 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
185 /* wrap it in SPNEGO */
186 msg1 = spnego_gen_auth(blob_out);
189 data_blob_free(&blob_out);
191 cred.bv_val = (char *)msg1.data;
192 cred.bv_len = msg1.length;
194 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
195 data_blob_free(&msg1);
196 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
201 ntlmssp_end(&ntlmssp_state);
202 return ADS_ERROR(rc);
205 blob = data_blob(scred->bv_val, scred->bv_len);
208 blob = data_blob_null;
213 ntlmssp_end(&ntlmssp_state);
214 data_blob_free(&blob_out);
215 return ADS_ERROR_NT(nt_status);
219 (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
220 DATA_BLOB tmp_blob = data_blob_null;
221 /* the server might give us back two challenges */
222 if (!spnego_parse_challenge(blob, &blob_in,
225 ntlmssp_end(&ntlmssp_state);
226 data_blob_free(&blob);
227 DEBUG(3,("Failed to parse challenges\n"));
228 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
230 data_blob_free(&tmp_blob);
231 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
232 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
235 ntlmssp_end(&ntlmssp_state);
236 data_blob_free(&blob);
237 DEBUG(3,("Failed to parse auth response\n"));
238 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
241 data_blob_free(&blob);
242 data_blob_free(&blob_out);
244 } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
246 /* we have a reference conter on ntlmssp_state, if we are signing
247 then the state will be kept by the signing engine */
249 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
250 ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
251 ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
252 ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
253 ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
254 status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
255 if (!ADS_ERR_OK(status)) {
256 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
257 ads_errstr(status)));
258 ntlmssp_end(&ntlmssp_state);
262 ntlmssp_end(&ntlmssp_state);
265 return ADS_ERROR(rc);
269 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
271 gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
275 gss_buffer_desc unwrapped, wrapped;
276 int conf_req_flag, conf_state;
278 unwrapped.value = buf;
279 unwrapped.length = len;
281 /* for now request sign and seal */
282 conf_req_flag = (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL);
284 gss_rc = gss_wrap(&minor_status, context_handle,
285 conf_req_flag, GSS_C_QOP_DEFAULT,
286 &unwrapped, &conf_state,
288 status = ADS_ERROR_GSS(gss_rc, minor_status);
289 if (!ADS_ERR_OK(status)) return status;
291 if (conf_req_flag && conf_state == 0) {
292 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
295 if ((ads->ldap.out.size - 4) < wrapped.length) {
296 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
299 /* copy the wrapped blob to the right location */
300 memcpy(ads->ldap.out.buf + 4, wrapped.value, wrapped.length);
302 /* set how many bytes must be written to the underlying socket */
303 ads->ldap.out.left = 4 + wrapped.length;
305 gss_release_buffer(&minor_status, &wrapped);
310 static ADS_STATUS ads_sasl_gssapi_unwrap(ADS_STRUCT *ads)
312 gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
316 gss_buffer_desc unwrapped, wrapped;
319 wrapped.value = ads->ldap.in.buf + 4;
320 wrapped.length = ads->ldap.in.ofs - 4;
322 gss_rc = gss_unwrap(&minor_status, context_handle,
323 &wrapped, &unwrapped,
324 &conf_state, GSS_C_QOP_DEFAULT);
325 status = ADS_ERROR_GSS(gss_rc, minor_status);
326 if (!ADS_ERR_OK(status)) return status;
328 if (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
329 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
332 if (wrapped.length < wrapped.length) {
333 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
336 /* copy the wrapped blob to the right location */
337 memcpy(ads->ldap.in.buf + 4, unwrapped.value, unwrapped.length);
339 /* set how many bytes must be written to the underlying socket */
340 ads->ldap.in.left = unwrapped.length;
341 ads->ldap.in.ofs = 4;
343 gss_release_buffer(&minor_status, &unwrapped);
348 static void ads_sasl_gssapi_disconnect(ADS_STRUCT *ads)
350 gss_ctx_id_t context_handle = ads->ldap.wrap_private_data;
353 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
355 ads->ldap.wrap_ops = NULL;
356 ads->ldap.wrap_private_data = NULL;
359 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
361 .wrap = ads_sasl_gssapi_wrap,
362 .unwrap = ads_sasl_gssapi_unwrap,
363 .disconnect = ads_sasl_gssapi_disconnect
367 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
369 static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
375 gss_OID_desc krb5_mech_type =
376 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
377 gss_OID mech_type = &krb5_mech_type;
378 gss_OID actual_mech_type = GSS_C_NULL_OID;
379 const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
380 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
381 gss_buffer_desc input_token, output_token;
382 uint32 req_flags, ret_flags;
383 uint32 req_tmp, ret_tmp;
386 struct berval cred, *scred = NULL;
388 input_token.value = NULL;
389 input_token.length = 0;
391 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
392 switch (ads->ldap.wrap_type) {
393 case ADS_SASLWRAP_TYPE_SEAL:
394 req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
396 case ADS_SASLWRAP_TYPE_SIGN:
397 req_flags |= GSS_C_INTEG_FLAG;
399 case ADS_SASLWRAP_TYPE_PLAIN:
403 /* Note: here we explicit ask for the krb5 mech_type */
404 gss_rc = gss_init_sec_context(&minor_status,
417 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
418 status = ADS_ERROR_GSS(gss_rc, minor_status);
423 * As some gssapi krb5 mech implementations
424 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
425 * to req_flags internaly, it's not possible to
426 * use plain or signing only connection via
427 * the gssapi interface.
429 * Because of this we need to check it the ret_flags
430 * has more flags as req_flags and correct the value
431 * of ads->ldap.wrap_type.
433 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
434 * we need to give an error.
436 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
437 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
439 if (req_tmp == ret_tmp) {
440 /* everythings fine... */
442 } else if (req_flags & GSS_C_CONF_FLAG) {
444 * here we wanted sealing but didn't got it
445 * from the gssapi library
447 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
450 } else if ((req_flags & GSS_C_INTEG_FLAG) &&
451 !(ret_flags & GSS_C_INTEG_FLAG)) {
453 * here we wanted siging but didn't got it
454 * from the gssapi library
456 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
459 } else if (ret_flags & GSS_C_CONF_FLAG) {
461 * here we didn't want sealing
462 * but the gssapi library forces it
463 * so correct the needed wrap_type if
464 * the caller didn't forced siging only
466 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
467 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
471 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
472 req_flags = ret_flags;
474 } else if (ret_flags & GSS_C_INTEG_FLAG) {
476 * here we didn't want signing
477 * but the gssapi library forces it
478 * so correct the needed wrap_type if
479 * the caller didn't forced plain
481 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
482 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
486 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
487 req_flags = ret_flags;
490 * This could (should?) not happen
492 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
497 /* and wrap that in a shiny SPNEGO wrapper */
498 unwrapped = data_blob_const(output_token.value, output_token.length);
499 wrapped = gen_negTokenTarg(spnego_mechs, unwrapped);
500 gss_release_buffer(&minor_status, &output_token);
501 if (unwrapped.length > wrapped.length) {
502 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
506 cred.bv_val = (char *)wrapped.data;
507 cred.bv_len = wrapped.length;
509 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL,
511 data_blob_free(&wrapped);
512 if (rc != LDAP_SUCCESS) {
513 status = ADS_ERROR(rc);
518 wrapped = data_blob_const(scred->bv_val, scred->bv_len);
520 wrapped = data_blob_null;
523 ok = spnego_parse_auth_response(wrapped, NT_STATUS_OK,
526 if (scred) ber_bvfree(scred);
528 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
532 input_token.value = unwrapped.data;
533 input_token.length = unwrapped.length;
536 * As we asked for mutal authentication
537 * we need to pass the servers response
540 gss_rc = gss_init_sec_context(&minor_status,
553 data_blob_free(&unwrapped);
555 status = ADS_ERROR_GSS(gss_rc, minor_status);
559 gss_release_buffer(&minor_status, &output_token);
562 * If we the sign and seal options
563 * doesn't match after getting the response
564 * from the server, we don't want to use the connection
566 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
567 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
569 if (req_tmp != ret_tmp) {
570 /* everythings fine... */
571 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
575 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
576 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
578 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
579 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
581 max_msg_size, &ads->ldap.out.max_unwrapped);
583 status = ADS_ERROR_GSS(gss_rc, minor_status);
587 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
588 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
589 ads->ldap.in.max_wrapped = max_msg_size;
590 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
591 if (!ADS_ERR_OK(status)) {
592 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
593 ads_errstr(status)));
596 /* make sure we don't free context_handle */
597 context_handle = GSS_C_NO_CONTEXT;
601 if (context_handle != GSS_C_NO_CONTEXT)
602 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
609 struct ads_service_principal {
612 krb5_principal principal;
618 static void ads_free_service_principal(struct ads_service_principal *p)
620 SAFE_FREE(p->string);
625 gss_release_name(&minor_status, &p->name);
629 krb5_free_principal(p->ctx, p->principal);
633 krb5_free_context(p->ctx);
639 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
640 const char *given_principal,
641 struct ads_service_principal *p)
644 krb5_enctype enc_types[] = {
645 #ifdef ENCTYPE_ARCFOUR_HMAC
646 ENCTYPE_ARCFOUR_HMAC,
651 gss_buffer_desc input_name;
652 gss_OID_desc nt_principal =
653 {10, CONST_DISCARD(char *, "\052\206\110\206\367\022\001\002\002\002")};
660 /* I've seen a child Windows 2000 domain not send
661 the principal name back in the first round of
662 the SASL bind reply. So we guess based on server
663 name and realm. --jerry */
664 if (given_principal) {
665 p->string = SMB_STRDUP(given_principal);
667 return ADS_ERROR(LDAP_NO_MEMORY);
669 } else if (ads->server.realm && ads->server.ldap_server) {
670 char *server, *server_realm;
672 server = SMB_STRDUP(ads->server.ldap_server);
673 server_realm = SMB_STRDUP(ads->server.realm);
675 if (!server || !server_realm) {
676 return ADS_ERROR(LDAP_NO_MEMORY);
680 strupper_m(server_realm);
681 asprintf(&p->string, "ldap/%s@%s", server, server_realm);
684 SAFE_FREE(server_realm);
687 return ADS_ERROR(LDAP_NO_MEMORY);
689 } else if (ads->config.realm && ads->config.ldap_server_name) {
690 char *server, *server_realm;
692 server = SMB_STRDUP(ads->config.ldap_server_name);
693 server_realm = SMB_STRDUP(ads->config.realm);
695 if (!server || !server_realm) {
696 return ADS_ERROR(LDAP_NO_MEMORY);
700 strupper_m(server_realm);
701 asprintf(&p->string, "ldap/%s@%s", server, server_realm);
704 SAFE_FREE(server_realm);
707 return ADS_ERROR(LDAP_NO_MEMORY);
711 initialize_krb5_error_table();
712 status = ADS_ERROR_KRB5(krb5_init_context(&p->ctx));
713 if (!ADS_ERR_OK(status)) {
714 ads_free_service_principal(p);
717 status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(p->ctx, enc_types));
718 if (!ADS_ERR_OK(status)) {
719 ads_free_service_principal(p);
722 status = ADS_ERROR_KRB5(smb_krb5_parse_name(p->ctx, p->string, &p->principal));
723 if (!ADS_ERR_OK(status)) {
724 ads_free_service_principal(p);
730 * The MIT libraries have a *HORRIBLE* bug - input_value.value needs
731 * to point to the *address* of the krb5_principal, and the gss libraries
732 * to a shallow copy of the krb5_principal pointer - so we need to keep
733 * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* !
734 * Just one more way in which MIT engineers screwed me over.... JRA.
736 * That's the reason for principal not beeing a local var in this function
738 input_name.value = &p->principal;
739 input_name.length = sizeof(p->principal);
741 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name);
743 ads_free_service_principal(p);
744 return ADS_ERROR_GSS(gss_rc, minor_status);
752 perform a LDAP/SASL/SPNEGO/KRB5 bind
754 static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
756 DATA_BLOB blob = data_blob_null;
757 struct berval cred, *scred = NULL;
758 DATA_BLOB session_key = data_blob_null;
761 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
762 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
765 rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
766 &ads->auth.tgs_expire);
769 return ADS_ERROR_KRB5(rc);
772 /* now send the auth packet and we should be done */
773 cred.bv_val = (char *)blob.data;
774 cred.bv_len = blob.length;
776 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
778 data_blob_free(&blob);
779 data_blob_free(&session_key);
783 return ADS_ERROR(rc);
786 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
787 struct ads_service_principal *p)
791 * we only use the gsskrb5 based implementation
792 * when sasl sign or seal is requested.
794 * This has the following reasons:
795 * - it's likely that the gssapi krb5 mech implementation
796 * doesn't support to negotiate plain connections
797 * - the ads_sasl_spnego_rawkrb5_bind is more robust
798 * against clock skew errors
800 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
801 return ads_sasl_spnego_gsskrb5_bind(ads, p->name);
804 return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
809 this performs a SASL/SPNEGO bind
811 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
813 struct berval *scred=NULL;
817 char *given_principal = NULL;
818 char *OIDs[ASN1_MAX_OIDS];
820 BOOL got_kerberos_mechanism = False;
823 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
825 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
826 status = ADS_ERROR(rc);
830 blob = data_blob(scred->bv_val, scred->bv_len);
835 file_save("sasl_spnego.dat", blob.data, blob.length);
838 /* the server sent us the first part of the SPNEGO exchange in the negprot
840 if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) {
841 data_blob_free(&blob);
842 status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
845 data_blob_free(&blob);
847 /* make sure the server understands kerberos */
848 for (i=0;OIDs[i];i++) {
849 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
851 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
852 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
853 got_kerberos_mechanism = True;
858 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));
861 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
862 got_kerberos_mechanism)
864 struct ads_service_principal p;
866 status = ads_generate_service_principal(ads, given_principal, &p);
867 SAFE_FREE(given_principal);
868 if (!ADS_ERR_OK(status)) {
872 status = ads_sasl_spnego_krb5_bind(ads, &p);
873 if (ADS_ERR_OK(status)) {
874 ads_free_service_principal(&p);
878 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
879 "calling kinit\n", ads_errstr(status)));
881 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
883 if (ADS_ERR_OK(status)) {
884 status = ads_sasl_spnego_krb5_bind(ads, &p);
887 ads_free_service_principal(&p);
889 /* only fallback to NTLMSSP if allowed */
890 if (ADS_ERR_OK(status) ||
891 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
897 SAFE_FREE(given_principal);
900 /* lets do NTLMSSP ... this has the big advantage that we don't need
901 to sync clocks, and we don't rely on special versions of the krb5
902 library for HMAC_MD4 encryption */
903 return ads_sasl_spnego_ntlmssp_bind(ads);
910 #define MAX_GSS_PASSES 3
912 /* this performs a SASL/gssapi bind
913 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
914 is very dependent on correctly configured DNS whereas
915 this routine is much less fragile
916 see RFC2078 and RFC2222 for details
918 static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
921 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
922 gss_OID mech_type = GSS_C_NULL_OID;
923 gss_buffer_desc output_token, input_token;
924 uint32 req_flags, ret_flags;
927 struct berval *scred = NULL;
931 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
932 uint8 wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
935 input_token.value = NULL;
936 input_token.length = 0;
939 * Note: here we always ask the gssapi for sign and seal
940 * as this is negotiated later after the mutal
943 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
945 for (i=0; i < MAX_GSS_PASSES; i++) {
946 gss_rc = gss_init_sec_context(&minor_status,
963 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
964 status = ADS_ERROR_GSS(gss_rc, minor_status);
968 cred.bv_val = (char *)output_token.value;
969 cred.bv_len = output_token.length;
971 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
973 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
974 status = ADS_ERROR(rc);
978 if (output_token.value) {
979 gss_release_buffer(&minor_status, &output_token);
983 input_token.value = scred->bv_val;
984 input_token.length = scred->bv_len;
986 input_token.value = NULL;
987 input_token.length = 0;
990 if (gss_rc == 0) break;
993 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
1000 status = ADS_ERROR_GSS(gss_rc, minor_status);
1004 p = (uint8 *)output_token.value;
1007 file_save("sasl_gssapi.dat", output_token.value, output_token.length);
1011 wrap_type = CVAL(p,0);
1013 max_msg_size = RIVAL(p,0);
1016 gss_release_buffer(&minor_status, &output_token);
1018 if (!(wrap_type & ads->ldap.wrap_type)) {
1020 * the server doesn't supports the wrap
1023 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
1024 ads->ldap.wrap_type, wrap_type));
1025 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
1026 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
1030 /* 0x58 is the minimum windows accepts */
1031 if (max_msg_size < 0x58) {
1032 max_msg_size = 0x58;
1035 output_token.length = 4;
1036 output_token.value = SMB_MALLOC(output_token.length);
1037 p = (uint8 *)output_token.value;
1039 RSIVAL(p,0,max_msg_size);
1040 SCVAL(p,0,ads->ldap.wrap_type);
1043 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
1044 * but using ads->config.bind_path is the wrong! It should be
1045 * the DN of the user object!
1047 * w2k3 gives an error when we send an incorrect DN, but sending nothing
1048 * is ok and matches the information flow used in GSS-SPNEGO.
1051 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
1052 &output_token, &conf_state,
1055 status = ADS_ERROR_GSS(gss_rc, minor_status);
1059 free(output_token.value);
1061 cred.bv_val = (char *)input_token.value;
1062 cred.bv_len = input_token.length;
1064 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
1066 gss_release_buffer(&minor_status, &input_token);
1067 status = ADS_ERROR(rc);
1068 if (!ADS_ERR_OK(status)) {
1072 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
1073 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
1074 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
1076 max_msg_size, &ads->ldap.out.max_unwrapped);
1078 status = ADS_ERROR_GSS(gss_rc, minor_status);
1082 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
1083 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
1084 ads->ldap.in.max_wrapped = max_msg_size;
1085 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
1086 if (!ADS_ERR_OK(status)) {
1087 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1088 ads_errstr(status)));
1091 /* make sure we don't free context_handle */
1092 context_handle = GSS_C_NO_CONTEXT;
1097 if (context_handle != GSS_C_NO_CONTEXT)
1098 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
1105 static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
1108 struct ads_service_principal p;
1110 status = ads_generate_service_principal(ads, NULL, &p);
1111 if (!ADS_ERR_OK(status)) {
1115 status = ads_sasl_gssapi_do_bind(ads, p.name);
1116 if (ADS_ERR_OK(status)) {
1117 ads_free_service_principal(&p);
1121 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1122 "calling kinit\n", ads_errstr(status)));
1124 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
1126 if (ADS_ERR_OK(status)) {
1127 status = ads_sasl_gssapi_do_bind(ads, p.name);
1130 ads_free_service_principal(&p);
1135 #endif /* HAVE_GGSAPI */
1137 /* mapping between SASL mechanisms and functions */
1140 ADS_STATUS (*fn)(ADS_STRUCT *);
1141 } sasl_mechanisms[] = {
1142 {"GSS-SPNEGO", ads_sasl_spnego_bind},
1144 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
1149 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
1151 const char *attrs[] = {"supportedSASLMechanisms", NULL};
1157 /* get a list of supported SASL mechanisms */
1158 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
1159 if (!ADS_ERR_OK(status)) return status;
1161 values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
1163 if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
1164 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
1165 } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
1166 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1168 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
1171 /* try our supported mechanisms in order */
1172 for (i=0;sasl_mechanisms[i].name;i++) {
1173 /* see if the server supports it */
1174 for (j=0;values && values[j];j++) {
1175 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
1176 DEBUG(4,("Found SASL mechanism %s\n", values[j]));
1177 status = sasl_mechanisms[i].fn(ads);
1178 ldap_value_free(values);
1185 ldap_value_free(values);
1187 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
1190 #endif /* HAVE_LDAP */