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"
33 static ADS_STATUS
ads_sasl_gensec_wrap(ADS_STRUCT
*ads
, uint8_t *buf
, uint32_t len
)
35 struct gensec_security
*gensec_security
=
36 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
37 struct gensec_security
);
39 DATA_BLOB unwrapped
, wrapped
;
40 TALLOC_CTX
*frame
= talloc_stackframe();
42 unwrapped
= data_blob_const(buf
, len
);
44 nt_status
= gensec_wrap(gensec_security
, frame
, &unwrapped
, &wrapped
);
45 if (!NT_STATUS_IS_OK(nt_status
)) {
47 return ADS_ERROR_NT(nt_status
);
50 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
52 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
55 /* copy the wrapped blob to the right location */
56 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.data
, wrapped
.length
);
58 /* set how many bytes must be written to the underlying socket */
59 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
66 static ADS_STATUS
ads_sasl_gensec_unwrap(ADS_STRUCT
*ads
)
68 struct gensec_security
*gensec_security
=
69 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
70 struct gensec_security
);
72 DATA_BLOB unwrapped
, wrapped
;
73 TALLOC_CTX
*frame
= talloc_stackframe();
75 wrapped
= data_blob_const(ads
->ldap
.in
.buf
+ 4, ads
->ldap
.in
.ofs
- 4);
77 nt_status
= gensec_unwrap(gensec_security
, frame
, &wrapped
, &unwrapped
);
78 if (!NT_STATUS_IS_OK(nt_status
)) {
80 return ADS_ERROR_NT(nt_status
);
83 if (wrapped
.length
< unwrapped
.length
) {
85 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
88 /* copy the wrapped blob to the right location */
89 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.data
, unwrapped
.length
);
91 /* set how many bytes must be written to the underlying socket */
92 ads
->ldap
.in
.left
= unwrapped
.length
;
100 static void ads_sasl_gensec_disconnect(ADS_STRUCT
*ads
)
102 struct gensec_security
*gensec_security
=
103 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
104 struct gensec_security
);
106 TALLOC_FREE(gensec_security
);
108 ads
->ldap
.wrap_ops
= NULL
;
109 ads
->ldap
.wrap_private_data
= NULL
;
112 static const struct ads_saslwrap_ops ads_sasl_gensec_ops
= {
114 .wrap
= ads_sasl_gensec_wrap
,
115 .unwrap
= ads_sasl_gensec_unwrap
,
116 .disconnect
= ads_sasl_gensec_disconnect
120 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
121 we fit on one socket??)
123 static ADS_STATUS
ads_sasl_spnego_gensec_bind(ADS_STRUCT
*ads
,
125 enum credentials_use_kerberos krb5_state
,
126 const char *target_service
,
127 const char *target_hostname
,
128 const DATA_BLOB server_blob
)
130 DATA_BLOB blob_in
= data_blob_null
;
131 DATA_BLOB blob_out
= data_blob_null
;
135 struct auth_generic_state
*auth_generic_state
;
136 bool use_spnego_principal
= lp_client_use_spnego_principal();
137 const char *sasl_list
[] = { sasl
, NULL
};
140 nt_status
= auth_generic_client_prepare(NULL
, &auth_generic_state
);
141 if (!NT_STATUS_IS_OK(nt_status
)) {
142 return ADS_ERROR_NT(nt_status
);
145 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_username(auth_generic_state
, ads
->auth
.user_name
))) {
146 return ADS_ERROR_NT(nt_status
);
148 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_domain(auth_generic_state
, ads
->auth
.realm
))) {
149 return ADS_ERROR_NT(nt_status
);
151 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_password(auth_generic_state
, ads
->auth
.password
))) {
152 return ADS_ERROR_NT(nt_status
);
155 if (server_blob
.length
== 0) {
156 use_spnego_principal
= false;
159 if (krb5_state
== CRED_DONT_USE_KERBEROS
) {
160 use_spnego_principal
= false;
163 cli_credentials_set_kerberos_state(auth_generic_state
->credentials
,
166 if (target_service
!= NULL
) {
167 nt_status
= gensec_set_target_service(
168 auth_generic_state
->gensec_security
,
170 if (!NT_STATUS_IS_OK(nt_status
)) {
171 return ADS_ERROR_NT(nt_status
);
175 if (target_hostname
!= NULL
) {
176 nt_status
= gensec_set_target_hostname(
177 auth_generic_state
->gensec_security
,
179 if (!NT_STATUS_IS_OK(nt_status
)) {
180 return ADS_ERROR_NT(nt_status
);
184 if (target_service
!= NULL
&& target_hostname
!= NULL
) {
185 use_spnego_principal
= false;
188 switch (ads
->ldap
.wrap_type
) {
189 case ADS_SASLWRAP_TYPE_SEAL
:
190 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
191 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SEAL
);
193 case ADS_SASLWRAP_TYPE_SIGN
:
194 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
195 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
198 * windows servers are broken with sign only,
199 * so we let the NTLMSSP backend to seal here,
200 * via GENSEC_FEATURE_LDAP_STYLE.
202 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
203 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_LDAP_STYLE
);
206 case ADS_SASLWRAP_TYPE_PLAIN
:
210 nt_status
= auth_generic_client_start_by_sasl(auth_generic_state
,
212 if (!NT_STATUS_IS_OK(nt_status
)) {
213 return ADS_ERROR_NT(nt_status
);
216 rc
= LDAP_SASL_BIND_IN_PROGRESS
;
217 nt_status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
218 if (use_spnego_principal
) {
219 blob_in
= data_blob_dup_talloc(talloc_tos(), server_blob
);
220 if (blob_in
.length
== 0) {
221 TALLOC_FREE(auth_generic_state
);
222 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
225 blob_in
= data_blob_null
;
227 blob_out
= data_blob_null
;
230 struct berval cred
, *scred
= NULL
;
232 nt_status
= gensec_update(auth_generic_state
->gensec_security
,
233 talloc_tos(), blob_in
, &blob_out
);
234 data_blob_free(&blob_in
);
235 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
236 && !NT_STATUS_IS_OK(nt_status
))
238 TALLOC_FREE(auth_generic_state
);
239 data_blob_free(&blob_out
);
240 return ADS_ERROR_NT(nt_status
);
243 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_out
.length
== 0) {
247 cred
.bv_val
= (char *)blob_out
.data
;
248 cred
.bv_len
= blob_out
.length
;
250 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, sasl
, &cred
, NULL
, NULL
, &scred
);
251 data_blob_free(&blob_out
);
252 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
257 TALLOC_FREE(auth_generic_state
);
258 return ADS_ERROR(rc
);
261 blob_in
= data_blob_talloc(talloc_tos(),
264 if (blob_in
.length
!= scred
->bv_len
) {
266 TALLOC_FREE(auth_generic_state
);
267 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
271 blob_in
= data_blob_null
;
273 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_in
.length
== 0) {
278 data_blob_free(&blob_in
);
279 data_blob_free(&blob_out
);
281 if (ads
->ldap
.wrap_type
>= ADS_SASLWRAP_TYPE_SEAL
) {
284 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
285 GENSEC_FEATURE_SEAL
);
287 DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
288 TALLOC_FREE(auth_generic_state
);
289 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
292 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
293 GENSEC_FEATURE_SIGN
);
295 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
296 TALLOC_FREE(auth_generic_state
);
297 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
300 } else if (ads
->ldap
.wrap_type
>= ADS_SASLWRAP_TYPE_SIGN
) {
303 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
304 GENSEC_FEATURE_SIGN
);
306 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
307 TALLOC_FREE(auth_generic_state
);
308 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
312 ads
->auth
.tgs_expire
= LONG_MAX
;
313 end_nt_time
= gensec_expire_time(auth_generic_state
->gensec_security
);
314 if (end_nt_time
!= GENSEC_EXPIRE_TIME_INFINITY
) {
316 nttime_to_timeval(&tv
, end_nt_time
);
317 ads
->auth
.tgs_expire
= tv
.tv_sec
;
320 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
321 size_t max_wrapped
= gensec_max_wrapped_size(auth_generic_state
->gensec_security
);
322 ads
->ldap
.out
.max_unwrapped
= gensec_max_input_size(auth_generic_state
->gensec_security
);
324 ads
->ldap
.out
.sig_size
= max_wrapped
- ads
->ldap
.out
.max_unwrapped
;
326 * Note that we have to truncate this to 0x2C
327 * (taken from a capture with LDAP unbind), as the
328 * signature size is not constant for Kerberos with
331 ads
->ldap
.in
.min_wrapped
= MIN(ads
->ldap
.out
.sig_size
, 0x2C);
332 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
333 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gensec_ops
, auth_generic_state
->gensec_security
);
334 if (!ADS_ERR_OK(status
)) {
335 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
336 ads_errstr(status
)));
337 TALLOC_FREE(auth_generic_state
);
340 /* Only keep the gensec_security element around long-term */
341 talloc_steal(NULL
, auth_generic_state
->gensec_security
);
343 TALLOC_FREE(auth_generic_state
);
345 return ADS_ERROR(rc
);
349 static ADS_STATUS
ads_init_gssapi_cred(ADS_STRUCT
*ads
, gss_cred_id_t
*cred
)
353 krb5_error_code kerr
;
354 krb5_ccache kccache
= NULL
;
357 *cred
= GSS_C_NO_CREDENTIAL
;
359 if (!ads
->auth
.ccache_name
) {
363 kerr
= krb5_init_context(&kctx
);
365 return ADS_ERROR_KRB5(kerr
);
368 kerr
= krb5_cc_resolve(kctx
, ads
->auth
.ccache_name
, &kccache
);
370 status
= ADS_ERROR_KRB5(kerr
);
374 maj
= smb_gss_krb5_import_cred(&min
, kctx
, kccache
, NULL
, NULL
, cred
);
375 if (maj
!= GSS_S_COMPLETE
) {
376 status
= ADS_ERROR_GSS(maj
, min
);
380 status
= ADS_SUCCESS
;
383 if (!ADS_ERR_OK(status
) && kccache
!= NULL
) {
384 krb5_cc_close(kctx
, kccache
);
386 krb5_free_context(kctx
);
390 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8_t *buf
, uint32_t len
)
392 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
395 uint32_t minor_status
;
396 gss_buffer_desc unwrapped
, wrapped
;
397 int conf_req_flag
, conf_state
;
399 unwrapped
.value
= buf
;
400 unwrapped
.length
= len
;
402 /* for now request sign and seal */
403 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
405 gss_rc
= gss_wrap(&minor_status
, context_handle
,
406 conf_req_flag
, GSS_C_QOP_DEFAULT
,
407 &unwrapped
, &conf_state
,
409 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
410 if (!ADS_ERR_OK(status
)) return status
;
412 if (conf_req_flag
&& conf_state
== 0) {
413 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
416 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
417 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
420 /* copy the wrapped blob to the right location */
421 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
423 /* set how many bytes must be written to the underlying socket */
424 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
426 gss_release_buffer(&minor_status
, &wrapped
);
431 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
433 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
436 uint32_t minor_status
;
437 gss_buffer_desc unwrapped
, wrapped
;
440 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
441 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
443 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
444 &wrapped
, &unwrapped
,
445 &conf_state
, GSS_C_QOP_DEFAULT
);
446 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
447 if (!ADS_ERR_OK(status
)) return status
;
449 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
450 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
453 if (wrapped
.length
< unwrapped
.length
) {
454 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
457 /* copy the wrapped blob to the right location */
458 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
460 /* set how many bytes must be written to the underlying socket */
461 ads
->ldap
.in
.left
= unwrapped
.length
;
462 ads
->ldap
.in
.ofs
= 4;
464 gss_release_buffer(&minor_status
, &unwrapped
);
469 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
471 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
472 uint32_t minor_status
;
474 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
476 ads
->ldap
.wrap_ops
= NULL
;
477 ads
->ldap
.wrap_private_data
= NULL
;
480 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
482 .wrap
= ads_sasl_gssapi_wrap
,
483 .unwrap
= ads_sasl_gssapi_unwrap
,
484 .disconnect
= ads_sasl_gssapi_disconnect
487 #endif /* HAVE_KRB5 */
490 struct ads_service_principal
{
499 static void ads_free_service_principal(struct ads_service_principal
*p
)
501 SAFE_FREE(p
->service
);
502 SAFE_FREE(p
->hostname
);
503 SAFE_FREE(p
->string
);
507 uint32_t minor_status
;
508 gss_release_name(&minor_status
, &p
->name
);
514 static ADS_STATUS
ads_guess_target(ADS_STRUCT
*ads
,
519 ADS_STATUS status
= ADS_ERROR(LDAP_NO_MEMORY
);
526 frame
= talloc_stackframe();
528 return ADS_ERROR(LDAP_NO_MEMORY
);
531 if (ads
->server
.realm
&& ads
->server
.ldap_server
) {
532 server
= strlower_talloc(frame
, ads
->server
.ldap_server
);
533 if (server
== NULL
) {
537 realm
= strupper_talloc(frame
, ads
->server
.realm
);
543 * If we got a name which is bigger than a NetBIOS name,
544 * but isn't a FQDN, create one.
546 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
549 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
550 if (dnsdomain
== NULL
) {
554 server
= talloc_asprintf(frame
,
557 if (server
== NULL
) {
561 } else if (ads
->config
.realm
&& ads
->config
.ldap_server_name
) {
562 server
= strlower_talloc(frame
, ads
->config
.ldap_server_name
);
563 if (server
== NULL
) {
567 realm
= strupper_talloc(frame
, ads
->config
.realm
);
573 * If we got a name which is bigger than a NetBIOS name,
574 * but isn't a FQDN, create one.
576 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
579 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
580 if (dnsdomain
== NULL
) {
584 server
= talloc_asprintf(frame
,
587 if (server
== NULL
) {
593 if (server
== NULL
|| realm
== NULL
) {
597 *service
= SMB_STRDUP("ldap");
598 if (*service
== NULL
) {
599 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
602 *hostname
= SMB_STRDUP(server
);
603 if (*hostname
== NULL
) {
605 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
608 rc
= asprintf(&princ
, "ldap/%s@%s", server
, realm
);
609 if (rc
== -1 || princ
== NULL
) {
611 SAFE_FREE(*hostname
);
612 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
618 status
= ADS_SUCCESS
;
624 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
625 struct ads_service_principal
*p
)
629 gss_buffer_desc input_name
;
630 /* GSS_KRB5_NT_PRINCIPAL_NAME */
631 gss_OID_desc nt_principal
=
632 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
633 uint32_t minor_status
;
639 status
= ads_guess_target(ads
,
643 if (!ADS_ERR_OK(status
)) {
648 input_name
.value
= p
->string
;
649 input_name
.length
= strlen(p
->string
);
651 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
653 ads_free_service_principal(p
);
654 return ADS_ERROR_GSS(gss_rc
, minor_status
);
661 #endif /* HAVE_KRB5 */
664 this performs a SASL/SPNEGO bind
666 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
668 TALLOC_CTX
*frame
= talloc_stackframe();
669 struct ads_service_principal p
= {0};
670 struct berval
*scred
=NULL
;
673 DATA_BLOB blob
= data_blob_null
;
674 char *given_principal
= NULL
;
675 char *OIDs
[ASN1_MAX_OIDS
];
677 bool got_kerberos_mechanism
= False
;
679 const char *mech
= NULL
;
681 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
683 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
684 status
= ADS_ERROR(rc
);
688 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
693 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
696 /* the server sent us the first part of the SPNEGO exchange in the negprot
698 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &given_principal
, NULL
) ||
700 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
703 TALLOC_FREE(given_principal
);
705 /* make sure the server understands kerberos */
706 for (i
=0;OIDs
[i
];i
++) {
707 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
709 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
710 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
711 got_kerberos_mechanism
= True
;
714 talloc_free(OIDs
[i
]);
717 status
= ads_generate_service_principal(ads
, &p
);
718 if (!ADS_ERR_OK(status
)) {
723 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
724 got_kerberos_mechanism
)
728 if (ads
->auth
.password
== NULL
||
729 ads
->auth
.password
[0] == '\0')
732 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
733 CRED_MUST_USE_KERBEROS
,
734 p
.service
, p
.hostname
,
736 if (ADS_ERR_OK(status
)) {
737 ads_free_service_principal(&p
);
741 DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
742 "calling kinit\n", ads_errstr(status
)));
745 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
747 if (ADS_ERR_OK(status
)) {
748 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
749 CRED_MUST_USE_KERBEROS
,
750 p
.service
, p
.hostname
,
752 if (!ADS_ERR_OK(status
)) {
753 DEBUG(0,("kinit succeeded but "
754 "ads_sasl_spnego_gensec_bind(KRB5) failed "
755 "for %s/%s with user[%s] realm[%s]: %s\n",
756 p
.service
, p
.hostname
,
759 ads_errstr(status
)));
763 /* only fallback to NTLMSSP if allowed */
764 if (ADS_ERR_OK(status
) ||
765 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
769 DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed "
770 "for %s/%s with user[%s] realm[%s]: %s, "
771 "fallback to NTLMSSP\n",
772 p
.service
, p
.hostname
,
775 ads_errstr(status
)));
779 /* lets do NTLMSSP ... this has the big advantage that we don't need
780 to sync clocks, and we don't rely on special versions of the krb5
781 library for HMAC_MD4 encryption */
783 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
784 CRED_DONT_USE_KERBEROS
,
785 p
.service
, p
.hostname
,
788 if (!ADS_ERR_OK(status
)) {
789 DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed "
790 "for %s/%s with user[%s] realm=[%s]: %s\n", mech
,
791 p
.service
, p
.hostname
,
794 ads_errstr(status
)));
796 ads_free_service_principal(&p
);
798 if (blob
.data
!= NULL
) {
799 data_blob_free(&blob
);
805 #define MAX_GSS_PASSES 3
807 /* this performs a SASL/gssapi bind
808 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
809 is very dependent on correctly configured DNS whereas
810 this routine is much less fragile
811 see RFC2078 and RFC2222 for details
813 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
815 uint32_t minor_status
;
816 gss_cred_id_t gss_cred
= GSS_C_NO_CREDENTIAL
;
817 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
818 gss_OID mech_type
= GSS_C_NULL_OID
;
819 gss_buffer_desc output_token
, input_token
;
820 uint32_t req_flags
, ret_flags
;
823 struct berval
*scred
= NULL
;
827 uint32_t max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
828 uint8_t wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
831 input_token
.value
= NULL
;
832 input_token
.length
= 0;
834 status
= ads_init_gssapi_cred(ads
, &gss_cred
);
835 if (!ADS_ERR_OK(status
)) {
840 * Note: here we always ask the gssapi for sign and seal
841 * as this is negotiated later after the mutal
844 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
846 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
847 gss_rc
= gss_init_sec_context(&minor_status
,
864 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
865 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
869 cred
.bv_val
= (char *)output_token
.value
;
870 cred
.bv_len
= output_token
.length
;
872 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
874 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
875 status
= ADS_ERROR(rc
);
879 if (output_token
.value
) {
880 gss_release_buffer(&minor_status
, &output_token
);
884 input_token
.value
= scred
->bv_val
;
885 input_token
.length
= scred
->bv_len
;
887 input_token
.value
= NULL
;
888 input_token
.length
= 0;
891 if (gss_rc
== 0) break;
894 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
901 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
905 p
= (uint8_t *)output_token
.value
;
908 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
912 wrap_type
= CVAL(p
,0);
914 max_msg_size
= RIVAL(p
,0);
917 gss_release_buffer(&minor_status
, &output_token
);
919 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
921 * the server doesn't supports the wrap
924 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
925 ads
->ldap
.wrap_type
, wrap_type
));
926 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
927 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
931 /* 0x58 is the minimum windows accepts */
932 if (max_msg_size
< 0x58) {
936 output_token
.length
= 4;
937 output_token
.value
= SMB_MALLOC(output_token
.length
);
938 if (!output_token
.value
) {
939 output_token
.length
= 0;
940 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
943 p
= (uint8_t *)output_token
.value
;
945 RSIVAL(p
,0,max_msg_size
);
946 SCVAL(p
,0,ads
->ldap
.wrap_type
);
949 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
950 * but using ads->config.bind_path is the wrong! It should be
951 * the DN of the user object!
953 * w2k3 gives an error when we send an incorrect DN, but sending nothing
954 * is ok and matches the information flow used in GSS-SPNEGO.
957 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
958 &output_token
, /* used as *input* here. */
960 &input_token
); /* Used as *output* here. */
962 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
963 output_token
.length
= 0;
964 SAFE_FREE(output_token
.value
);
968 /* We've finished with output_token. */
969 SAFE_FREE(output_token
.value
);
970 output_token
.length
= 0;
972 cred
.bv_val
= (char *)input_token
.value
;
973 cred
.bv_len
= input_token
.length
;
975 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
977 gss_release_buffer(&minor_status
, &input_token
);
978 status
= ADS_ERROR(rc
);
979 if (!ADS_ERR_OK(status
)) {
983 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
984 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
985 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
987 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
989 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
993 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
994 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
995 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
996 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
997 if (!ADS_ERR_OK(status
)) {
998 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
999 ads_errstr(status
)));
1002 /* make sure we don't free context_handle */
1003 context_handle
= GSS_C_NO_CONTEXT
;
1007 if (gss_cred
!= GSS_C_NO_CREDENTIAL
)
1008 gss_release_cred(&minor_status
, &gss_cred
);
1009 if (context_handle
!= GSS_C_NO_CONTEXT
)
1010 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1017 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1020 struct ads_service_principal p
;
1022 status
= ads_generate_service_principal(ads
, &p
);
1023 if (!ADS_ERR_OK(status
)) {
1027 if (ads
->auth
.password
== NULL
||
1028 ads
->auth
.password
[0] == '\0') {
1029 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1030 if (ADS_ERR_OK(status
)) {
1031 ads_free_service_principal(&p
);
1035 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1036 "calling kinit\n", ads_errstr(status
)));
1039 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1041 if (ADS_ERR_OK(status
)) {
1042 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1045 ads_free_service_principal(&p
);
1050 #endif /* HAVE_KRB5 */
1052 /* mapping between SASL mechanisms and functions */
1055 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1056 } sasl_mechanisms
[] = {
1057 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1059 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1064 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1066 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1072 /* get a list of supported SASL mechanisms */
1073 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1074 if (!ADS_ERR_OK(status
)) return status
;
1076 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1078 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1079 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1080 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1081 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1083 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1086 /* try our supported mechanisms in order */
1087 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1088 /* see if the server supports it */
1089 for (j
=0;values
&& values
[j
];j
++) {
1090 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1091 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1093 status
= sasl_mechanisms
[i
].fn(ads
);
1094 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
1095 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
1096 ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
1098 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1099 "retrying with signing enabled\n"));
1100 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1103 ldap_value_free(values
);
1110 ldap_value_free(values
);
1112 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1115 #endif /* HAVE_LDAP */