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 "../libcli/auth/ntlmssp.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
;
34 uint8
*dptr
= ads
->ldap
.out
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
36 frame
= talloc_stackframe();
37 /* copy the data to the right location */
38 memcpy(dptr
, buf
, len
);
40 /* create the signature and may encrypt the data */
41 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
42 nt_status
= ntlmssp_seal_packet(ntlmssp_state
,
48 nt_status
= ntlmssp_sign_packet(ntlmssp_state
,
54 status
= ADS_ERROR_NT(nt_status
);
55 if (!ADS_ERR_OK(status
)) return status
;
57 /* copy the signature to the right location */
58 memcpy(ads
->ldap
.out
.buf
+ 4,
59 sig
.data
, NTLMSSP_SIG_SIZE
);
63 /* set how many bytes must be written to the underlying socket */
64 ads
->ldap
.out
.left
= 4 + NTLMSSP_SIG_SIZE
+ len
;
69 static ADS_STATUS
ads_sasl_ntlmssp_unwrap(ADS_STRUCT
*ads
)
71 struct ntlmssp_state
*ntlmssp_state
=
72 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
76 uint8
*dptr
= ads
->ldap
.in
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
77 uint32 dlen
= ads
->ldap
.in
.ofs
- (4 + NTLMSSP_SIG_SIZE
);
79 /* wrap the signature into a DATA_BLOB */
80 sig
= data_blob_const(ads
->ldap
.in
.buf
+ 4, NTLMSSP_SIG_SIZE
);
82 /* verify the signature and maybe decrypt the data */
83 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
84 nt_status
= ntlmssp_unseal_packet(ntlmssp_state
,
89 nt_status
= ntlmssp_check_packet(ntlmssp_state
,
94 status
= ADS_ERROR_NT(nt_status
);
95 if (!ADS_ERR_OK(status
)) return status
;
97 /* set the amount of bytes for the upper layer and set the ofs to the data */
98 ads
->ldap
.in
.left
= dlen
;
99 ads
->ldap
.in
.ofs
= 4 + NTLMSSP_SIG_SIZE
;
104 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT
*ads
)
106 struct ntlmssp_state
*ntlmssp_state
=
107 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
109 ntlmssp_end(&ntlmssp_state
);
111 ads
->ldap
.wrap_ops
= NULL
;
112 ads
->ldap
.wrap_private_data
= NULL
;
115 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops
= {
117 .wrap
= ads_sasl_ntlmssp_wrap
,
118 .unwrap
= ads_sasl_ntlmssp_unwrap
,
119 .disconnect
= ads_sasl_ntlmssp_disconnect
123 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
124 we fit on one socket??)
126 static ADS_STATUS
ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT
*ads
)
128 DATA_BLOB msg1
= data_blob_null
;
129 DATA_BLOB blob
= data_blob_null
;
130 DATA_BLOB blob_in
= data_blob_null
;
131 DATA_BLOB blob_out
= data_blob_null
;
132 struct berval cred
, *scred
= NULL
;
139 struct ntlmssp_state
*ntlmssp_state
;
141 nt_status
= ntlmssp_client_start(NULL
,
144 lp_client_ntlmv2_auth(),
146 if (!NT_STATUS_IS_OK(nt_status
)) {
147 return ADS_ERROR_NT(nt_status
);
149 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SIGN
;
151 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, ads
->auth
.user_name
))) {
152 return ADS_ERROR_NT(nt_status
);
154 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, ads
->auth
.realm
))) {
155 return ADS_ERROR_NT(nt_status
);
157 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, ads
->auth
.password
))) {
158 return ADS_ERROR_NT(nt_status
);
161 switch (ads
->ldap
.wrap_type
) {
162 case ADS_SASLWRAP_TYPE_SEAL
:
163 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
165 case ADS_SASLWRAP_TYPE_SIGN
:
166 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
167 features
= NTLMSSP_FEATURE_SIGN
;
170 * windows servers are broken with sign only,
171 * so we need to use seal here too
173 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
174 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
177 case ADS_SASLWRAP_TYPE_PLAIN
:
181 ntlmssp_want_feature(ntlmssp_state
, features
);
183 blob_in
= data_blob_null
;
186 nt_status
= ntlmssp_update(ntlmssp_state
,
188 data_blob_free(&blob_in
);
189 if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
190 || NT_STATUS_IS_OK(nt_status
))
191 && blob_out
.length
) {
193 /* and wrap it in a SPNEGO wrapper */
194 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
196 /* wrap it in SPNEGO */
197 msg1
= spnego_gen_auth(blob_out
);
200 data_blob_free(&blob_out
);
202 cred
.bv_val
= (char *)msg1
.data
;
203 cred
.bv_len
= msg1
.length
;
205 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
206 data_blob_free(&msg1
);
207 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
212 ntlmssp_end(&ntlmssp_state
);
213 return ADS_ERROR(rc
);
216 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
219 blob
= data_blob_null
;
224 ntlmssp_end(&ntlmssp_state
);
225 data_blob_free(&blob_out
);
226 return ADS_ERROR_NT(nt_status
);
230 (rc
== LDAP_SASL_BIND_IN_PROGRESS
)) {
231 DATA_BLOB tmp_blob
= data_blob_null
;
232 /* the server might give us back two challenges */
233 if (!spnego_parse_challenge(blob
, &blob_in
,
236 ntlmssp_end(&ntlmssp_state
);
237 data_blob_free(&blob
);
238 DEBUG(3,("Failed to parse challenges\n"));
239 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
241 data_blob_free(&tmp_blob
);
242 } else if (rc
== LDAP_SASL_BIND_IN_PROGRESS
) {
243 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
246 ntlmssp_end(&ntlmssp_state
);
247 data_blob_free(&blob
);
248 DEBUG(3,("Failed to parse auth response\n"));
249 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
252 data_blob_free(&blob
);
253 data_blob_free(&blob_out
);
255 } while (rc
== LDAP_SASL_BIND_IN_PROGRESS
&& !NT_STATUS_IS_OK(nt_status
));
257 /* we have a reference conter on ntlmssp_state, if we are signing
258 then the state will be kept by the signing engine */
260 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
261 ads
->ldap
.out
.max_unwrapped
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
- NTLMSSP_SIG_SIZE
;
262 ads
->ldap
.out
.sig_size
= NTLMSSP_SIG_SIZE
;
263 ads
->ldap
.in
.min_wrapped
= ads
->ldap
.out
.sig_size
;
264 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
265 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_ntlmssp_ops
, ntlmssp_state
);
266 if (!ADS_ERR_OK(status
)) {
267 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
268 ads_errstr(status
)));
269 ntlmssp_end(&ntlmssp_state
);
273 ntlmssp_end(&ntlmssp_state
);
276 return ADS_ERROR(rc
);
280 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
282 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
286 gss_buffer_desc unwrapped
, wrapped
;
287 int conf_req_flag
, conf_state
;
289 unwrapped
.value
= buf
;
290 unwrapped
.length
= len
;
292 /* for now request sign and seal */
293 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
295 gss_rc
= gss_wrap(&minor_status
, context_handle
,
296 conf_req_flag
, GSS_C_QOP_DEFAULT
,
297 &unwrapped
, &conf_state
,
299 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
300 if (!ADS_ERR_OK(status
)) return status
;
302 if (conf_req_flag
&& conf_state
== 0) {
303 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
306 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
307 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
310 /* copy the wrapped blob to the right location */
311 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
313 /* set how many bytes must be written to the underlying socket */
314 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
316 gss_release_buffer(&minor_status
, &wrapped
);
321 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
323 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
327 gss_buffer_desc unwrapped
, wrapped
;
330 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
331 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
333 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
334 &wrapped
, &unwrapped
,
335 &conf_state
, GSS_C_QOP_DEFAULT
);
336 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
337 if (!ADS_ERR_OK(status
)) return status
;
339 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
340 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
343 if (wrapped
.length
< unwrapped
.length
) {
344 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
347 /* copy the wrapped blob to the right location */
348 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
350 /* set how many bytes must be written to the underlying socket */
351 ads
->ldap
.in
.left
= unwrapped
.length
;
352 ads
->ldap
.in
.ofs
= 4;
354 gss_release_buffer(&minor_status
, &unwrapped
);
359 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
361 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
364 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
366 ads
->ldap
.wrap_ops
= NULL
;
367 ads
->ldap
.wrap_private_data
= NULL
;
370 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
372 .wrap
= ads_sasl_gssapi_wrap
,
373 .unwrap
= ads_sasl_gssapi_unwrap
,
374 .disconnect
= ads_sasl_gssapi_disconnect
378 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
380 static ADS_STATUS
ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
386 gss_OID_desc krb5_mech_type
=
387 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
388 gss_OID mech_type
= &krb5_mech_type
;
389 gss_OID actual_mech_type
= GSS_C_NULL_OID
;
390 const char *spnego_mechs
[] = {OID_KERBEROS5_OLD
, OID_KERBEROS5
, OID_NTLMSSP
, NULL
};
391 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
392 gss_buffer_desc input_token
, output_token
;
393 uint32 req_flags
, ret_flags
;
394 uint32 req_tmp
, ret_tmp
;
397 struct berval cred
, *scred
= NULL
;
399 input_token
.value
= NULL
;
400 input_token
.length
= 0;
402 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
;
403 switch (ads
->ldap
.wrap_type
) {
404 case ADS_SASLWRAP_TYPE_SEAL
:
405 req_flags
|= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
407 case ADS_SASLWRAP_TYPE_SIGN
:
408 req_flags
|= GSS_C_INTEG_FLAG
;
410 case ADS_SASLWRAP_TYPE_PLAIN
:
414 /* Note: here we explicit ask for the krb5 mech_type */
415 gss_rc
= gss_init_sec_context(&minor_status
,
428 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
429 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
434 * As some gssapi krb5 mech implementations
435 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
436 * to req_flags internaly, it's not possible to
437 * use plain or signing only connection via
438 * the gssapi interface.
440 * Because of this we need to check it the ret_flags
441 * has more flags as req_flags and correct the value
442 * of ads->ldap.wrap_type.
444 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
445 * we need to give an error.
447 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
448 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
450 if (req_tmp
== ret_tmp
) {
451 /* everythings fine... */
453 } else if (req_flags
& GSS_C_CONF_FLAG
) {
455 * here we wanted sealing but didn't got it
456 * from the gssapi library
458 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
461 } else if ((req_flags
& GSS_C_INTEG_FLAG
) &&
462 !(ret_flags
& GSS_C_INTEG_FLAG
)) {
464 * here we wanted siging but didn't got it
465 * from the gssapi library
467 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
470 } else if (ret_flags
& GSS_C_CONF_FLAG
) {
472 * here we didn't want sealing
473 * but the gssapi library forces it
474 * so correct the needed wrap_type if
475 * the caller didn't forced siging only
477 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
478 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
482 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
483 req_flags
= ret_flags
;
485 } else if (ret_flags
& GSS_C_INTEG_FLAG
) {
487 * here we didn't want signing
488 * but the gssapi library forces it
489 * so correct the needed wrap_type if
490 * the caller didn't forced plain
492 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
493 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
497 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
498 req_flags
= ret_flags
;
501 * This could (should?) not happen
503 status
= ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
508 /* and wrap that in a shiny SPNEGO wrapper */
509 unwrapped
= data_blob_const(output_token
.value
, output_token
.length
);
510 wrapped
= gen_negTokenTarg(spnego_mechs
, unwrapped
);
511 gss_release_buffer(&minor_status
, &output_token
);
512 if (unwrapped
.length
> wrapped
.length
) {
513 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
517 cred
.bv_val
= (char *)wrapped
.data
;
518 cred
.bv_len
= wrapped
.length
;
520 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
,
522 data_blob_free(&wrapped
);
523 if (rc
!= LDAP_SUCCESS
) {
524 status
= ADS_ERROR(rc
);
529 wrapped
= data_blob_const(scred
->bv_val
, scred
->bv_len
);
531 wrapped
= data_blob_null
;
534 ok
= spnego_parse_auth_response(wrapped
, NT_STATUS_OK
,
537 if (scred
) ber_bvfree(scred
);
539 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
543 input_token
.value
= unwrapped
.data
;
544 input_token
.length
= unwrapped
.length
;
547 * As we asked for mutal authentication
548 * we need to pass the servers response
551 gss_rc
= gss_init_sec_context(&minor_status
,
564 data_blob_free(&unwrapped
);
566 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
570 gss_release_buffer(&minor_status
, &output_token
);
573 * If we the sign and seal options
574 * doesn't match after getting the response
575 * from the server, we don't want to use the connection
577 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
578 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
580 if (req_tmp
!= ret_tmp
) {
581 /* everythings fine... */
582 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
586 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
587 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
589 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
590 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
592 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
594 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
598 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
599 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
600 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
601 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
602 if (!ADS_ERR_OK(status
)) {
603 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
604 ads_errstr(status
)));
607 /* make sure we don't free context_handle */
608 context_handle
= GSS_C_NO_CONTEXT
;
611 status
= ADS_SUCCESS
;
614 if (context_handle
!= GSS_C_NO_CONTEXT
)
615 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
619 #endif /* HAVE_GSSAPI */
622 struct ads_service_principal
{
629 static void ads_free_service_principal(struct ads_service_principal
*p
)
631 SAFE_FREE(p
->string
);
636 gss_release_name(&minor_status
, &p
->name
);
642 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
643 const char *given_principal
,
644 struct ads_service_principal
*p
)
648 gss_buffer_desc input_name
;
649 /* GSS_KRB5_NT_PRINCIPAL_NAME */
650 gss_OID_desc nt_principal
=
651 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
658 /* I've seen a child Windows 2000 domain not send
659 the principal name back in the first round of
660 the SASL bind reply. So we guess based on server
661 name and realm. --jerry */
662 /* Also try best guess when we get the w2k8 ignore
663 principal back - gd */
665 if (!given_principal
||
666 strequal(given_principal
, ADS_IGNORE_PRINCIPAL
)) {
668 status
= ads_guess_service_principal(ads
, &p
->string
);
669 if (!ADS_ERR_OK(status
)) {
673 p
->string
= SMB_STRDUP(given_principal
);
675 return ADS_ERROR(LDAP_NO_MEMORY
);
680 input_name
.value
= p
->string
;
681 input_name
.length
= strlen(p
->string
);
683 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
685 ads_free_service_principal(p
);
686 return ADS_ERROR_GSS(gss_rc
, minor_status
);
694 perform a LDAP/SASL/SPNEGO/KRB5 bind
696 static ADS_STATUS
ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT
*ads
, const char *principal
)
698 DATA_BLOB blob
= data_blob_null
;
699 struct berval cred
, *scred
= NULL
;
700 DATA_BLOB session_key
= data_blob_null
;
703 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
704 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
707 rc
= spnego_gen_negTokenTarg(principal
, ads
->auth
.time_offset
, &blob
, &session_key
, 0,
708 &ads
->auth
.tgs_expire
);
711 return ADS_ERROR_KRB5(rc
);
714 /* now send the auth packet and we should be done */
715 cred
.bv_val
= (char *)blob
.data
;
716 cred
.bv_len
= blob
.length
;
718 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
720 data_blob_free(&blob
);
721 data_blob_free(&session_key
);
725 return ADS_ERROR(rc
);
728 static ADS_STATUS
ads_sasl_spnego_krb5_bind(ADS_STRUCT
*ads
,
729 struct ads_service_principal
*p
)
733 * we only use the gsskrb5 based implementation
734 * when sasl sign or seal is requested.
736 * This has the following reasons:
737 * - it's likely that the gssapi krb5 mech implementation
738 * doesn't support to negotiate plain connections
739 * - the ads_sasl_spnego_rawkrb5_bind is more robust
740 * against clock skew errors
742 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
743 return ads_sasl_spnego_gsskrb5_bind(ads
, p
->name
);
746 return ads_sasl_spnego_rawkrb5_bind(ads
, p
->string
);
748 #endif /* HAVE_KRB5 */
751 this performs a SASL/SPNEGO bind
753 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
755 struct berval
*scred
=NULL
;
759 char *given_principal
= NULL
;
760 char *OIDs
[ASN1_MAX_OIDS
];
762 bool got_kerberos_mechanism
= False
;
765 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
767 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
768 status
= ADS_ERROR(rc
);
772 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
777 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
780 /* the server sent us the first part of the SPNEGO exchange in the negprot
782 if (!spnego_parse_negTokenInit(blob
, OIDs
, &given_principal
)) {
783 data_blob_free(&blob
);
784 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
787 data_blob_free(&blob
);
789 /* make sure the server understands kerberos */
790 for (i
=0;OIDs
[i
];i
++) {
791 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
793 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
794 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
795 got_kerberos_mechanism
= True
;
798 talloc_free(OIDs
[i
]);
800 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal
));
803 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
804 got_kerberos_mechanism
)
806 struct ads_service_principal p
;
808 status
= ads_generate_service_principal(ads
, given_principal
, &p
);
809 TALLOC_FREE(given_principal
);
810 if (!ADS_ERR_OK(status
)) {
814 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
815 if (ADS_ERR_OK(status
)) {
816 ads_free_service_principal(&p
);
820 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
821 "calling kinit\n", ads_errstr(status
)));
823 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
825 if (ADS_ERR_OK(status
)) {
826 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
827 if (!ADS_ERR_OK(status
)) {
828 DEBUG(0,("kinit succeeded but "
829 "ads_sasl_spnego_krb5_bind failed: %s\n",
830 ads_errstr(status
)));
834 ads_free_service_principal(&p
);
836 /* only fallback to NTLMSSP if allowed */
837 if (ADS_ERR_OK(status
) ||
838 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
844 TALLOC_FREE(given_principal
);
847 /* lets do NTLMSSP ... this has the big advantage that we don't need
848 to sync clocks, and we don't rely on special versions of the krb5
849 library for HMAC_MD4 encryption */
850 return ads_sasl_spnego_ntlmssp_bind(ads
);
857 #define MAX_GSS_PASSES 3
859 /* this performs a SASL/gssapi bind
860 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
861 is very dependent on correctly configured DNS whereas
862 this routine is much less fragile
863 see RFC2078 and RFC2222 for details
865 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
868 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
869 gss_OID mech_type
= GSS_C_NULL_OID
;
870 gss_buffer_desc output_token
, input_token
;
871 uint32 req_flags
, ret_flags
;
874 struct berval
*scred
= NULL
;
878 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
879 uint8 wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
882 input_token
.value
= NULL
;
883 input_token
.length
= 0;
886 * Note: here we always ask the gssapi for sign and seal
887 * as this is negotiated later after the mutal
890 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
892 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
893 gss_rc
= gss_init_sec_context(&minor_status
,
910 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
911 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
915 cred
.bv_val
= (char *)output_token
.value
;
916 cred
.bv_len
= output_token
.length
;
918 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
920 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
921 status
= ADS_ERROR(rc
);
925 if (output_token
.value
) {
926 gss_release_buffer(&minor_status
, &output_token
);
930 input_token
.value
= scred
->bv_val
;
931 input_token
.length
= scred
->bv_len
;
933 input_token
.value
= NULL
;
934 input_token
.length
= 0;
937 if (gss_rc
== 0) break;
940 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
947 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
951 p
= (uint8
*)output_token
.value
;
954 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
958 wrap_type
= CVAL(p
,0);
960 max_msg_size
= RIVAL(p
,0);
963 gss_release_buffer(&minor_status
, &output_token
);
965 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
967 * the server doesn't supports the wrap
970 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
971 ads
->ldap
.wrap_type
, wrap_type
));
972 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
973 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
977 /* 0x58 is the minimum windows accepts */
978 if (max_msg_size
< 0x58) {
982 output_token
.length
= 4;
983 output_token
.value
= SMB_MALLOC(output_token
.length
);
984 p
= (uint8
*)output_token
.value
;
986 RSIVAL(p
,0,max_msg_size
);
987 SCVAL(p
,0,ads
->ldap
.wrap_type
);
990 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
991 * but using ads->config.bind_path is the wrong! It should be
992 * the DN of the user object!
994 * w2k3 gives an error when we send an incorrect DN, but sending nothing
995 * is ok and matches the information flow used in GSS-SPNEGO.
998 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
999 &output_token
, &conf_state
,
1002 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1006 free(output_token
.value
);
1008 cred
.bv_val
= (char *)input_token
.value
;
1009 cred
.bv_len
= input_token
.length
;
1011 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
1013 gss_release_buffer(&minor_status
, &input_token
);
1014 status
= ADS_ERROR(rc
);
1015 if (!ADS_ERR_OK(status
)) {
1019 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
1020 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
1021 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
1023 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
1025 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1029 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
1030 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1031 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
1032 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
1033 if (!ADS_ERR_OK(status
)) {
1034 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1035 ads_errstr(status
)));
1038 /* make sure we don't free context_handle */
1039 context_handle
= GSS_C_NO_CONTEXT
;
1044 if (context_handle
!= GSS_C_NO_CONTEXT
)
1045 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1052 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1055 struct ads_service_principal p
;
1057 status
= ads_generate_service_principal(ads
, NULL
, &p
);
1058 if (!ADS_ERR_OK(status
)) {
1062 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1063 if (ADS_ERR_OK(status
)) {
1064 ads_free_service_principal(&p
);
1068 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1069 "calling kinit\n", ads_errstr(status
)));
1071 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1073 if (ADS_ERR_OK(status
)) {
1074 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1077 ads_free_service_principal(&p
);
1082 #endif /* HAVE_GSSAPI */
1084 /* mapping between SASL mechanisms and functions */
1087 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1088 } sasl_mechanisms
[] = {
1089 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1091 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1096 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1098 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1104 /* get a list of supported SASL mechanisms */
1105 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1106 if (!ADS_ERR_OK(status
)) return status
;
1108 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1110 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1111 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1112 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1113 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1115 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1118 /* try our supported mechanisms in order */
1119 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1120 /* see if the server supports it */
1121 for (j
=0;values
&& values
[j
];j
++) {
1122 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1123 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1125 status
= sasl_mechanisms
[i
].fn(ads
);
1126 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
1127 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
1128 ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
1130 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1131 "retrying with signing enabled\n"));
1132 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1135 ldap_value_free(values
);
1142 ldap_value_free(values
);
1144 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1147 #endif /* HAVE_LDAP */