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 = ads->ldap.wrap_private_data;
30 uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
32 /* copy the data to the right location */
33 memcpy(dptr, buf, len);
35 /* create the signature and may encrypt the data */
36 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
37 nt_status = ntlmssp_seal_packet(ntlmssp_state,
42 nt_status = ntlmssp_sign_packet(ntlmssp_state,
47 status = ADS_ERROR_NT(nt_status);
48 if (!ADS_ERR_OK(status)) return status;
50 /* copy the signature to the right location */
51 memcpy(ads->ldap.out.buf + 4,
52 sig.data, NTLMSSP_SIG_SIZE);
56 /* set how many bytes must be written to the underlying socket */
57 ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
62 static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
64 struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
68 uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
69 uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
71 /* wrap the signature into a DATA_BLOB */
72 sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
74 /* verify the signature and maybe decrypt the data */
75 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
76 nt_status = ntlmssp_unseal_packet(ntlmssp_state,
81 nt_status = ntlmssp_check_packet(ntlmssp_state,
86 status = ADS_ERROR_NT(nt_status);
87 if (!ADS_ERR_OK(status)) return status;
89 /* set the amount of bytes for the upper layer and set the ofs to the data */
90 ads->ldap.in.left = dlen;
91 ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE;
96 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
98 struct ntlmssp_state *ntlmssp_state = ads->ldap.wrap_private_data;
100 ntlmssp_end(&ntlmssp_state);
102 ads->ldap.wrap_ops = NULL;
103 ads->ldap.wrap_private_data = NULL;
106 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
108 .wrap = ads_sasl_ntlmssp_wrap,
109 .unwrap = ads_sasl_ntlmssp_unwrap,
110 .disconnect = ads_sasl_ntlmssp_disconnect
114 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
115 we fit on one socket??)
117 static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
119 DATA_BLOB msg1 = data_blob_null;
120 DATA_BLOB blob = data_blob_null;
121 DATA_BLOB blob_in = data_blob_null;
122 DATA_BLOB blob_out = data_blob_null;
123 struct berval cred, *scred = NULL;
129 struct ntlmssp_state *ntlmssp_state;
131 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
132 return ADS_ERROR_NT(nt_status);
134 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
136 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
137 return ADS_ERROR_NT(nt_status);
139 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
140 return ADS_ERROR_NT(nt_status);
142 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
143 return ADS_ERROR_NT(nt_status);
146 switch (ads->ldap.wrap_type) {
147 case ADS_SASLWRAP_TYPE_SEAL:
148 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
150 case ADS_SASLWRAP_TYPE_SIGN:
151 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
152 features = NTLMSSP_FEATURE_SIGN;
155 * windows servers are broken with sign only,
156 * so we need to use seal here too
158 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
159 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
162 case ADS_SASLWRAP_TYPE_PLAIN:
166 ntlmssp_want_feature(ntlmssp_state, features);
168 blob_in = data_blob_null;
171 nt_status = ntlmssp_update(ntlmssp_state,
173 data_blob_free(&blob_in);
174 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
175 || NT_STATUS_IS_OK(nt_status))
176 && blob_out.length) {
178 /* and wrap it in a SPNEGO wrapper */
179 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
181 /* wrap it in SPNEGO */
182 msg1 = spnego_gen_auth(blob_out);
185 data_blob_free(&blob_out);
187 cred.bv_val = (char *)msg1.data;
188 cred.bv_len = msg1.length;
190 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
191 data_blob_free(&msg1);
192 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
197 ntlmssp_end(&ntlmssp_state);
198 return ADS_ERROR(rc);
201 blob = data_blob(scred->bv_val, scred->bv_len);
204 blob = data_blob_null;
209 ntlmssp_end(&ntlmssp_state);
210 data_blob_free(&blob_out);
211 return ADS_ERROR_NT(nt_status);
215 (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
216 DATA_BLOB tmp_blob = data_blob_null;
217 /* the server might give us back two challenges */
218 if (!spnego_parse_challenge(blob, &blob_in,
221 ntlmssp_end(&ntlmssp_state);
222 data_blob_free(&blob);
223 DEBUG(3,("Failed to parse challenges\n"));
224 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
226 data_blob_free(&tmp_blob);
227 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
228 if (!spnego_parse_auth_response(blob, nt_status, OID_NTLMSSP,
231 ntlmssp_end(&ntlmssp_state);
232 data_blob_free(&blob);
233 DEBUG(3,("Failed to parse auth response\n"));
234 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
237 data_blob_free(&blob);
238 data_blob_free(&blob_out);
240 } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
242 /* we have a reference conter on ntlmssp_state, if we are signing
243 then the state will be kept by the signing engine */
245 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
246 ads->ldap.out.min = 4;
247 ads->ldap.out.max = 0x0FFFFFFF - NTLMSSP_SIG_SIZE;
248 ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
249 ads->ldap.in.min = 4;
250 ads->ldap.in.max = 0x0FFFFFFF;
251 ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
253 ntlmssp_end(&ntlmssp_state);
256 return ADS_ERROR(rc);
261 perform a LDAP/SASL/SPNEGO/KRB5 bind
263 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *principal)
265 DATA_BLOB blob = data_blob_null;
266 struct berval cred, *scred = NULL;
267 DATA_BLOB session_key = data_blob_null;
270 rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0,
271 &ads->auth.tgs_expire);
274 return ADS_ERROR_KRB5(rc);
277 /* now send the auth packet and we should be done */
278 cred.bv_val = (char *)blob.data;
279 cred.bv_len = blob.length;
281 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
283 data_blob_free(&blob);
284 data_blob_free(&session_key);
288 return ADS_ERROR(rc);
293 this performs a SASL/SPNEGO bind
295 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
297 struct berval *scred=NULL;
301 char *principal = NULL;
302 char *OIDs[ASN1_MAX_OIDS];
304 BOOL got_kerberos_mechanism = False;
307 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
309 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
310 status = ADS_ERROR(rc);
314 blob = data_blob(scred->bv_val, scred->bv_len);
319 file_save("sasl_spnego.dat", blob.data, blob.length);
322 /* the server sent us the first part of the SPNEGO exchange in the negprot
324 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
325 data_blob_free(&blob);
326 status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
329 data_blob_free(&blob);
331 /* make sure the server understands kerberos */
332 for (i=0;OIDs[i];i++) {
333 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
335 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
336 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
337 got_kerberos_mechanism = True;
342 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", principal));
345 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
346 got_kerberos_mechanism)
348 /* I've seen a child Windows 2000 domain not send
349 the principal name back in the first round of
350 the SASL bind reply. So we guess based on server
351 name and realm. --jerry */
353 if ( ads->server.realm && ads->server.ldap_server ) {
354 char *server, *server_realm;
356 server = SMB_STRDUP( ads->server.ldap_server );
357 server_realm = SMB_STRDUP( ads->server.realm );
359 if ( !server || !server_realm )
360 return ADS_ERROR(LDAP_NO_MEMORY);
362 strlower_m( server );
363 strupper_m( server_realm );
364 asprintf( &principal, "ldap/%s@%s", server, server_realm );
367 SAFE_FREE( server_realm );
370 return ADS_ERROR(LDAP_NO_MEMORY);
375 status = ads_sasl_spnego_krb5_bind(ads, principal);
376 if (ADS_ERR_OK(status)) {
377 SAFE_FREE(principal);
381 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
382 "calling kinit\n", ads_errstr(status)));
384 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
386 if (ADS_ERR_OK(status)) {
387 status = ads_sasl_spnego_krb5_bind(ads, principal);
390 /* only fallback to NTLMSSP if allowed */
391 if (ADS_ERR_OK(status) ||
392 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
393 SAFE_FREE(principal);
399 SAFE_FREE(principal);
401 /* lets do NTLMSSP ... this has the big advantage that we don't need
402 to sync clocks, and we don't rely on special versions of the krb5
403 library for HMAC_MD4 encryption */
404 return ads_sasl_spnego_ntlmssp_bind(ads);
411 #define MAX_GSS_PASSES 3
413 /* this performs a SASL/gssapi bind
414 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
415 is very dependent on correctly configured DNS whereas
416 this routine is much less fragile
417 see RFC2078 and RFC2222 for details
419 static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
422 gss_name_t serv_name;
423 gss_buffer_desc input_name;
424 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
425 gss_OID mech_type = GSS_C_NULL_OID;
426 gss_buffer_desc output_token, input_token;
427 uint32 ret_flags, conf_state;
429 struct berval *scred = NULL;
433 uint32 max_msg_size = 0;
436 krb5_principal principal = NULL;
437 krb5_context ctx = NULL;
438 krb5_enctype enc_types[] = {
439 #ifdef ENCTYPE_ARCFOUR_HMAC
440 ENCTYPE_ARCFOUR_HMAC,
444 gss_OID_desc nt_principal =
445 {10, CONST_DISCARD(char *, "\052\206\110\206\367\022\001\002\002\002")};
447 /* we need to fetch a service ticket as the ldap user in the
448 servers realm, regardless of our realm */
449 asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm);
451 initialize_krb5_error_table();
452 status = ADS_ERROR_KRB5(krb5_init_context(&ctx));
453 if (!ADS_ERR_OK(status)) {
457 status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types));
458 if (!ADS_ERR_OK(status)) {
460 krb5_free_context(ctx);
463 status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal));
464 if (!ADS_ERR_OK(status)) {
466 krb5_free_context(ctx);
470 input_name.value = &principal;
471 input_name.length = sizeof(principal);
473 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name);
476 * The MIT libraries have a *HORRIBLE* bug - input_value.value needs
477 * to point to the *address* of the krb5_principal, and the gss libraries
478 * to a shallow copy of the krb5_principal pointer - so we need to keep
479 * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* !
480 * Just one more way in which MIT engineers screwed me over.... JRA.
486 krb5_free_principal(ctx, principal);
487 krb5_free_context(ctx);
488 return ADS_ERROR_GSS(gss_rc, minor_status);
491 input_token.value = NULL;
492 input_token.length = 0;
494 for (i=0; i < MAX_GSS_PASSES; i++) {
495 gss_rc = gss_init_sec_context(&minor_status,
500 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
509 if (input_token.value) {
510 gss_release_buffer(&minor_status, &input_token);
513 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
514 status = ADS_ERROR_GSS(gss_rc, minor_status);
518 cred.bv_val = (char *)output_token.value;
519 cred.bv_len = output_token.length;
521 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
523 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
524 status = ADS_ERROR(rc);
528 if (output_token.value) {
529 gss_release_buffer(&minor_status, &output_token);
533 input_token.value = scred->bv_val;
534 input_token.length = scred->bv_len;
536 input_token.value = NULL;
537 input_token.length = 0;
540 if (gss_rc == 0) break;
543 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
544 (int *)&conf_state,NULL);
546 status = ADS_ERROR_GSS(gss_rc, minor_status);
550 gss_release_buffer(&minor_status, &input_token);
552 p = (uint8 *)output_token.value;
555 file_save("sasl_gssapi.dat", output_token.value, output_token.length);
559 max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
562 gss_release_buffer(&minor_status, &output_token);
564 output_token.length = 4;
565 output_token.value = SMB_MALLOC(output_token.length);
566 p = (uint8 *)output_token.value;
568 *p++ = 1; /* no sign & seal selection */
569 /* choose the same size as the server gave us */
570 *p++ = max_msg_size>>16;
571 *p++ = max_msg_size>>8;
574 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
575 * but using ads->config.bind_path is the wrong! It should be
576 * the DN of the user object!
578 * w2k3 gives an error when we send an incorrect DN, but sending nothing
579 * is ok and matches the information flow used in GSS-SPNEGO.
582 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
583 &output_token, (int *)&conf_state,
586 status = ADS_ERROR_GSS(gss_rc, minor_status);
590 free(output_token.value);
592 cred.bv_val = (char *)input_token.value;
593 cred.bv_len = input_token.length;
595 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
597 status = ADS_ERROR(rc);
599 gss_release_buffer(&minor_status, &input_token);
603 gss_release_name(&minor_status, &serv_name);
604 if (context_handle != GSS_C_NO_CONTEXT)
605 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
606 krb5_free_principal(ctx, principal);
607 krb5_free_context(ctx);
613 #endif /* HAVE_GGSAPI */
615 /* mapping between SASL mechanisms and functions */
618 ADS_STATUS (*fn)(ADS_STRUCT *);
619 } sasl_mechanisms[] = {
620 {"GSS-SPNEGO", ads_sasl_spnego_bind},
622 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
627 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
629 const char *attrs[] = {"supportedSASLMechanisms", NULL};
635 /* get a list of supported SASL mechanisms */
636 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
637 if (!ADS_ERR_OK(status)) return status;
639 values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
641 if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
642 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
643 } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
644 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
646 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
649 /* try our supported mechanisms in order */
650 for (i=0;sasl_mechanisms[i].name;i++) {
651 /* see if the server supports it */
652 for (j=0;values && values[j];j++) {
653 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
654 DEBUG(4,("Found SASL mechanism %s\n", values[j]));
655 status = sasl_mechanisms[i].fn(ads);
656 ldap_value_free(values);
663 ldap_value_free(values);
665 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
668 #endif /* HAVE_LDAP */