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 nt_status
= ntlmssp_client_start(NULL
,
140 lp_client_ntlmv2_auth(),
142 if (!NT_STATUS_IS_OK(nt_status
)) {
143 return ADS_ERROR_NT(nt_status
);
145 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SIGN
;
147 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, ads
->auth
.user_name
))) {
148 return ADS_ERROR_NT(nt_status
);
150 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, ads
->auth
.realm
))) {
151 return ADS_ERROR_NT(nt_status
);
153 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, ads
->auth
.password
))) {
154 return ADS_ERROR_NT(nt_status
);
157 switch (ads
->ldap
.wrap_type
) {
158 case ADS_SASLWRAP_TYPE_SEAL
:
159 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
161 case ADS_SASLWRAP_TYPE_SIGN
:
162 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
163 features
= NTLMSSP_FEATURE_SIGN
;
166 * windows servers are broken with sign only,
167 * so we need to use seal here too
169 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
170 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
173 case ADS_SASLWRAP_TYPE_PLAIN
:
177 ntlmssp_want_feature(ntlmssp_state
, features
);
179 blob_in
= data_blob_null
;
182 nt_status
= ntlmssp_update(ntlmssp_state
,
184 data_blob_free(&blob_in
);
185 if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
186 || NT_STATUS_IS_OK(nt_status
))
187 && blob_out
.length
) {
189 /* and wrap it in a SPNEGO wrapper */
190 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
192 /* wrap it in SPNEGO */
193 msg1
= spnego_gen_auth(blob_out
);
196 data_blob_free(&blob_out
);
198 cred
.bv_val
= (char *)msg1
.data
;
199 cred
.bv_len
= msg1
.length
;
201 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
202 data_blob_free(&msg1
);
203 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
208 ntlmssp_end(&ntlmssp_state
);
209 return ADS_ERROR(rc
);
212 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
215 blob
= data_blob_null
;
220 ntlmssp_end(&ntlmssp_state
);
221 data_blob_free(&blob_out
);
222 return ADS_ERROR_NT(nt_status
);
226 (rc
== LDAP_SASL_BIND_IN_PROGRESS
)) {
227 DATA_BLOB tmp_blob
= data_blob_null
;
228 /* the server might give us back two challenges */
229 if (!spnego_parse_challenge(blob
, &blob_in
,
232 ntlmssp_end(&ntlmssp_state
);
233 data_blob_free(&blob
);
234 DEBUG(3,("Failed to parse challenges\n"));
235 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
237 data_blob_free(&tmp_blob
);
238 } else if (rc
== LDAP_SASL_BIND_IN_PROGRESS
) {
239 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
242 ntlmssp_end(&ntlmssp_state
);
243 data_blob_free(&blob
);
244 DEBUG(3,("Failed to parse auth response\n"));
245 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
248 data_blob_free(&blob
);
249 data_blob_free(&blob_out
);
251 } while (rc
== LDAP_SASL_BIND_IN_PROGRESS
&& !NT_STATUS_IS_OK(nt_status
));
253 /* we have a reference conter on ntlmssp_state, if we are signing
254 then the state will be kept by the signing engine */
256 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
257 ads
->ldap
.out
.max_unwrapped
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
- NTLMSSP_SIG_SIZE
;
258 ads
->ldap
.out
.sig_size
= NTLMSSP_SIG_SIZE
;
259 ads
->ldap
.in
.min_wrapped
= ads
->ldap
.out
.sig_size
;
260 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
261 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_ntlmssp_ops
, ntlmssp_state
);
262 if (!ADS_ERR_OK(status
)) {
263 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
264 ads_errstr(status
)));
265 ntlmssp_end(&ntlmssp_state
);
269 ntlmssp_end(&ntlmssp_state
);
272 return ADS_ERROR(rc
);
276 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
278 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
282 gss_buffer_desc unwrapped
, wrapped
;
283 int conf_req_flag
, conf_state
;
285 unwrapped
.value
= buf
;
286 unwrapped
.length
= len
;
288 /* for now request sign and seal */
289 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
291 gss_rc
= gss_wrap(&minor_status
, context_handle
,
292 conf_req_flag
, GSS_C_QOP_DEFAULT
,
293 &unwrapped
, &conf_state
,
295 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
296 if (!ADS_ERR_OK(status
)) return status
;
298 if (conf_req_flag
&& conf_state
== 0) {
299 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
302 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
303 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
306 /* copy the wrapped blob to the right location */
307 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
309 /* set how many bytes must be written to the underlying socket */
310 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
312 gss_release_buffer(&minor_status
, &wrapped
);
317 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
319 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
323 gss_buffer_desc unwrapped
, wrapped
;
326 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
327 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
329 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
330 &wrapped
, &unwrapped
,
331 &conf_state
, GSS_C_QOP_DEFAULT
);
332 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
333 if (!ADS_ERR_OK(status
)) return status
;
335 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
336 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
339 if (wrapped
.length
< unwrapped
.length
) {
340 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
343 /* copy the wrapped blob to the right location */
344 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
346 /* set how many bytes must be written to the underlying socket */
347 ads
->ldap
.in
.left
= unwrapped
.length
;
348 ads
->ldap
.in
.ofs
= 4;
350 gss_release_buffer(&minor_status
, &unwrapped
);
355 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
357 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
360 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
362 ads
->ldap
.wrap_ops
= NULL
;
363 ads
->ldap
.wrap_private_data
= NULL
;
366 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
368 .wrap
= ads_sasl_gssapi_wrap
,
369 .unwrap
= ads_sasl_gssapi_unwrap
,
370 .disconnect
= ads_sasl_gssapi_disconnect
374 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
376 static ADS_STATUS
ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
382 gss_OID_desc krb5_mech_type
=
383 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
384 gss_OID mech_type
= &krb5_mech_type
;
385 gss_OID actual_mech_type
= GSS_C_NULL_OID
;
386 const char *spnego_mechs
[] = {OID_KERBEROS5_OLD
, OID_KERBEROS5
, OID_NTLMSSP
, NULL
};
387 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
388 gss_buffer_desc input_token
, output_token
;
389 uint32 req_flags
, ret_flags
;
390 uint32 req_tmp
, ret_tmp
;
393 struct berval cred
, *scred
= NULL
;
395 input_token
.value
= NULL
;
396 input_token
.length
= 0;
398 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
;
399 switch (ads
->ldap
.wrap_type
) {
400 case ADS_SASLWRAP_TYPE_SEAL
:
401 req_flags
|= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
403 case ADS_SASLWRAP_TYPE_SIGN
:
404 req_flags
|= GSS_C_INTEG_FLAG
;
406 case ADS_SASLWRAP_TYPE_PLAIN
:
410 /* Note: here we explicit ask for the krb5 mech_type */
411 gss_rc
= gss_init_sec_context(&minor_status
,
424 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
425 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
430 * As some gssapi krb5 mech implementations
431 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
432 * to req_flags internaly, it's not possible to
433 * use plain or signing only connection via
434 * the gssapi interface.
436 * Because of this we need to check it the ret_flags
437 * has more flags as req_flags and correct the value
438 * of ads->ldap.wrap_type.
440 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
441 * we need to give an error.
443 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
444 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
446 if (req_tmp
== ret_tmp
) {
447 /* everythings fine... */
449 } else if (req_flags
& GSS_C_CONF_FLAG
) {
451 * here we wanted sealing but didn't got it
452 * from the gssapi library
454 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
457 } else if ((req_flags
& GSS_C_INTEG_FLAG
) &&
458 !(ret_flags
& GSS_C_INTEG_FLAG
)) {
460 * here we wanted siging but didn't got it
461 * from the gssapi library
463 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
466 } else if (ret_flags
& GSS_C_CONF_FLAG
) {
468 * here we didn't want sealing
469 * but the gssapi library forces it
470 * so correct the needed wrap_type if
471 * the caller didn't forced siging only
473 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
474 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
478 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
479 req_flags
= ret_flags
;
481 } else if (ret_flags
& GSS_C_INTEG_FLAG
) {
483 * here we didn't want signing
484 * but the gssapi library forces it
485 * so correct the needed wrap_type if
486 * the caller didn't forced plain
488 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
489 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
493 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
494 req_flags
= ret_flags
;
497 * This could (should?) not happen
499 status
= ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
504 /* and wrap that in a shiny SPNEGO wrapper */
505 unwrapped
= data_blob_const(output_token
.value
, output_token
.length
);
506 wrapped
= gen_negTokenTarg(spnego_mechs
, unwrapped
);
507 gss_release_buffer(&minor_status
, &output_token
);
508 if (unwrapped
.length
> wrapped
.length
) {
509 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
513 cred
.bv_val
= (char *)wrapped
.data
;
514 cred
.bv_len
= wrapped
.length
;
516 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
,
518 data_blob_free(&wrapped
);
519 if (rc
!= LDAP_SUCCESS
) {
520 status
= ADS_ERROR(rc
);
525 wrapped
= data_blob_const(scred
->bv_val
, scred
->bv_len
);
527 wrapped
= data_blob_null
;
530 ok
= spnego_parse_auth_response(wrapped
, NT_STATUS_OK
,
533 if (scred
) ber_bvfree(scred
);
535 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
539 input_token
.value
= unwrapped
.data
;
540 input_token
.length
= unwrapped
.length
;
543 * As we asked for mutal authentication
544 * we need to pass the servers response
547 gss_rc
= gss_init_sec_context(&minor_status
,
560 data_blob_free(&unwrapped
);
562 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
566 gss_release_buffer(&minor_status
, &output_token
);
569 * If we the sign and seal options
570 * doesn't match after getting the response
571 * from the server, we don't want to use the connection
573 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
574 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
576 if (req_tmp
!= ret_tmp
) {
577 /* everythings fine... */
578 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
582 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
583 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
585 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
586 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
588 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
590 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
594 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
595 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
596 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
597 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
598 if (!ADS_ERR_OK(status
)) {
599 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
600 ads_errstr(status
)));
603 /* make sure we don't free context_handle */
604 context_handle
= GSS_C_NO_CONTEXT
;
607 status
= ADS_SUCCESS
;
610 if (context_handle
!= GSS_C_NO_CONTEXT
)
611 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
615 #endif /* HAVE_GSSAPI */
618 struct ads_service_principal
{
625 static void ads_free_service_principal(struct ads_service_principal
*p
)
627 SAFE_FREE(p
->string
);
632 gss_release_name(&minor_status
, &p
->name
);
638 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
639 const char *given_principal
,
640 struct ads_service_principal
*p
)
644 gss_buffer_desc input_name
;
645 /* GSS_KRB5_NT_PRINCIPAL_NAME */
646 gss_OID_desc nt_principal
=
647 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
654 /* I've seen a child Windows 2000 domain not send
655 the principal name back in the first round of
656 the SASL bind reply. So we guess based on server
657 name and realm. --jerry */
658 /* Also try best guess when we get the w2k8 ignore
659 principal back - gd */
661 if (!given_principal
||
662 strequal(given_principal
, ADS_IGNORE_PRINCIPAL
)) {
664 status
= ads_guess_service_principal(ads
, &p
->string
);
665 if (!ADS_ERR_OK(status
)) {
669 p
->string
= SMB_STRDUP(given_principal
);
671 return ADS_ERROR(LDAP_NO_MEMORY
);
676 input_name
.value
= p
->string
;
677 input_name
.length
= strlen(p
->string
);
679 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
681 ads_free_service_principal(p
);
682 return ADS_ERROR_GSS(gss_rc
, minor_status
);
690 perform a LDAP/SASL/SPNEGO/KRB5 bind
692 static ADS_STATUS
ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT
*ads
, const char *principal
)
694 DATA_BLOB blob
= data_blob_null
;
695 struct berval cred
, *scred
= NULL
;
696 DATA_BLOB session_key
= data_blob_null
;
699 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
700 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
703 rc
= spnego_gen_negTokenTarg(principal
, ads
->auth
.time_offset
, &blob
, &session_key
, 0,
704 &ads
->auth
.tgs_expire
);
707 return ADS_ERROR_KRB5(rc
);
710 /* now send the auth packet and we should be done */
711 cred
.bv_val
= (char *)blob
.data
;
712 cred
.bv_len
= blob
.length
;
714 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
716 data_blob_free(&blob
);
717 data_blob_free(&session_key
);
721 return ADS_ERROR(rc
);
724 static ADS_STATUS
ads_sasl_spnego_krb5_bind(ADS_STRUCT
*ads
,
725 struct ads_service_principal
*p
)
729 * we only use the gsskrb5 based implementation
730 * when sasl sign or seal is requested.
732 * This has the following reasons:
733 * - it's likely that the gssapi krb5 mech implementation
734 * doesn't support to negotiate plain connections
735 * - the ads_sasl_spnego_rawkrb5_bind is more robust
736 * against clock skew errors
738 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
739 return ads_sasl_spnego_gsskrb5_bind(ads
, p
->name
);
742 return ads_sasl_spnego_rawkrb5_bind(ads
, p
->string
);
744 #endif /* HAVE_KRB5 */
747 this performs a SASL/SPNEGO bind
749 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
751 struct berval
*scred
=NULL
;
755 char *given_principal
= NULL
;
756 char *OIDs
[ASN1_MAX_OIDS
];
758 bool got_kerberos_mechanism
= False
;
761 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
763 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
764 status
= ADS_ERROR(rc
);
768 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
773 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
776 /* the server sent us the first part of the SPNEGO exchange in the negprot
778 if (!spnego_parse_negTokenInit(blob
, OIDs
, &given_principal
)) {
779 data_blob_free(&blob
);
780 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
783 data_blob_free(&blob
);
785 /* make sure the server understands kerberos */
786 for (i
=0;OIDs
[i
];i
++) {
787 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
789 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
790 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
791 got_kerberos_mechanism
= True
;
794 talloc_free(OIDs
[i
]);
796 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal
));
799 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
800 got_kerberos_mechanism
)
802 struct ads_service_principal p
;
804 status
= ads_generate_service_principal(ads
, given_principal
, &p
);
805 TALLOC_FREE(given_principal
);
806 if (!ADS_ERR_OK(status
)) {
810 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
811 if (ADS_ERR_OK(status
)) {
812 ads_free_service_principal(&p
);
816 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
817 "calling kinit\n", ads_errstr(status
)));
819 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
821 if (ADS_ERR_OK(status
)) {
822 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
823 if (!ADS_ERR_OK(status
)) {
824 DEBUG(0,("kinit succeeded but "
825 "ads_sasl_spnego_krb5_bind failed: %s\n",
826 ads_errstr(status
)));
830 ads_free_service_principal(&p
);
832 /* only fallback to NTLMSSP if allowed */
833 if (ADS_ERR_OK(status
) ||
834 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
840 TALLOC_FREE(given_principal
);
843 /* lets do NTLMSSP ... this has the big advantage that we don't need
844 to sync clocks, and we don't rely on special versions of the krb5
845 library for HMAC_MD4 encryption */
846 return ads_sasl_spnego_ntlmssp_bind(ads
);
853 #define MAX_GSS_PASSES 3
855 /* this performs a SASL/gssapi bind
856 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
857 is very dependent on correctly configured DNS whereas
858 this routine is much less fragile
859 see RFC2078 and RFC2222 for details
861 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
864 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
865 gss_OID mech_type
= GSS_C_NULL_OID
;
866 gss_buffer_desc output_token
, input_token
;
867 uint32 req_flags
, ret_flags
;
870 struct berval
*scred
= NULL
;
874 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
875 uint8 wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
878 input_token
.value
= NULL
;
879 input_token
.length
= 0;
882 * Note: here we always ask the gssapi for sign and seal
883 * as this is negotiated later after the mutal
886 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
888 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
889 gss_rc
= gss_init_sec_context(&minor_status
,
906 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
907 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
911 cred
.bv_val
= (char *)output_token
.value
;
912 cred
.bv_len
= output_token
.length
;
914 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
916 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
917 status
= ADS_ERROR(rc
);
921 if (output_token
.value
) {
922 gss_release_buffer(&minor_status
, &output_token
);
926 input_token
.value
= scred
->bv_val
;
927 input_token
.length
= scred
->bv_len
;
929 input_token
.value
= NULL
;
930 input_token
.length
= 0;
933 if (gss_rc
== 0) break;
936 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
943 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
947 p
= (uint8
*)output_token
.value
;
950 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
954 wrap_type
= CVAL(p
,0);
956 max_msg_size
= RIVAL(p
,0);
959 gss_release_buffer(&minor_status
, &output_token
);
961 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
963 * the server doesn't supports the wrap
966 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
967 ads
->ldap
.wrap_type
, wrap_type
));
968 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
969 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
973 /* 0x58 is the minimum windows accepts */
974 if (max_msg_size
< 0x58) {
978 output_token
.length
= 4;
979 output_token
.value
= SMB_MALLOC(output_token
.length
);
980 p
= (uint8
*)output_token
.value
;
982 RSIVAL(p
,0,max_msg_size
);
983 SCVAL(p
,0,ads
->ldap
.wrap_type
);
986 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
987 * but using ads->config.bind_path is the wrong! It should be
988 * the DN of the user object!
990 * w2k3 gives an error when we send an incorrect DN, but sending nothing
991 * is ok and matches the information flow used in GSS-SPNEGO.
994 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
995 &output_token
, &conf_state
,
998 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1002 free(output_token
.value
);
1004 cred
.bv_val
= (char *)input_token
.value
;
1005 cred
.bv_len
= input_token
.length
;
1007 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
1009 gss_release_buffer(&minor_status
, &input_token
);
1010 status
= ADS_ERROR(rc
);
1011 if (!ADS_ERR_OK(status
)) {
1015 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
1016 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
1017 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
1019 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
1021 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1025 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
1026 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1027 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
1028 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
1029 if (!ADS_ERR_OK(status
)) {
1030 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1031 ads_errstr(status
)));
1034 /* make sure we don't free context_handle */
1035 context_handle
= GSS_C_NO_CONTEXT
;
1040 if (context_handle
!= GSS_C_NO_CONTEXT
)
1041 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1048 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1051 struct ads_service_principal p
;
1053 status
= ads_generate_service_principal(ads
, NULL
, &p
);
1054 if (!ADS_ERR_OK(status
)) {
1058 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1059 if (ADS_ERR_OK(status
)) {
1060 ads_free_service_principal(&p
);
1064 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1065 "calling kinit\n", ads_errstr(status
)));
1067 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1069 if (ADS_ERR_OK(status
)) {
1070 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1073 ads_free_service_principal(&p
);
1078 #endif /* HAVE_GSSAPI */
1080 /* mapping between SASL mechanisms and functions */
1083 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1084 } sasl_mechanisms
[] = {
1085 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1087 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1092 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1094 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1100 /* get a list of supported SASL mechanisms */
1101 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1102 if (!ADS_ERR_OK(status
)) return status
;
1104 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1106 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1107 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1108 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1109 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1111 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1114 /* try our supported mechanisms in order */
1115 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1116 /* see if the server supports it */
1117 for (j
=0;values
&& values
[j
];j
++) {
1118 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1119 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1121 status
= sasl_mechanisms
[i
].fn(ads
);
1122 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
1123 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
1124 ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
1126 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1127 "retrying with signing enabled\n"));
1128 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1131 ldap_value_free(values
);
1138 ldap_value_free(values
);
1140 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1143 #endif /* HAVE_LDAP */