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(struct ads_saslwrap
*wrap
,
34 uint8_t *buf
, uint32_t len
)
36 struct gensec_security
*gensec_security
=
37 talloc_get_type_abort(wrap
->wrap_private_data
,
38 struct gensec_security
);
40 DATA_BLOB unwrapped
, wrapped
;
41 TALLOC_CTX
*frame
= talloc_stackframe();
43 unwrapped
= data_blob_const(buf
, len
);
45 nt_status
= gensec_wrap(gensec_security
, frame
, &unwrapped
, &wrapped
);
46 if (!NT_STATUS_IS_OK(nt_status
)) {
48 return ADS_ERROR_NT(nt_status
);
51 if ((wrap
->out
.size
- 4) < wrapped
.length
) {
53 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
56 /* copy the wrapped blob to the right location */
57 memcpy(wrap
->out
.buf
+ 4, wrapped
.data
, wrapped
.length
);
59 /* set how many bytes must be written to the underlying socket */
60 wrap
->out
.left
= 4 + wrapped
.length
;
67 static ADS_STATUS
ads_sasl_gensec_unwrap(struct ads_saslwrap
*wrap
)
69 struct gensec_security
*gensec_security
=
70 talloc_get_type_abort(wrap
->wrap_private_data
,
71 struct gensec_security
);
73 DATA_BLOB unwrapped
, wrapped
;
74 TALLOC_CTX
*frame
= talloc_stackframe();
76 wrapped
= data_blob_const(wrap
->in
.buf
+ 4, wrap
->in
.ofs
- 4);
78 nt_status
= gensec_unwrap(gensec_security
, frame
, &wrapped
, &unwrapped
);
79 if (!NT_STATUS_IS_OK(nt_status
)) {
81 return ADS_ERROR_NT(nt_status
);
84 if (wrapped
.length
< unwrapped
.length
) {
86 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
89 /* copy the wrapped blob to the right location */
90 memcpy(wrap
->in
.buf
+ 4, unwrapped
.data
, unwrapped
.length
);
92 /* set how many bytes must be written to the underlying socket */
93 wrap
->in
.left
= unwrapped
.length
;
101 static void ads_sasl_gensec_disconnect(struct ads_saslwrap
*wrap
)
103 struct gensec_security
*gensec_security
=
104 talloc_get_type_abort(wrap
->wrap_private_data
,
105 struct gensec_security
);
107 TALLOC_FREE(gensec_security
);
109 wrap
->wrap_ops
= NULL
;
110 wrap
->wrap_private_data
= NULL
;
113 static const struct ads_saslwrap_ops ads_sasl_gensec_ops
= {
115 .wrap
= ads_sasl_gensec_wrap
,
116 .unwrap
= ads_sasl_gensec_unwrap
,
117 .disconnect
= ads_sasl_gensec_disconnect
121 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
122 we fit on one socket??)
124 static ADS_STATUS
ads_sasl_spnego_gensec_bind(ADS_STRUCT
*ads
,
126 enum credentials_use_kerberos krb5_state
,
127 const char *target_service
,
128 const char *target_hostname
,
129 const DATA_BLOB server_blob
)
131 DATA_BLOB blob_in
= data_blob_null
;
132 DATA_BLOB blob_out
= data_blob_null
;
136 struct auth_generic_state
*auth_generic_state
;
137 bool use_spnego_principal
= lp_client_use_spnego_principal();
138 const char *sasl_list
[] = { sasl
, NULL
};
140 struct ads_saslwrap
*wrap
= &ads
->ldap_wrap_data
;
142 nt_status
= auth_generic_client_prepare(NULL
, &auth_generic_state
);
143 if (!NT_STATUS_IS_OK(nt_status
)) {
144 return ADS_ERROR_NT(nt_status
);
147 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_username(auth_generic_state
, ads
->auth
.user_name
))) {
148 return ADS_ERROR_NT(nt_status
);
150 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_domain(auth_generic_state
, ads
->auth
.realm
))) {
151 return ADS_ERROR_NT(nt_status
);
153 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_password(auth_generic_state
, ads
->auth
.password
))) {
154 return ADS_ERROR_NT(nt_status
);
157 if (server_blob
.length
== 0) {
158 use_spnego_principal
= false;
161 if (krb5_state
== CRED_DONT_USE_KERBEROS
) {
162 use_spnego_principal
= false;
165 cli_credentials_set_kerberos_state(auth_generic_state
->credentials
,
168 if (target_service
!= NULL
) {
169 nt_status
= gensec_set_target_service(
170 auth_generic_state
->gensec_security
,
172 if (!NT_STATUS_IS_OK(nt_status
)) {
173 return ADS_ERROR_NT(nt_status
);
177 if (target_hostname
!= NULL
) {
178 nt_status
= gensec_set_target_hostname(
179 auth_generic_state
->gensec_security
,
181 if (!NT_STATUS_IS_OK(nt_status
)) {
182 return ADS_ERROR_NT(nt_status
);
186 if (target_service
!= NULL
&& target_hostname
!= NULL
) {
187 use_spnego_principal
= false;
190 switch (wrap
->wrap_type
) {
191 case ADS_SASLWRAP_TYPE_SEAL
:
192 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
193 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SEAL
);
195 case ADS_SASLWRAP_TYPE_SIGN
:
196 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
197 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
200 * windows servers are broken with sign only,
201 * so we let the NTLMSSP backend to seal here,
202 * via GENSEC_FEATURE_LDAP_STYLE.
204 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
205 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_LDAP_STYLE
);
208 case ADS_SASLWRAP_TYPE_PLAIN
:
212 nt_status
= auth_generic_client_start_by_sasl(auth_generic_state
,
214 if (!NT_STATUS_IS_OK(nt_status
)) {
215 return ADS_ERROR_NT(nt_status
);
218 rc
= LDAP_SASL_BIND_IN_PROGRESS
;
219 nt_status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
220 if (use_spnego_principal
) {
221 blob_in
= data_blob_dup_talloc(talloc_tos(), server_blob
);
222 if (blob_in
.length
== 0) {
223 TALLOC_FREE(auth_generic_state
);
224 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
227 blob_in
= data_blob_null
;
229 blob_out
= data_blob_null
;
232 struct berval cred
, *scred
= NULL
;
234 nt_status
= gensec_update(auth_generic_state
->gensec_security
,
235 talloc_tos(), blob_in
, &blob_out
);
236 data_blob_free(&blob_in
);
237 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
238 && !NT_STATUS_IS_OK(nt_status
))
240 TALLOC_FREE(auth_generic_state
);
241 data_blob_free(&blob_out
);
242 return ADS_ERROR_NT(nt_status
);
245 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_out
.length
== 0) {
249 cred
.bv_val
= (char *)blob_out
.data
;
250 cred
.bv_len
= blob_out
.length
;
252 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, sasl
, &cred
, NULL
, NULL
, &scred
);
253 data_blob_free(&blob_out
);
254 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
259 TALLOC_FREE(auth_generic_state
);
260 return ADS_ERROR(rc
);
263 blob_in
= data_blob_talloc(talloc_tos(),
266 if (blob_in
.length
!= scred
->bv_len
) {
268 TALLOC_FREE(auth_generic_state
);
269 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
273 blob_in
= data_blob_null
;
275 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_in
.length
== 0) {
280 data_blob_free(&blob_in
);
281 data_blob_free(&blob_out
);
283 if (wrap
->wrap_type
>= ADS_SASLWRAP_TYPE_SEAL
) {
286 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
287 GENSEC_FEATURE_SEAL
);
289 DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
290 TALLOC_FREE(auth_generic_state
);
291 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
294 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
295 GENSEC_FEATURE_SIGN
);
297 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
298 TALLOC_FREE(auth_generic_state
);
299 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
302 } else if (wrap
->wrap_type
>= ADS_SASLWRAP_TYPE_SIGN
) {
305 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
306 GENSEC_FEATURE_SIGN
);
308 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
309 TALLOC_FREE(auth_generic_state
);
310 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
314 ads
->auth
.tgs_expire
= LONG_MAX
;
315 end_nt_time
= gensec_expire_time(auth_generic_state
->gensec_security
);
316 if (end_nt_time
!= GENSEC_EXPIRE_TIME_INFINITY
) {
318 nttime_to_timeval(&tv
, end_nt_time
);
319 ads
->auth
.tgs_expire
= tv
.tv_sec
;
322 if (wrap
->wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
324 gensec_max_wrapped_size(auth_generic_state
->gensec_security
);
325 wrap
->out
.max_unwrapped
=
326 gensec_max_input_size(auth_generic_state
->gensec_security
);
328 wrap
->out
.sig_size
= max_wrapped
- wrap
->out
.max_unwrapped
;
330 * Note that we have to truncate this to 0x2C
331 * (taken from a capture with LDAP unbind), as the
332 * signature size is not constant for Kerberos with
335 wrap
->in
.min_wrapped
= MIN(wrap
->out
.sig_size
, 0x2C);
336 wrap
->in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
337 status
= ads_setup_sasl_wrapping(wrap
, ads
->ldap
.ld
,
338 &ads_sasl_gensec_ops
,
339 auth_generic_state
->gensec_security
);
340 if (!ADS_ERR_OK(status
)) {
341 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
342 ads_errstr(status
)));
343 TALLOC_FREE(auth_generic_state
);
346 /* Only keep the gensec_security element around long-term */
347 talloc_steal(NULL
, auth_generic_state
->gensec_security
);
349 TALLOC_FREE(auth_generic_state
);
351 return ADS_ERROR(rc
);
355 static ADS_STATUS
ads_init_gssapi_cred(ADS_STRUCT
*ads
, gss_cred_id_t
*cred
)
359 krb5_error_code kerr
;
360 krb5_ccache kccache
= NULL
;
363 *cred
= GSS_C_NO_CREDENTIAL
;
365 if (!ads
->auth
.ccache_name
) {
369 kerr
= krb5_init_context(&kctx
);
371 return ADS_ERROR_KRB5(kerr
);
374 kerr
= krb5_cc_resolve(kctx
, ads
->auth
.ccache_name
, &kccache
);
376 status
= ADS_ERROR_KRB5(kerr
);
380 maj
= smb_gss_krb5_import_cred(&min
, kctx
, kccache
, NULL
, NULL
, cred
);
381 if (maj
!= GSS_S_COMPLETE
) {
382 status
= ADS_ERROR_GSS(maj
, min
);
386 status
= ADS_SUCCESS
;
389 if (!ADS_ERR_OK(status
) && kccache
!= NULL
) {
390 krb5_cc_close(kctx
, kccache
);
392 krb5_free_context(kctx
);
396 static ADS_STATUS
ads_sasl_gssapi_wrap(struct ads_saslwrap
*wrap
, uint8_t *buf
, uint32_t len
)
398 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)wrap
->wrap_private_data
;
401 uint32_t minor_status
;
402 gss_buffer_desc unwrapped
, wrapped
;
403 int conf_req_flag
, conf_state
;
405 unwrapped
.value
= buf
;
406 unwrapped
.length
= len
;
408 /* for now request sign and seal */
409 conf_req_flag
= (wrap
->wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
411 gss_rc
= gss_wrap(&minor_status
, context_handle
,
412 conf_req_flag
, GSS_C_QOP_DEFAULT
,
413 &unwrapped
, &conf_state
,
415 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
416 if (!ADS_ERR_OK(status
)) return status
;
418 if (conf_req_flag
&& conf_state
== 0) {
419 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
422 if ((wrap
->out
.size
- 4) < wrapped
.length
) {
423 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
426 /* copy the wrapped blob to the right location */
427 memcpy(wrap
->out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
429 /* set how many bytes must be written to the underlying socket */
430 wrap
->out
.left
= 4 + wrapped
.length
;
432 gss_release_buffer(&minor_status
, &wrapped
);
437 static ADS_STATUS
ads_sasl_gssapi_unwrap(struct ads_saslwrap
*wrap
)
439 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)wrap
->wrap_private_data
;
442 uint32_t minor_status
;
443 gss_buffer_desc unwrapped
, wrapped
;
446 wrapped
.value
= wrap
->in
.buf
+ 4;
447 wrapped
.length
= wrap
->in
.ofs
- 4;
449 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
450 &wrapped
, &unwrapped
,
451 &conf_state
, GSS_C_QOP_DEFAULT
);
452 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
453 if (!ADS_ERR_OK(status
)) return status
;
455 if (wrap
->wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
456 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
459 if (wrapped
.length
< unwrapped
.length
) {
460 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
463 /* copy the wrapped blob to the right location */
464 memcpy(wrap
->in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
466 /* set how many bytes must be written to the underlying socket */
467 wrap
->in
.left
= unwrapped
.length
;
470 gss_release_buffer(&minor_status
, &unwrapped
);
475 static void ads_sasl_gssapi_disconnect(struct ads_saslwrap
*wrap
)
477 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)wrap
->wrap_private_data
;
478 uint32_t minor_status
;
480 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
482 wrap
->wrap_ops
= NULL
;
483 wrap
->wrap_private_data
= NULL
;
486 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
488 .wrap
= ads_sasl_gssapi_wrap
,
489 .unwrap
= ads_sasl_gssapi_unwrap
,
490 .disconnect
= ads_sasl_gssapi_disconnect
493 #endif /* HAVE_KRB5 */
496 struct ads_service_principal
{
505 static void ads_free_service_principal(struct ads_service_principal
*p
)
507 SAFE_FREE(p
->service
);
508 SAFE_FREE(p
->hostname
);
509 SAFE_FREE(p
->string
);
513 uint32_t minor_status
;
514 gss_release_name(&minor_status
, &p
->name
);
520 static ADS_STATUS
ads_guess_target(ADS_STRUCT
*ads
,
525 ADS_STATUS status
= ADS_ERROR(LDAP_NO_MEMORY
);
532 frame
= talloc_stackframe();
534 return ADS_ERROR(LDAP_NO_MEMORY
);
537 if (ads
->server
.realm
&& ads
->server
.ldap_server
) {
538 server
= strlower_talloc(frame
, ads
->server
.ldap_server
);
539 if (server
== NULL
) {
543 realm
= strupper_talloc(frame
, ads
->server
.realm
);
549 * If we got a name which is bigger than a NetBIOS name,
550 * but isn't a FQDN, create one.
552 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
555 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
556 if (dnsdomain
== NULL
) {
560 server
= talloc_asprintf(frame
,
563 if (server
== NULL
) {
567 } else if (ads
->config
.realm
&& ads
->config
.ldap_server_name
) {
568 server
= strlower_talloc(frame
, ads
->config
.ldap_server_name
);
569 if (server
== NULL
) {
573 realm
= strupper_talloc(frame
, ads
->config
.realm
);
579 * If we got a name which is bigger than a NetBIOS name,
580 * but isn't a FQDN, create one.
582 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
585 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
586 if (dnsdomain
== NULL
) {
590 server
= talloc_asprintf(frame
,
593 if (server
== NULL
) {
599 if (server
== NULL
|| realm
== NULL
) {
603 *service
= SMB_STRDUP("ldap");
604 if (*service
== NULL
) {
605 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
608 *hostname
= SMB_STRDUP(server
);
609 if (*hostname
== NULL
) {
611 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
614 rc
= asprintf(&princ
, "ldap/%s@%s", server
, realm
);
615 if (rc
== -1 || princ
== NULL
) {
617 SAFE_FREE(*hostname
);
618 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
624 status
= ADS_SUCCESS
;
630 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
631 struct ads_service_principal
*p
)
635 gss_buffer_desc input_name
;
636 /* GSS_KRB5_NT_PRINCIPAL_NAME */
637 gss_OID_desc nt_principal
=
638 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
639 uint32_t minor_status
;
645 status
= ads_guess_target(ads
,
649 if (!ADS_ERR_OK(status
)) {
654 input_name
.value
= p
->string
;
655 input_name
.length
= strlen(p
->string
);
657 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
659 ads_free_service_principal(p
);
660 return ADS_ERROR_GSS(gss_rc
, minor_status
);
667 #endif /* HAVE_KRB5 */
670 this performs a SASL/SPNEGO bind
672 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
674 TALLOC_CTX
*frame
= talloc_stackframe();
675 struct ads_service_principal p
= {0};
676 struct berval
*scred
=NULL
;
679 DATA_BLOB blob
= data_blob_null
;
680 char *given_principal
= NULL
;
681 char *OIDs
[ASN1_MAX_OIDS
];
683 bool got_kerberos_mechanism
= False
;
685 const char *mech
= NULL
;
687 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
689 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
690 status
= ADS_ERROR(rc
);
694 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
699 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
702 /* the server sent us the first part of the SPNEGO exchange in the negprot
704 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &given_principal
, NULL
) ||
706 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
709 TALLOC_FREE(given_principal
);
711 /* make sure the server understands kerberos */
712 for (i
=0;OIDs
[i
];i
++) {
713 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
715 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
716 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
717 got_kerberos_mechanism
= True
;
720 talloc_free(OIDs
[i
]);
723 status
= ads_generate_service_principal(ads
, &p
);
724 if (!ADS_ERR_OK(status
)) {
729 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
730 got_kerberos_mechanism
)
734 if (ads
->auth
.password
== NULL
||
735 ads
->auth
.password
[0] == '\0')
738 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
739 CRED_MUST_USE_KERBEROS
,
740 p
.service
, p
.hostname
,
742 if (ADS_ERR_OK(status
)) {
743 ads_free_service_principal(&p
);
747 DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
748 "calling kinit\n", ads_errstr(status
)));
751 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
753 if (ADS_ERR_OK(status
)) {
754 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
755 CRED_MUST_USE_KERBEROS
,
756 p
.service
, p
.hostname
,
758 if (!ADS_ERR_OK(status
)) {
759 DEBUG(0,("kinit succeeded but "
760 "ads_sasl_spnego_gensec_bind(KRB5) failed "
761 "for %s/%s with user[%s] realm[%s]: %s\n",
762 p
.service
, p
.hostname
,
765 ads_errstr(status
)));
769 /* only fallback to NTLMSSP if allowed */
770 if (ADS_ERR_OK(status
) ||
771 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
775 DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed "
776 "for %s/%s with user[%s] realm[%s]: %s, "
777 "fallback to NTLMSSP\n",
778 p
.service
, p
.hostname
,
781 ads_errstr(status
)));
785 /* lets do NTLMSSP ... this has the big advantage that we don't need
786 to sync clocks, and we don't rely on special versions of the krb5
787 library for HMAC_MD4 encryption */
789 status
= ads_sasl_spnego_gensec_bind(ads
, "GSS-SPNEGO",
790 CRED_DONT_USE_KERBEROS
,
791 p
.service
, p
.hostname
,
794 if (!ADS_ERR_OK(status
)) {
795 DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed "
796 "for %s/%s with user[%s] realm=[%s]: %s\n", mech
,
797 p
.service
, p
.hostname
,
800 ads_errstr(status
)));
802 ads_free_service_principal(&p
);
804 if (blob
.data
!= NULL
) {
805 data_blob_free(&blob
);
811 #define MAX_GSS_PASSES 3
813 /* this performs a SASL/gssapi bind
814 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
815 is very dependent on correctly configured DNS whereas
816 this routine is much less fragile
817 see RFC2078 and RFC2222 for details
819 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
821 uint32_t minor_status
;
822 gss_cred_id_t gss_cred
= GSS_C_NO_CREDENTIAL
;
823 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
824 gss_OID mech_type
= GSS_C_NULL_OID
;
825 gss_buffer_desc output_token
, input_token
;
826 uint32_t req_flags
, ret_flags
;
829 struct berval
*scred
= NULL
;
833 uint32_t max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
834 uint8_t wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
836 struct ads_saslwrap
*wrap
= &ads
->ldap_wrap_data
;
838 input_token
.value
= NULL
;
839 input_token
.length
= 0;
841 status
= ads_init_gssapi_cred(ads
, &gss_cred
);
842 if (!ADS_ERR_OK(status
)) {
847 * Note: here we always ask the gssapi for sign and seal
848 * as this is negotiated later after the mutal
851 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
853 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
854 gss_rc
= gss_init_sec_context(&minor_status
,
871 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
872 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
876 cred
.bv_val
= (char *)output_token
.value
;
877 cred
.bv_len
= output_token
.length
;
879 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
881 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
882 status
= ADS_ERROR(rc
);
886 if (output_token
.value
) {
887 gss_release_buffer(&minor_status
, &output_token
);
891 input_token
.value
= scred
->bv_val
;
892 input_token
.length
= scred
->bv_len
;
894 input_token
.value
= NULL
;
895 input_token
.length
= 0;
898 if (gss_rc
== 0) break;
901 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
908 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
912 p
= (uint8_t *)output_token
.value
;
915 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
919 wrap_type
= CVAL(p
,0);
921 max_msg_size
= RIVAL(p
,0);
924 gss_release_buffer(&minor_status
, &output_token
);
926 if (!(wrap_type
& wrap
->wrap_type
)) {
928 * the server doesn't supports the wrap
931 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
932 wrap
->wrap_type
, wrap_type
));
933 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
934 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
938 /* 0x58 is the minimum windows accepts */
939 if (max_msg_size
< 0x58) {
943 output_token
.length
= 4;
944 output_token
.value
= SMB_MALLOC(output_token
.length
);
945 if (!output_token
.value
) {
946 output_token
.length
= 0;
947 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
950 p
= (uint8_t *)output_token
.value
;
952 RSIVAL(p
,0,max_msg_size
);
953 SCVAL(p
,0,wrap
->wrap_type
);
956 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
957 * but using ads->config.bind_path is the wrong! It should be
958 * the DN of the user object!
960 * w2k3 gives an error when we send an incorrect DN, but sending nothing
961 * is ok and matches the information flow used in GSS-SPNEGO.
964 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
965 &output_token
, /* used as *input* here. */
967 &input_token
); /* Used as *output* here. */
969 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
970 output_token
.length
= 0;
971 SAFE_FREE(output_token
.value
);
975 /* We've finished with output_token. */
976 SAFE_FREE(output_token
.value
);
977 output_token
.length
= 0;
979 cred
.bv_val
= (char *)input_token
.value
;
980 cred
.bv_len
= input_token
.length
;
982 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
984 gss_release_buffer(&minor_status
, &input_token
);
985 status
= ADS_ERROR(rc
);
986 if (!ADS_ERR_OK(status
)) {
990 if (wrap
->wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
991 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
992 (wrap
->wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
994 max_msg_size
, &wrap
->out
.max_unwrapped
);
996 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1000 wrap
->out
.sig_size
= max_msg_size
- wrap
->out
.max_unwrapped
;
1001 wrap
->in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1002 wrap
->in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
1003 status
= ads_setup_sasl_wrapping(wrap
->wrap_private_data
, ads
->ldap
.ld
,
1004 &ads_sasl_gssapi_ops
,
1006 if (!ADS_ERR_OK(status
)) {
1007 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1008 ads_errstr(status
)));
1011 /* make sure we don't free context_handle */
1012 context_handle
= GSS_C_NO_CONTEXT
;
1016 if (gss_cred
!= GSS_C_NO_CREDENTIAL
)
1017 gss_release_cred(&minor_status
, &gss_cred
);
1018 if (context_handle
!= GSS_C_NO_CONTEXT
)
1019 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1026 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1029 struct ads_service_principal p
;
1031 status
= ads_generate_service_principal(ads
, &p
);
1032 if (!ADS_ERR_OK(status
)) {
1036 if (ads
->auth
.password
== NULL
||
1037 ads
->auth
.password
[0] == '\0') {
1038 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1039 if (ADS_ERR_OK(status
)) {
1040 ads_free_service_principal(&p
);
1044 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1045 "calling kinit\n", ads_errstr(status
)));
1048 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1050 if (ADS_ERR_OK(status
)) {
1051 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1054 ads_free_service_principal(&p
);
1059 #endif /* HAVE_KRB5 */
1061 /* mapping between SASL mechanisms and functions */
1064 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1065 } sasl_mechanisms
[] = {
1066 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1068 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1073 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1075 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1080 struct ads_saslwrap
*wrap
= &ads
->ldap_wrap_data
;
1082 /* get a list of supported SASL mechanisms */
1083 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1084 if (!ADS_ERR_OK(status
)) return status
;
1086 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1088 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1089 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1090 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1091 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1093 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1096 /* try our supported mechanisms in order */
1097 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1098 /* see if the server supports it */
1099 for (j
=0;values
&& values
[j
];j
++) {
1100 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1101 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1103 status
= sasl_mechanisms
[i
].fn(ads
);
1104 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
1105 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
1106 wrap
->wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
1108 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1109 "retrying with signing enabled\n"));
1110 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1113 ldap_value_free(values
);
1120 ldap_value_free(values
);
1122 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1125 #endif /* HAVE_LDAP */