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"
26 static ADS_STATUS
ads_sasl_ntlmssp_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
28 struct ntlmssp_state
*ntlmssp_state
=
29 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
33 uint8
*dptr
= ads
->ldap
.out
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
35 /* copy the data to the right location */
36 memcpy(dptr
, buf
, len
);
38 /* create the signature and may encrypt the data */
39 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
40 nt_status
= ntlmssp_seal_packet(ntlmssp_state
,
45 nt_status
= ntlmssp_sign_packet(ntlmssp_state
,
50 status
= ADS_ERROR_NT(nt_status
);
51 if (!ADS_ERR_OK(status
)) return status
;
53 /* copy the signature to the right location */
54 memcpy(ads
->ldap
.out
.buf
+ 4,
55 sig
.data
, NTLMSSP_SIG_SIZE
);
59 /* set how many bytes must be written to the underlying socket */
60 ads
->ldap
.out
.left
= 4 + NTLMSSP_SIG_SIZE
+ len
;
65 static ADS_STATUS
ads_sasl_ntlmssp_unwrap(ADS_STRUCT
*ads
)
67 struct ntlmssp_state
*ntlmssp_state
=
68 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
72 uint8
*dptr
= ads
->ldap
.in
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
73 uint32 dlen
= ads
->ldap
.in
.ofs
- (4 + NTLMSSP_SIG_SIZE
);
75 /* wrap the signature into a DATA_BLOB */
76 sig
= data_blob_const(ads
->ldap
.in
.buf
+ 4, NTLMSSP_SIG_SIZE
);
78 /* verify the signature and maybe decrypt the data */
79 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
80 nt_status
= ntlmssp_unseal_packet(ntlmssp_state
,
85 nt_status
= ntlmssp_check_packet(ntlmssp_state
,
90 status
= ADS_ERROR_NT(nt_status
);
91 if (!ADS_ERR_OK(status
)) return status
;
93 /* set the amount of bytes for the upper layer and set the ofs to the data */
94 ads
->ldap
.in
.left
= dlen
;
95 ads
->ldap
.in
.ofs
= 4 + NTLMSSP_SIG_SIZE
;
100 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT
*ads
)
102 struct ntlmssp_state
*ntlmssp_state
=
103 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
105 ntlmssp_end(&ntlmssp_state
);
107 ads
->ldap
.wrap_ops
= NULL
;
108 ads
->ldap
.wrap_private_data
= NULL
;
111 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops
= {
113 .wrap
= ads_sasl_ntlmssp_wrap
,
114 .unwrap
= ads_sasl_ntlmssp_unwrap
,
115 .disconnect
= ads_sasl_ntlmssp_disconnect
119 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
120 we fit on one socket??)
122 static ADS_STATUS
ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT
*ads
)
124 DATA_BLOB msg1
= data_blob_null
;
125 DATA_BLOB blob
= data_blob_null
;
126 DATA_BLOB blob_in
= data_blob_null
;
127 DATA_BLOB blob_out
= data_blob_null
;
128 struct berval cred
, *scred
= NULL
;
135 struct ntlmssp_state
*ntlmssp_state
;
137 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
138 return ADS_ERROR_NT(nt_status
);
140 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SIGN
;
142 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, ads
->auth
.user_name
))) {
143 return ADS_ERROR_NT(nt_status
);
145 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, ads
->auth
.realm
))) {
146 return ADS_ERROR_NT(nt_status
);
148 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, ads
->auth
.password
))) {
149 return ADS_ERROR_NT(nt_status
);
152 switch (ads
->ldap
.wrap_type
) {
153 case ADS_SASLWRAP_TYPE_SEAL
:
154 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
156 case ADS_SASLWRAP_TYPE_SIGN
:
157 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
158 features
= NTLMSSP_FEATURE_SIGN
;
161 * windows servers are broken with sign only,
162 * so we need to use seal here too
164 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
165 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
168 case ADS_SASLWRAP_TYPE_PLAIN
:
172 ntlmssp_want_feature(ntlmssp_state
, features
);
174 blob_in
= data_blob_null
;
177 nt_status
= ntlmssp_update(ntlmssp_state
,
179 data_blob_free(&blob_in
);
180 if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
181 || NT_STATUS_IS_OK(nt_status
))
182 && blob_out
.length
) {
184 /* and wrap it in a SPNEGO wrapper */
185 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
187 /* wrap it in SPNEGO */
188 msg1
= spnego_gen_auth(blob_out
);
191 data_blob_free(&blob_out
);
193 cred
.bv_val
= (char *)msg1
.data
;
194 cred
.bv_len
= msg1
.length
;
196 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
197 data_blob_free(&msg1
);
198 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
203 ntlmssp_end(&ntlmssp_state
);
204 return ADS_ERROR(rc
);
207 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
210 blob
= data_blob_null
;
215 ntlmssp_end(&ntlmssp_state
);
216 data_blob_free(&blob_out
);
217 return ADS_ERROR_NT(nt_status
);
221 (rc
== LDAP_SASL_BIND_IN_PROGRESS
)) {
222 DATA_BLOB tmp_blob
= data_blob_null
;
223 /* the server might give us back two challenges */
224 if (!spnego_parse_challenge(blob
, &blob_in
,
227 ntlmssp_end(&ntlmssp_state
);
228 data_blob_free(&blob
);
229 DEBUG(3,("Failed to parse challenges\n"));
230 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
232 data_blob_free(&tmp_blob
);
233 } else if (rc
== LDAP_SASL_BIND_IN_PROGRESS
) {
234 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
237 ntlmssp_end(&ntlmssp_state
);
238 data_blob_free(&blob
);
239 DEBUG(3,("Failed to parse auth response\n"));
240 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
243 data_blob_free(&blob
);
244 data_blob_free(&blob_out
);
246 } while (rc
== LDAP_SASL_BIND_IN_PROGRESS
&& !NT_STATUS_IS_OK(nt_status
));
248 /* we have a reference conter on ntlmssp_state, if we are signing
249 then the state will be kept by the signing engine */
251 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
252 ads
->ldap
.out
.max_unwrapped
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
- NTLMSSP_SIG_SIZE
;
253 ads
->ldap
.out
.sig_size
= NTLMSSP_SIG_SIZE
;
254 ads
->ldap
.in
.min_wrapped
= ads
->ldap
.out
.sig_size
;
255 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
256 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_ntlmssp_ops
, ntlmssp_state
);
257 if (!ADS_ERR_OK(status
)) {
258 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
259 ads_errstr(status
)));
260 ntlmssp_end(&ntlmssp_state
);
264 ntlmssp_end(&ntlmssp_state
);
267 return ADS_ERROR(rc
);
271 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
273 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
277 gss_buffer_desc unwrapped
, wrapped
;
278 int conf_req_flag
, conf_state
;
280 unwrapped
.value
= buf
;
281 unwrapped
.length
= len
;
283 /* for now request sign and seal */
284 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
286 gss_rc
= gss_wrap(&minor_status
, context_handle
,
287 conf_req_flag
, GSS_C_QOP_DEFAULT
,
288 &unwrapped
, &conf_state
,
290 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
291 if (!ADS_ERR_OK(status
)) return status
;
293 if (conf_req_flag
&& conf_state
== 0) {
294 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
297 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
298 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
301 /* copy the wrapped blob to the right location */
302 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
304 /* set how many bytes must be written to the underlying socket */
305 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
307 gss_release_buffer(&minor_status
, &wrapped
);
312 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
314 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
318 gss_buffer_desc unwrapped
, wrapped
;
321 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
322 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
324 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
325 &wrapped
, &unwrapped
,
326 &conf_state
, GSS_C_QOP_DEFAULT
);
327 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
328 if (!ADS_ERR_OK(status
)) return status
;
330 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
331 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
334 if (wrapped
.length
< unwrapped
.length
) {
335 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
338 /* copy the wrapped blob to the right location */
339 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
341 /* set how many bytes must be written to the underlying socket */
342 ads
->ldap
.in
.left
= unwrapped
.length
;
343 ads
->ldap
.in
.ofs
= 4;
345 gss_release_buffer(&minor_status
, &unwrapped
);
350 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
352 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
355 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
357 ads
->ldap
.wrap_ops
= NULL
;
358 ads
->ldap
.wrap_private_data
= NULL
;
361 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
363 .wrap
= ads_sasl_gssapi_wrap
,
364 .unwrap
= ads_sasl_gssapi_unwrap
,
365 .disconnect
= ads_sasl_gssapi_disconnect
369 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
371 static ADS_STATUS
ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
377 gss_OID_desc krb5_mech_type
=
378 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
379 gss_OID mech_type
= &krb5_mech_type
;
380 gss_OID actual_mech_type
= GSS_C_NULL_OID
;
381 const char *spnego_mechs
[] = {OID_KERBEROS5_OLD
, OID_KERBEROS5
, OID_NTLMSSP
, NULL
};
382 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
383 gss_buffer_desc input_token
, output_token
;
384 uint32 req_flags
, ret_flags
;
385 uint32 req_tmp
, ret_tmp
;
388 struct berval cred
, *scred
= NULL
;
390 input_token
.value
= NULL
;
391 input_token
.length
= 0;
393 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
;
394 switch (ads
->ldap
.wrap_type
) {
395 case ADS_SASLWRAP_TYPE_SEAL
:
396 req_flags
|= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
398 case ADS_SASLWRAP_TYPE_SIGN
:
399 req_flags
|= GSS_C_INTEG_FLAG
;
401 case ADS_SASLWRAP_TYPE_PLAIN
:
405 /* Note: here we explicit ask for the krb5 mech_type */
406 gss_rc
= gss_init_sec_context(&minor_status
,
419 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
420 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
425 * As some gssapi krb5 mech implementations
426 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
427 * to req_flags internaly, it's not possible to
428 * use plain or signing only connection via
429 * the gssapi interface.
431 * Because of this we need to check it the ret_flags
432 * has more flags as req_flags and correct the value
433 * of ads->ldap.wrap_type.
435 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
436 * we need to give an error.
438 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
439 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
441 if (req_tmp
== ret_tmp
) {
442 /* everythings fine... */
444 } else if (req_flags
& GSS_C_CONF_FLAG
) {
446 * here we wanted sealing but didn't got it
447 * from the gssapi library
449 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
452 } else if ((req_flags
& GSS_C_INTEG_FLAG
) &&
453 !(ret_flags
& GSS_C_INTEG_FLAG
)) {
455 * here we wanted siging but didn't got it
456 * from the gssapi library
458 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
461 } else if (ret_flags
& GSS_C_CONF_FLAG
) {
463 * here we didn't want sealing
464 * but the gssapi library forces it
465 * so correct the needed wrap_type if
466 * the caller didn't forced siging only
468 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
469 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
473 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
474 req_flags
= ret_flags
;
476 } else if (ret_flags
& GSS_C_INTEG_FLAG
) {
478 * here we didn't want signing
479 * but the gssapi library forces it
480 * so correct the needed wrap_type if
481 * the caller didn't forced plain
483 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
484 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
488 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
489 req_flags
= ret_flags
;
492 * This could (should?) not happen
494 status
= ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
499 /* and wrap that in a shiny SPNEGO wrapper */
500 unwrapped
= data_blob_const(output_token
.value
, output_token
.length
);
501 wrapped
= gen_negTokenTarg(spnego_mechs
, unwrapped
);
502 gss_release_buffer(&minor_status
, &output_token
);
503 if (unwrapped
.length
> wrapped
.length
) {
504 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
508 cred
.bv_val
= (char *)wrapped
.data
;
509 cred
.bv_len
= wrapped
.length
;
511 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
,
513 data_blob_free(&wrapped
);
514 if (rc
!= LDAP_SUCCESS
) {
515 status
= ADS_ERROR(rc
);
520 wrapped
= data_blob_const(scred
->bv_val
, scred
->bv_len
);
522 wrapped
= data_blob_null
;
525 ok
= spnego_parse_auth_response(wrapped
, NT_STATUS_OK
,
528 if (scred
) ber_bvfree(scred
);
530 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
534 input_token
.value
= unwrapped
.data
;
535 input_token
.length
= unwrapped
.length
;
538 * As we asked for mutal authentication
539 * we need to pass the servers response
542 gss_rc
= gss_init_sec_context(&minor_status
,
555 data_blob_free(&unwrapped
);
557 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
561 gss_release_buffer(&minor_status
, &output_token
);
564 * If we the sign and seal options
565 * doesn't match after getting the response
566 * from the server, we don't want to use the connection
568 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
569 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
571 if (req_tmp
!= ret_tmp
) {
572 /* everythings fine... */
573 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
577 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
578 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
580 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
581 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
583 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
585 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
589 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
590 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
591 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
592 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
593 if (!ADS_ERR_OK(status
)) {
594 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
595 ads_errstr(status
)));
598 /* make sure we don't free context_handle */
599 context_handle
= GSS_C_NO_CONTEXT
;
602 status
= ADS_SUCCESS
;
605 if (context_handle
!= GSS_C_NO_CONTEXT
)
606 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
610 #endif /* HAVE_GSSAPI */
613 struct ads_service_principal
{
620 static void ads_free_service_principal(struct ads_service_principal
*p
)
622 SAFE_FREE(p
->string
);
627 gss_release_name(&minor_status
, &p
->name
);
633 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
634 const char *given_principal
,
635 struct ads_service_principal
*p
)
639 gss_buffer_desc input_name
;
640 /* GSS_KRB5_NT_PRINCIPAL_NAME */
641 gss_OID_desc nt_principal
=
642 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
649 /* I've seen a child Windows 2000 domain not send
650 the principal name back in the first round of
651 the SASL bind reply. So we guess based on server
652 name and realm. --jerry */
653 /* Also try best guess when we get the w2k8 ignore
654 principal back - gd */
656 if (!given_principal
||
657 strequal(given_principal
, ADS_IGNORE_PRINCIPAL
)) {
659 status
= ads_guess_service_principal(ads
, &p
->string
);
660 if (!ADS_ERR_OK(status
)) {
664 p
->string
= SMB_STRDUP(given_principal
);
666 return ADS_ERROR(LDAP_NO_MEMORY
);
671 input_name
.value
= p
->string
;
672 input_name
.length
= strlen(p
->string
);
674 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
676 ads_free_service_principal(p
);
677 return ADS_ERROR_GSS(gss_rc
, minor_status
);
685 perform a LDAP/SASL/SPNEGO/KRB5 bind
687 static ADS_STATUS
ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT
*ads
, const char *principal
)
689 DATA_BLOB blob
= data_blob_null
;
690 struct berval cred
, *scred
= NULL
;
691 DATA_BLOB session_key
= data_blob_null
;
694 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
695 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
698 rc
= spnego_gen_negTokenTarg(principal
, ads
->auth
.time_offset
, &blob
, &session_key
, 0,
699 &ads
->auth
.tgs_expire
);
702 return ADS_ERROR_KRB5(rc
);
705 /* now send the auth packet and we should be done */
706 cred
.bv_val
= (char *)blob
.data
;
707 cred
.bv_len
= blob
.length
;
709 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
711 data_blob_free(&blob
);
712 data_blob_free(&session_key
);
716 return ADS_ERROR(rc
);
719 static ADS_STATUS
ads_sasl_spnego_krb5_bind(ADS_STRUCT
*ads
,
720 struct ads_service_principal
*p
)
724 * we only use the gsskrb5 based implementation
725 * when sasl sign or seal is requested.
727 * This has the following reasons:
728 * - it's likely that the gssapi krb5 mech implementation
729 * doesn't support to negotiate plain connections
730 * - the ads_sasl_spnego_rawkrb5_bind is more robust
731 * against clock skew errors
733 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
734 return ads_sasl_spnego_gsskrb5_bind(ads
, p
->name
);
737 return ads_sasl_spnego_rawkrb5_bind(ads
, p
->string
);
739 #endif /* HAVE_KRB5 */
742 this performs a SASL/SPNEGO bind
744 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
746 struct berval
*scred
=NULL
;
750 char *given_principal
= NULL
;
751 char *OIDs
[ASN1_MAX_OIDS
];
753 bool got_kerberos_mechanism
= False
;
756 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
758 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
759 status
= ADS_ERROR(rc
);
763 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
768 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
771 /* the server sent us the first part of the SPNEGO exchange in the negprot
773 if (!spnego_parse_negTokenInit(blob
, OIDs
, &given_principal
)) {
774 data_blob_free(&blob
);
775 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
778 data_blob_free(&blob
);
780 /* make sure the server understands kerberos */
781 for (i
=0;OIDs
[i
];i
++) {
782 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
784 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
785 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
786 got_kerberos_mechanism
= True
;
789 talloc_free(OIDs
[i
]);
791 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal
));
794 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
795 got_kerberos_mechanism
)
797 struct ads_service_principal p
;
799 status
= ads_generate_service_principal(ads
, given_principal
, &p
);
800 TALLOC_FREE(given_principal
);
801 if (!ADS_ERR_OK(status
)) {
805 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
806 if (ADS_ERR_OK(status
)) {
807 ads_free_service_principal(&p
);
811 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
812 "calling kinit\n", ads_errstr(status
)));
814 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
816 if (ADS_ERR_OK(status
)) {
817 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
818 if (!ADS_ERR_OK(status
)) {
819 DEBUG(0,("kinit succeeded but "
820 "ads_sasl_spnego_krb5_bind failed: %s\n",
821 ads_errstr(status
)));
825 ads_free_service_principal(&p
);
827 /* only fallback to NTLMSSP if allowed */
828 if (ADS_ERR_OK(status
) ||
829 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
835 TALLOC_FREE(given_principal
);
838 /* lets do NTLMSSP ... this has the big advantage that we don't need
839 to sync clocks, and we don't rely on special versions of the krb5
840 library for HMAC_MD4 encryption */
841 return ads_sasl_spnego_ntlmssp_bind(ads
);
848 #define MAX_GSS_PASSES 3
850 /* this performs a SASL/gssapi bind
851 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
852 is very dependent on correctly configured DNS whereas
853 this routine is much less fragile
854 see RFC2078 and RFC2222 for details
856 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
859 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
860 gss_OID mech_type
= GSS_C_NULL_OID
;
861 gss_buffer_desc output_token
, input_token
;
862 uint32 req_flags
, ret_flags
;
865 struct berval
*scred
= NULL
;
869 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
870 uint8 wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
873 input_token
.value
= NULL
;
874 input_token
.length
= 0;
877 * Note: here we always ask the gssapi for sign and seal
878 * as this is negotiated later after the mutal
881 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
883 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
884 gss_rc
= gss_init_sec_context(&minor_status
,
901 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
902 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
906 cred
.bv_val
= (char *)output_token
.value
;
907 cred
.bv_len
= output_token
.length
;
909 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
911 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
912 status
= ADS_ERROR(rc
);
916 if (output_token
.value
) {
917 gss_release_buffer(&minor_status
, &output_token
);
921 input_token
.value
= scred
->bv_val
;
922 input_token
.length
= scred
->bv_len
;
924 input_token
.value
= NULL
;
925 input_token
.length
= 0;
928 if (gss_rc
== 0) break;
931 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
938 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
942 p
= (uint8
*)output_token
.value
;
945 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
949 wrap_type
= CVAL(p
,0);
951 max_msg_size
= RIVAL(p
,0);
954 gss_release_buffer(&minor_status
, &output_token
);
956 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
958 * the server doesn't supports the wrap
961 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
962 ads
->ldap
.wrap_type
, wrap_type
));
963 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
964 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
968 /* 0x58 is the minimum windows accepts */
969 if (max_msg_size
< 0x58) {
973 output_token
.length
= 4;
974 output_token
.value
= SMB_MALLOC(output_token
.length
);
975 p
= (uint8
*)output_token
.value
;
977 RSIVAL(p
,0,max_msg_size
);
978 SCVAL(p
,0,ads
->ldap
.wrap_type
);
981 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
982 * but using ads->config.bind_path is the wrong! It should be
983 * the DN of the user object!
985 * w2k3 gives an error when we send an incorrect DN, but sending nothing
986 * is ok and matches the information flow used in GSS-SPNEGO.
989 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
990 &output_token
, &conf_state
,
993 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
997 free(output_token
.value
);
999 cred
.bv_val
= (char *)input_token
.value
;
1000 cred
.bv_len
= input_token
.length
;
1002 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
1004 gss_release_buffer(&minor_status
, &input_token
);
1005 status
= ADS_ERROR(rc
);
1006 if (!ADS_ERR_OK(status
)) {
1010 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
1011 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
1012 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
1014 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
1016 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1020 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
1021 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1022 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
1023 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
1024 if (!ADS_ERR_OK(status
)) {
1025 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1026 ads_errstr(status
)));
1029 /* make sure we don't free context_handle */
1030 context_handle
= GSS_C_NO_CONTEXT
;
1035 if (context_handle
!= GSS_C_NO_CONTEXT
)
1036 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1043 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1046 struct ads_service_principal p
;
1048 status
= ads_generate_service_principal(ads
, NULL
, &p
);
1049 if (!ADS_ERR_OK(status
)) {
1053 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1054 if (ADS_ERR_OK(status
)) {
1055 ads_free_service_principal(&p
);
1059 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1060 "calling kinit\n", ads_errstr(status
)));
1062 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1064 if (ADS_ERR_OK(status
)) {
1065 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1068 ads_free_service_principal(&p
);
1073 #endif /* HAVE_GSSAPI */
1075 /* mapping between SASL mechanisms and functions */
1078 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1079 } sasl_mechanisms
[] = {
1080 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1082 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1087 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1089 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1095 /* get a list of supported SASL mechanisms */
1096 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1097 if (!ADS_ERR_OK(status
)) return status
;
1099 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1101 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1102 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1103 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1104 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1106 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1109 /* try our supported mechanisms in order */
1110 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1111 /* see if the server supports it */
1112 for (j
=0;values
&& values
[j
];j
++) {
1113 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1114 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1115 status
= sasl_mechanisms
[i
].fn(ads
);
1116 ldap_value_free(values
);
1123 ldap_value_free(values
);
1125 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1128 #endif /* HAVE_LDAP */