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/gensec/gensec.h"
23 #include "auth_generic.h"
26 #include "system/gssapi.h"
27 #include "lib/param/loadparm.h"
31 static ADS_STATUS
ads_sasl_ntlmssp_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
33 struct gensec_security
*gensec_security
=
34 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
35 struct gensec_security
);
37 DATA_BLOB unwrapped
, wrapped
;
38 TALLOC_CTX
*frame
= talloc_stackframe();
40 unwrapped
= data_blob_const(buf
, len
);
42 nt_status
= gensec_wrap(gensec_security
, frame
, &unwrapped
, &wrapped
);
43 if (!NT_STATUS_IS_OK(nt_status
)) {
45 return ADS_ERROR_NT(nt_status
);
48 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
49 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
52 /* copy the wrapped blob to the right location */
53 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.data
, wrapped
.length
);
55 /* set how many bytes must be written to the underlying socket */
56 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
63 static ADS_STATUS
ads_sasl_ntlmssp_unwrap(ADS_STRUCT
*ads
)
65 struct gensec_security
*gensec_security
=
66 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
67 struct gensec_security
);
69 DATA_BLOB unwrapped
, wrapped
;
70 TALLOC_CTX
*frame
= talloc_stackframe();
72 wrapped
= data_blob_const(ads
->ldap
.in
.buf
+ 4, ads
->ldap
.in
.ofs
- 4);
74 nt_status
= gensec_unwrap(gensec_security
, frame
, &wrapped
, &unwrapped
);
75 if (!NT_STATUS_IS_OK(nt_status
)) {
77 return ADS_ERROR_NT(nt_status
);
80 if (wrapped
.length
< unwrapped
.length
) {
82 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
85 /* copy the wrapped blob to the right location */
86 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.data
, unwrapped
.length
);
88 /* set how many bytes must be written to the underlying socket */
89 ads
->ldap
.in
.left
= unwrapped
.length
;
97 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT
*ads
)
99 struct gensec_security
*gensec_security
=
100 talloc_get_type_abort(ads
->ldap
.wrap_private_data
,
101 struct gensec_security
);
103 TALLOC_FREE(gensec_security
);
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
;
132 struct auth_generic_state
*auth_generic_state
;
134 nt_status
= auth_generic_client_prepare(NULL
, &auth_generic_state
);
135 if (!NT_STATUS_IS_OK(nt_status
)) {
136 return ADS_ERROR_NT(nt_status
);
139 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_username(auth_generic_state
, ads
->auth
.user_name
))) {
140 return ADS_ERROR_NT(nt_status
);
142 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_domain(auth_generic_state
, ads
->auth
.realm
))) {
143 return ADS_ERROR_NT(nt_status
);
145 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_password(auth_generic_state
, ads
->auth
.password
))) {
146 return ADS_ERROR_NT(nt_status
);
149 switch (ads
->ldap
.wrap_type
) {
150 case ADS_SASLWRAP_TYPE_SEAL
:
151 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
152 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SEAL
);
154 case ADS_SASLWRAP_TYPE_SIGN
:
155 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
156 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
159 * windows servers are broken with sign only,
160 * so we need to use seal here too
162 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
163 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SEAL
);
164 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
167 case ADS_SASLWRAP_TYPE_PLAIN
:
171 nt_status
= auth_generic_client_start(auth_generic_state
, GENSEC_OID_NTLMSSP
);
172 if (!NT_STATUS_IS_OK(nt_status
)) {
173 return ADS_ERROR_NT(nt_status
);
176 blob_in
= data_blob_null
;
179 nt_status
= gensec_update(auth_generic_state
->gensec_security
,
180 talloc_tos(), NULL
, blob_in
, &blob_out
);
181 data_blob_free(&blob_in
);
182 if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
183 || NT_STATUS_IS_OK(nt_status
))
184 && blob_out
.length
) {
186 const char *OIDs_ntlm
[] = {OID_NTLMSSP
, NULL
};
187 /* and wrap it in a SPNEGO wrapper */
188 msg1
= spnego_gen_negTokenInit(talloc_tos(),
189 OIDs_ntlm
, &blob_out
, NULL
);
191 /* wrap it in SPNEGO */
192 msg1
= spnego_gen_auth(talloc_tos(), blob_out
);
195 data_blob_free(&blob_out
);
197 cred
.bv_val
= (char *)msg1
.data
;
198 cred
.bv_len
= msg1
.length
;
200 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
201 data_blob_free(&msg1
);
202 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
207 TALLOC_FREE(auth_generic_state
);
208 return ADS_ERROR(rc
);
211 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
214 blob
= data_blob_null
;
219 TALLOC_FREE(auth_generic_state
);
220 data_blob_free(&blob_out
);
221 return ADS_ERROR_NT(nt_status
);
225 (rc
== LDAP_SASL_BIND_IN_PROGRESS
)) {
226 DATA_BLOB tmp_blob
= data_blob_null
;
227 /* the server might give us back two challenges */
228 if (!spnego_parse_challenge(talloc_tos(), blob
, &blob_in
,
231 TALLOC_FREE(auth_generic_state
);
232 data_blob_free(&blob
);
233 DEBUG(3,("Failed to parse challenges\n"));
234 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
236 data_blob_free(&tmp_blob
);
237 } else if (rc
== LDAP_SASL_BIND_IN_PROGRESS
) {
238 if (!spnego_parse_auth_response(talloc_tos(), blob
, nt_status
, OID_NTLMSSP
,
241 TALLOC_FREE(auth_generic_state
);
242 data_blob_free(&blob
);
243 DEBUG(3,("Failed to parse auth response\n"));
244 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
247 data_blob_free(&blob
);
248 data_blob_free(&blob_out
);
250 } while (rc
== LDAP_SASL_BIND_IN_PROGRESS
&& !NT_STATUS_IS_OK(nt_status
));
252 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
253 uint32_t sig_size
= gensec_sig_size(auth_generic_state
->gensec_security
, 0);
254 ads
->ldap
.out
.max_unwrapped
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
- sig_size
;
255 ads
->ldap
.out
.sig_size
= sig_size
;
256 ads
->ldap
.in
.min_wrapped
= ads
->ldap
.out
.sig_size
;
257 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
258 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_ntlmssp_ops
, auth_generic_state
->gensec_security
);
259 if (!ADS_ERR_OK(status
)) {
260 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
261 ads_errstr(status
)));
262 TALLOC_FREE(auth_generic_state
);
265 /* Only keep the gensec_security element around long-term */
266 talloc_steal(NULL
, auth_generic_state
->gensec_security
);
268 TALLOC_FREE(auth_generic_state
);
270 return ADS_ERROR(rc
);
274 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
276 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
280 gss_buffer_desc unwrapped
, wrapped
;
281 int conf_req_flag
, conf_state
;
283 unwrapped
.value
= buf
;
284 unwrapped
.length
= len
;
286 /* for now request sign and seal */
287 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
289 gss_rc
= gss_wrap(&minor_status
, context_handle
,
290 conf_req_flag
, GSS_C_QOP_DEFAULT
,
291 &unwrapped
, &conf_state
,
293 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
294 if (!ADS_ERR_OK(status
)) return status
;
296 if (conf_req_flag
&& conf_state
== 0) {
297 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
300 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
301 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
304 /* copy the wrapped blob to the right location */
305 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
307 /* set how many bytes must be written to the underlying socket */
308 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
310 gss_release_buffer(&minor_status
, &wrapped
);
315 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
317 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
321 gss_buffer_desc unwrapped
, wrapped
;
324 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
325 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
327 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
328 &wrapped
, &unwrapped
,
329 &conf_state
, GSS_C_QOP_DEFAULT
);
330 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
331 if (!ADS_ERR_OK(status
)) return status
;
333 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
334 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
337 if (wrapped
.length
< unwrapped
.length
) {
338 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
341 /* copy the wrapped blob to the right location */
342 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
344 /* set how many bytes must be written to the underlying socket */
345 ads
->ldap
.in
.left
= unwrapped
.length
;
346 ads
->ldap
.in
.ofs
= 4;
348 gss_release_buffer(&minor_status
, &unwrapped
);
353 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
355 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
358 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
360 ads
->ldap
.wrap_ops
= NULL
;
361 ads
->ldap
.wrap_private_data
= NULL
;
364 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
366 .wrap
= ads_sasl_gssapi_wrap
,
367 .unwrap
= ads_sasl_gssapi_unwrap
,
368 .disconnect
= ads_sasl_gssapi_disconnect
372 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
374 static ADS_STATUS
ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
380 gss_OID_desc krb5_mech_type
=
381 {9, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
382 gss_OID mech_type
= &krb5_mech_type
;
383 gss_OID actual_mech_type
= GSS_C_NULL_OID
;
384 const char *spnego_mechs
[] = {OID_KERBEROS5_OLD
, OID_KERBEROS5
, OID_NTLMSSP
, NULL
};
385 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
386 gss_buffer_desc input_token
, output_token
;
387 uint32 req_flags
, ret_flags
;
388 uint32 req_tmp
, ret_tmp
;
391 struct berval cred
, *scred
= NULL
;
393 input_token
.value
= NULL
;
394 input_token
.length
= 0;
396 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
;
397 switch (ads
->ldap
.wrap_type
) {
398 case ADS_SASLWRAP_TYPE_SEAL
:
399 req_flags
|= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
401 case ADS_SASLWRAP_TYPE_SIGN
:
402 req_flags
|= GSS_C_INTEG_FLAG
;
404 case ADS_SASLWRAP_TYPE_PLAIN
:
408 /* Note: here we explicit ask for the krb5 mech_type */
409 gss_rc
= gss_init_sec_context(&minor_status
,
422 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
423 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
428 * As some gssapi krb5 mech implementations
429 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
430 * to req_flags internaly, it's not possible to
431 * use plain or signing only connection via
432 * the gssapi interface.
434 * Because of this we need to check it the ret_flags
435 * has more flags as req_flags and correct the value
436 * of ads->ldap.wrap_type.
438 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
439 * we need to give an error.
441 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
442 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
444 if (req_tmp
== ret_tmp
) {
445 /* everythings fine... */
447 } else if (req_flags
& GSS_C_CONF_FLAG
) {
449 * here we wanted sealing but didn't got it
450 * from the gssapi library
452 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
455 } else if ((req_flags
& GSS_C_INTEG_FLAG
) &&
456 !(ret_flags
& GSS_C_INTEG_FLAG
)) {
458 * here we wanted siging but didn't got it
459 * from the gssapi library
461 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
464 } else if (ret_flags
& GSS_C_CONF_FLAG
) {
466 * here we didn't want sealing
467 * but the gssapi library forces it
468 * so correct the needed wrap_type if
469 * the caller didn't forced siging only
471 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
472 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
476 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
477 req_flags
= ret_flags
;
479 } else if (ret_flags
& GSS_C_INTEG_FLAG
) {
481 * here we didn't want signing
482 * but the gssapi library forces it
483 * so correct the needed wrap_type if
484 * the caller didn't forced plain
486 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
487 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
491 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
492 req_flags
= ret_flags
;
495 * This could (should?) not happen
497 status
= ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
502 /* and wrap that in a shiny SPNEGO wrapper */
503 unwrapped
= data_blob_const(output_token
.value
, output_token
.length
);
504 wrapped
= spnego_gen_negTokenInit(talloc_tos(),
505 spnego_mechs
, &unwrapped
, NULL
);
506 gss_release_buffer(&minor_status
, &output_token
);
507 if (unwrapped
.length
> wrapped
.length
) {
508 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
512 cred
.bv_val
= (char *)wrapped
.data
;
513 cred
.bv_len
= wrapped
.length
;
515 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
,
517 data_blob_free(&wrapped
);
518 if (rc
!= LDAP_SUCCESS
) {
519 status
= ADS_ERROR(rc
);
524 wrapped
= data_blob_const(scred
->bv_val
, scred
->bv_len
);
526 wrapped
= data_blob_null
;
529 ok
= spnego_parse_auth_response(talloc_tos(), wrapped
, NT_STATUS_OK
,
532 if (scred
) ber_bvfree(scred
);
534 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
538 input_token
.value
= unwrapped
.data
;
539 input_token
.length
= unwrapped
.length
;
542 * As we asked for mutal authentication
543 * we need to pass the servers response
546 gss_rc
= gss_init_sec_context(&minor_status
,
559 data_blob_free(&unwrapped
);
561 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
565 gss_release_buffer(&minor_status
, &output_token
);
568 * If we the sign and seal options
569 * doesn't match after getting the response
570 * from the server, we don't want to use the connection
572 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
573 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
575 if (req_tmp
!= ret_tmp
) {
576 /* everythings fine... */
577 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
581 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
582 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
584 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
585 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
587 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
589 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
593 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
594 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
595 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
596 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
597 if (!ADS_ERR_OK(status
)) {
598 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
599 ads_errstr(status
)));
602 /* make sure we don't free context_handle */
603 context_handle
= GSS_C_NO_CONTEXT
;
606 status
= ADS_SUCCESS
;
609 if (context_handle
!= GSS_C_NO_CONTEXT
)
610 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
614 #endif /* HAVE_KRB5 */
617 struct ads_service_principal
{
624 static void ads_free_service_principal(struct ads_service_principal
*p
)
626 SAFE_FREE(p
->string
);
631 gss_release_name(&minor_status
, &p
->name
);
638 static ADS_STATUS
ads_guess_service_principal(ADS_STRUCT
*ads
,
639 char **returned_principal
)
643 if (ads
->server
.realm
&& ads
->server
.ldap_server
) {
644 char *server
, *server_realm
;
646 server
= SMB_STRDUP(ads
->server
.ldap_server
);
647 server_realm
= SMB_STRDUP(ads
->server
.realm
);
649 if (!server
|| !server_realm
) {
651 SAFE_FREE(server_realm
);
652 return ADS_ERROR(LDAP_NO_MEMORY
);
656 strupper_m(server_realm
);
657 if (asprintf(&princ
, "ldap/%s@%s", server
, server_realm
) == -1) {
659 SAFE_FREE(server_realm
);
660 return ADS_ERROR(LDAP_NO_MEMORY
);
664 SAFE_FREE(server_realm
);
667 return ADS_ERROR(LDAP_NO_MEMORY
);
669 } else if (ads
->config
.realm
&& ads
->config
.ldap_server_name
) {
670 char *server
, *server_realm
;
672 server
= SMB_STRDUP(ads
->config
.ldap_server_name
);
673 server_realm
= SMB_STRDUP(ads
->config
.realm
);
675 if (!server
|| !server_realm
) {
677 SAFE_FREE(server_realm
);
678 return ADS_ERROR(LDAP_NO_MEMORY
);
682 strupper_m(server_realm
);
683 if (asprintf(&princ
, "ldap/%s@%s", server
, server_realm
) == -1) {
685 SAFE_FREE(server_realm
);
686 return ADS_ERROR(LDAP_NO_MEMORY
);
690 SAFE_FREE(server_realm
);
693 return ADS_ERROR(LDAP_NO_MEMORY
);
698 return ADS_ERROR(LDAP_PARAM_ERROR
);
701 *returned_principal
= princ
;
706 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
707 const char *given_principal
,
708 struct ads_service_principal
*p
)
712 gss_buffer_desc input_name
;
713 /* GSS_KRB5_NT_PRINCIPAL_NAME */
714 gss_OID_desc nt_principal
=
715 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
722 /* I've seen a child Windows 2000 domain not send
723 the principal name back in the first round of
724 the SASL bind reply. So we guess based on server
725 name and realm. --jerry */
726 /* Also try best guess when we get the w2k8 ignore principal
727 back, or when we are configured to ignore it - gd,
730 if (!lp_client_use_spnego_principal() ||
732 strequal(given_principal
, ADS_IGNORE_PRINCIPAL
)) {
734 status
= ads_guess_service_principal(ads
, &p
->string
);
735 if (!ADS_ERR_OK(status
)) {
739 p
->string
= SMB_STRDUP(given_principal
);
741 return ADS_ERROR(LDAP_NO_MEMORY
);
746 input_name
.value
= p
->string
;
747 input_name
.length
= strlen(p
->string
);
749 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
751 ads_free_service_principal(p
);
752 return ADS_ERROR_GSS(gss_rc
, minor_status
);
760 perform a LDAP/SASL/SPNEGO/KRB5 bind
762 static ADS_STATUS
ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT
*ads
, const char *principal
)
764 DATA_BLOB blob
= data_blob_null
;
765 struct berval cred
, *scred
= NULL
;
766 DATA_BLOB session_key
= data_blob_null
;
769 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
770 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
773 rc
= spnego_gen_krb5_negTokenInit(talloc_tos(), principal
,
774 ads
->auth
.time_offset
, &blob
, &session_key
, 0,
775 &ads
->auth
.tgs_expire
);
778 return ADS_ERROR_KRB5(rc
);
781 /* now send the auth packet and we should be done */
782 cred
.bv_val
= (char *)blob
.data
;
783 cred
.bv_len
= blob
.length
;
785 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
787 data_blob_free(&blob
);
788 data_blob_free(&session_key
);
792 return ADS_ERROR(rc
);
795 static ADS_STATUS
ads_sasl_spnego_krb5_bind(ADS_STRUCT
*ads
,
796 struct ads_service_principal
*p
)
800 * we only use the gsskrb5 based implementation
801 * when sasl sign or seal is requested.
803 * This has the following reasons:
804 * - it's likely that the gssapi krb5 mech implementation
805 * doesn't support to negotiate plain connections
806 * - the ads_sasl_spnego_rawkrb5_bind is more robust
807 * against clock skew errors
809 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
810 return ads_sasl_spnego_gsskrb5_bind(ads
, p
->name
);
813 return ads_sasl_spnego_rawkrb5_bind(ads
, p
->string
);
815 #endif /* HAVE_KRB5 */
818 this performs a SASL/SPNEGO bind
820 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
822 struct berval
*scred
=NULL
;
826 char *given_principal
= NULL
;
827 char *OIDs
[ASN1_MAX_OIDS
];
829 bool got_kerberos_mechanism
= False
;
832 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
834 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
835 status
= ADS_ERROR(rc
);
839 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
844 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
847 /* the server sent us the first part of the SPNEGO exchange in the negprot
849 if (!spnego_parse_negTokenInit(talloc_tos(), blob
, OIDs
, &given_principal
, NULL
) ||
851 data_blob_free(&blob
);
852 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
855 data_blob_free(&blob
);
857 /* make sure the server understands kerberos */
858 for (i
=0;OIDs
[i
];i
++) {
859 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
861 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
862 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
863 got_kerberos_mechanism
= True
;
866 talloc_free(OIDs
[i
]);
868 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal
));
871 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
872 got_kerberos_mechanism
)
874 struct ads_service_principal p
;
876 status
= ads_generate_service_principal(ads
, given_principal
, &p
);
877 TALLOC_FREE(given_principal
);
878 if (!ADS_ERR_OK(status
)) {
882 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
883 if (ADS_ERR_OK(status
)) {
884 ads_free_service_principal(&p
);
888 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
889 "calling kinit\n", ads_errstr(status
)));
891 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
893 if (ADS_ERR_OK(status
)) {
894 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
895 if (!ADS_ERR_OK(status
)) {
896 DEBUG(0,("kinit succeeded but "
897 "ads_sasl_spnego_krb5_bind failed: %s\n",
898 ads_errstr(status
)));
902 ads_free_service_principal(&p
);
904 /* only fallback to NTLMSSP if allowed */
905 if (ADS_ERR_OK(status
) ||
906 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
912 TALLOC_FREE(given_principal
);
915 /* lets do NTLMSSP ... this has the big advantage that we don't need
916 to sync clocks, and we don't rely on special versions of the krb5
917 library for HMAC_MD4 encryption */
918 return ads_sasl_spnego_ntlmssp_bind(ads
);
925 #define MAX_GSS_PASSES 3
927 /* this performs a SASL/gssapi bind
928 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
929 is very dependent on correctly configured DNS whereas
930 this routine is much less fragile
931 see RFC2078 and RFC2222 for details
933 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
936 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
937 gss_OID mech_type
= GSS_C_NULL_OID
;
938 gss_buffer_desc output_token
, input_token
;
939 uint32 req_flags
, ret_flags
;
942 struct berval
*scred
= NULL
;
946 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
947 uint8 wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
950 input_token
.value
= NULL
;
951 input_token
.length
= 0;
954 * Note: here we always ask the gssapi for sign and seal
955 * as this is negotiated later after the mutal
958 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
960 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
961 gss_rc
= gss_init_sec_context(&minor_status
,
978 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
979 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
983 cred
.bv_val
= (char *)output_token
.value
;
984 cred
.bv_len
= output_token
.length
;
986 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
988 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
989 status
= ADS_ERROR(rc
);
993 if (output_token
.value
) {
994 gss_release_buffer(&minor_status
, &output_token
);
998 input_token
.value
= scred
->bv_val
;
999 input_token
.length
= scred
->bv_len
;
1001 input_token
.value
= NULL
;
1002 input_token
.length
= 0;
1005 if (gss_rc
== 0) break;
1008 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
1015 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1019 p
= (uint8
*)output_token
.value
;
1022 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
1026 wrap_type
= CVAL(p
,0);
1028 max_msg_size
= RIVAL(p
,0);
1031 gss_release_buffer(&minor_status
, &output_token
);
1033 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
1035 * the server doesn't supports the wrap
1038 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
1039 ads
->ldap
.wrap_type
, wrap_type
));
1040 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
1041 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
1045 /* 0x58 is the minimum windows accepts */
1046 if (max_msg_size
< 0x58) {
1047 max_msg_size
= 0x58;
1050 output_token
.length
= 4;
1051 output_token
.value
= SMB_MALLOC(output_token
.length
);
1052 if (!output_token
.value
) {
1053 output_token
.length
= 0;
1054 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
1057 p
= (uint8
*)output_token
.value
;
1059 RSIVAL(p
,0,max_msg_size
);
1060 SCVAL(p
,0,ads
->ldap
.wrap_type
);
1063 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
1064 * but using ads->config.bind_path is the wrong! It should be
1065 * the DN of the user object!
1067 * w2k3 gives an error when we send an incorrect DN, but sending nothing
1068 * is ok and matches the information flow used in GSS-SPNEGO.
1071 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
1072 &output_token
, /* used as *input* here. */
1074 &input_token
); /* Used as *output* here. */
1076 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1077 output_token
.length
= 0;
1078 SAFE_FREE(output_token
.value
);
1082 /* We've finished with output_token. */
1083 SAFE_FREE(output_token
.value
);
1084 output_token
.length
= 0;
1086 cred
.bv_val
= (char *)input_token
.value
;
1087 cred
.bv_len
= input_token
.length
;
1089 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
1091 gss_release_buffer(&minor_status
, &input_token
);
1092 status
= ADS_ERROR(rc
);
1093 if (!ADS_ERR_OK(status
)) {
1097 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
1098 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
1099 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
1101 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
1103 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1107 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
1108 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1109 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
1110 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
1111 if (!ADS_ERR_OK(status
)) {
1112 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1113 ads_errstr(status
)));
1116 /* make sure we don't free context_handle */
1117 context_handle
= GSS_C_NO_CONTEXT
;
1122 if (context_handle
!= GSS_C_NO_CONTEXT
)
1123 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1130 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1133 struct ads_service_principal p
;
1135 status
= ads_generate_service_principal(ads
, NULL
, &p
);
1136 if (!ADS_ERR_OK(status
)) {
1140 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1141 if (ADS_ERR_OK(status
)) {
1142 ads_free_service_principal(&p
);
1146 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1147 "calling kinit\n", ads_errstr(status
)));
1149 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1151 if (ADS_ERR_OK(status
)) {
1152 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1155 ads_free_service_principal(&p
);
1160 #endif /* HAVE_KRB5 */
1162 /* mapping between SASL mechanisms and functions */
1165 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1166 } sasl_mechanisms
[] = {
1167 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1169 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1174 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1176 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1182 /* get a list of supported SASL mechanisms */
1183 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1184 if (!ADS_ERR_OK(status
)) return status
;
1186 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1188 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1189 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1190 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1191 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1193 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1196 /* try our supported mechanisms in order */
1197 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1198 /* see if the server supports it */
1199 for (j
=0;values
&& values
[j
];j
++) {
1200 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1201 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1203 status
= sasl_mechanisms
[i
].fn(ads
);
1204 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
1205 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
1206 ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
1208 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1209 "retrying with signing enabled\n"));
1210 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1213 ldap_value_free(values
);
1220 ldap_value_free(values
);
1222 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1225 #endif /* HAVE_LDAP */