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"
25 static ADS_STATUS
ads_sasl_ntlmssp_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
27 struct ntlmssp_state
*ntlmssp_state
=
28 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
32 uint8
*dptr
= ads
->ldap
.out
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
34 /* copy the data to the right location */
35 memcpy(dptr
, buf
, len
);
37 /* create the signature and may encrypt the data */
38 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
39 nt_status
= ntlmssp_seal_packet(ntlmssp_state
,
44 nt_status
= ntlmssp_sign_packet(ntlmssp_state
,
49 status
= ADS_ERROR_NT(nt_status
);
50 if (!ADS_ERR_OK(status
)) return status
;
52 /* copy the signature to the right location */
53 memcpy(ads
->ldap
.out
.buf
+ 4,
54 sig
.data
, NTLMSSP_SIG_SIZE
);
58 /* set how many bytes must be written to the underlying socket */
59 ads
->ldap
.out
.left
= 4 + NTLMSSP_SIG_SIZE
+ len
;
64 static ADS_STATUS
ads_sasl_ntlmssp_unwrap(ADS_STRUCT
*ads
)
66 struct ntlmssp_state
*ntlmssp_state
=
67 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
71 uint8
*dptr
= ads
->ldap
.in
.buf
+ (4 + NTLMSSP_SIG_SIZE
);
72 uint32 dlen
= ads
->ldap
.in
.ofs
- (4 + NTLMSSP_SIG_SIZE
);
74 /* wrap the signature into a DATA_BLOB */
75 sig
= data_blob_const(ads
->ldap
.in
.buf
+ 4, NTLMSSP_SIG_SIZE
);
77 /* verify the signature and maybe decrypt the data */
78 if (ntlmssp_state
->neg_flags
& NTLMSSP_NEGOTIATE_SEAL
) {
79 nt_status
= ntlmssp_unseal_packet(ntlmssp_state
,
84 nt_status
= ntlmssp_check_packet(ntlmssp_state
,
89 status
= ADS_ERROR_NT(nt_status
);
90 if (!ADS_ERR_OK(status
)) return status
;
92 /* set the amount of bytes for the upper layer and set the ofs to the data */
93 ads
->ldap
.in
.left
= dlen
;
94 ads
->ldap
.in
.ofs
= 4 + NTLMSSP_SIG_SIZE
;
99 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT
*ads
)
101 struct ntlmssp_state
*ntlmssp_state
=
102 (struct ntlmssp_state
*)ads
->ldap
.wrap_private_data
;
104 ntlmssp_end(&ntlmssp_state
);
106 ads
->ldap
.wrap_ops
= NULL
;
107 ads
->ldap
.wrap_private_data
= NULL
;
110 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops
= {
112 .wrap
= ads_sasl_ntlmssp_wrap
,
113 .unwrap
= ads_sasl_ntlmssp_unwrap
,
114 .disconnect
= ads_sasl_ntlmssp_disconnect
118 perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
119 we fit on one socket??)
121 static ADS_STATUS
ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT
*ads
)
123 DATA_BLOB msg1
= data_blob_null
;
124 DATA_BLOB blob
= data_blob_null
;
125 DATA_BLOB blob_in
= data_blob_null
;
126 DATA_BLOB blob_out
= data_blob_null
;
127 struct berval cred
, *scred
= NULL
;
134 struct ntlmssp_state
*ntlmssp_state
;
136 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_client_start(&ntlmssp_state
))) {
137 return ADS_ERROR_NT(nt_status
);
139 ntlmssp_state
->neg_flags
&= ~NTLMSSP_NEGOTIATE_SIGN
;
141 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_username(ntlmssp_state
, ads
->auth
.user_name
))) {
142 return ADS_ERROR_NT(nt_status
);
144 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_domain(ntlmssp_state
, ads
->auth
.realm
))) {
145 return ADS_ERROR_NT(nt_status
);
147 if (!NT_STATUS_IS_OK(nt_status
= ntlmssp_set_password(ntlmssp_state
, ads
->auth
.password
))) {
148 return ADS_ERROR_NT(nt_status
);
151 switch (ads
->ldap
.wrap_type
) {
152 case ADS_SASLWRAP_TYPE_SEAL
:
153 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
155 case ADS_SASLWRAP_TYPE_SIGN
:
156 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
157 features
= NTLMSSP_FEATURE_SIGN
;
160 * windows servers are broken with sign only,
161 * so we need to use seal here too
163 features
= NTLMSSP_FEATURE_SIGN
| NTLMSSP_FEATURE_SEAL
;
164 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
167 case ADS_SASLWRAP_TYPE_PLAIN
:
171 ntlmssp_want_feature(ntlmssp_state
, features
);
173 blob_in
= data_blob_null
;
176 nt_status
= ntlmssp_update(ntlmssp_state
,
178 data_blob_free(&blob_in
);
179 if ((NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
180 || NT_STATUS_IS_OK(nt_status
))
181 && blob_out
.length
) {
183 /* and wrap it in a SPNEGO wrapper */
184 msg1
= gen_negTokenInit(OID_NTLMSSP
, blob_out
);
186 /* wrap it in SPNEGO */
187 msg1
= spnego_gen_auth(blob_out
);
190 data_blob_free(&blob_out
);
192 cred
.bv_val
= (char *)msg1
.data
;
193 cred
.bv_len
= msg1
.length
;
195 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
196 data_blob_free(&msg1
);
197 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
202 ntlmssp_end(&ntlmssp_state
);
203 return ADS_ERROR(rc
);
206 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
209 blob
= data_blob_null
;
214 ntlmssp_end(&ntlmssp_state
);
215 data_blob_free(&blob_out
);
216 return ADS_ERROR_NT(nt_status
);
220 (rc
== LDAP_SASL_BIND_IN_PROGRESS
)) {
221 DATA_BLOB tmp_blob
= data_blob_null
;
222 /* the server might give us back two challenges */
223 if (!spnego_parse_challenge(blob
, &blob_in
,
226 ntlmssp_end(&ntlmssp_state
);
227 data_blob_free(&blob
);
228 DEBUG(3,("Failed to parse challenges\n"));
229 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
231 data_blob_free(&tmp_blob
);
232 } else if (rc
== LDAP_SASL_BIND_IN_PROGRESS
) {
233 if (!spnego_parse_auth_response(blob
, nt_status
, OID_NTLMSSP
,
236 ntlmssp_end(&ntlmssp_state
);
237 data_blob_free(&blob
);
238 DEBUG(3,("Failed to parse auth response\n"));
239 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER
);
242 data_blob_free(&blob
);
243 data_blob_free(&blob_out
);
245 } while (rc
== LDAP_SASL_BIND_IN_PROGRESS
&& !NT_STATUS_IS_OK(nt_status
));
247 /* we have a reference conter on ntlmssp_state, if we are signing
248 then the state will be kept by the signing engine */
250 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
251 ads
->ldap
.out
.max_unwrapped
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
- NTLMSSP_SIG_SIZE
;
252 ads
->ldap
.out
.sig_size
= NTLMSSP_SIG_SIZE
;
253 ads
->ldap
.in
.min_wrapped
= ads
->ldap
.out
.sig_size
;
254 ads
->ldap
.in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
255 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_ntlmssp_ops
, ntlmssp_state
);
256 if (!ADS_ERR_OK(status
)) {
257 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
258 ads_errstr(status
)));
259 ntlmssp_end(&ntlmssp_state
);
263 ntlmssp_end(&ntlmssp_state
);
266 return ADS_ERROR(rc
);
270 static ADS_STATUS
ads_sasl_gssapi_wrap(ADS_STRUCT
*ads
, uint8
*buf
, uint32 len
)
272 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
276 gss_buffer_desc unwrapped
, wrapped
;
277 int conf_req_flag
, conf_state
;
279 unwrapped
.value
= buf
;
280 unwrapped
.length
= len
;
282 /* for now request sign and seal */
283 conf_req_flag
= (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
);
285 gss_rc
= gss_wrap(&minor_status
, context_handle
,
286 conf_req_flag
, GSS_C_QOP_DEFAULT
,
287 &unwrapped
, &conf_state
,
289 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
290 if (!ADS_ERR_OK(status
)) return status
;
292 if (conf_req_flag
&& conf_state
== 0) {
293 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
296 if ((ads
->ldap
.out
.size
- 4) < wrapped
.length
) {
297 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
300 /* copy the wrapped blob to the right location */
301 memcpy(ads
->ldap
.out
.buf
+ 4, wrapped
.value
, wrapped
.length
);
303 /* set how many bytes must be written to the underlying socket */
304 ads
->ldap
.out
.left
= 4 + wrapped
.length
;
306 gss_release_buffer(&minor_status
, &wrapped
);
311 static ADS_STATUS
ads_sasl_gssapi_unwrap(ADS_STRUCT
*ads
)
313 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
317 gss_buffer_desc unwrapped
, wrapped
;
320 wrapped
.value
= ads
->ldap
.in
.buf
+ 4;
321 wrapped
.length
= ads
->ldap
.in
.ofs
- 4;
323 gss_rc
= gss_unwrap(&minor_status
, context_handle
,
324 &wrapped
, &unwrapped
,
325 &conf_state
, GSS_C_QOP_DEFAULT
);
326 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
327 if (!ADS_ERR_OK(status
)) return status
;
329 if (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
&& conf_state
== 0) {
330 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
333 if (wrapped
.length
< unwrapped
.length
) {
334 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
337 /* copy the wrapped blob to the right location */
338 memcpy(ads
->ldap
.in
.buf
+ 4, unwrapped
.value
, unwrapped
.length
);
340 /* set how many bytes must be written to the underlying socket */
341 ads
->ldap
.in
.left
= unwrapped
.length
;
342 ads
->ldap
.in
.ofs
= 4;
344 gss_release_buffer(&minor_status
, &unwrapped
);
349 static void ads_sasl_gssapi_disconnect(ADS_STRUCT
*ads
)
351 gss_ctx_id_t context_handle
= (gss_ctx_id_t
)ads
->ldap
.wrap_private_data
;
354 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
356 ads
->ldap
.wrap_ops
= NULL
;
357 ads
->ldap
.wrap_private_data
= NULL
;
360 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops
= {
362 .wrap
= ads_sasl_gssapi_wrap
,
363 .unwrap
= ads_sasl_gssapi_unwrap
,
364 .disconnect
= ads_sasl_gssapi_disconnect
368 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
370 static ADS_STATUS
ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
376 gss_OID_desc krb5_mech_type
=
377 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
378 gss_OID mech_type
= &krb5_mech_type
;
379 gss_OID actual_mech_type
= GSS_C_NULL_OID
;
380 const char *spnego_mechs
[] = {OID_KERBEROS5_OLD
, OID_KERBEROS5
, OID_NTLMSSP
, NULL
};
381 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
382 gss_buffer_desc input_token
, output_token
;
383 uint32 req_flags
, ret_flags
;
384 uint32 req_tmp
, ret_tmp
;
387 struct berval cred
, *scred
= NULL
;
389 input_token
.value
= NULL
;
390 input_token
.length
= 0;
392 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
;
393 switch (ads
->ldap
.wrap_type
) {
394 case ADS_SASLWRAP_TYPE_SEAL
:
395 req_flags
|= GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
397 case ADS_SASLWRAP_TYPE_SIGN
:
398 req_flags
|= GSS_C_INTEG_FLAG
;
400 case ADS_SASLWRAP_TYPE_PLAIN
:
404 /* Note: here we explicit ask for the krb5 mech_type */
405 gss_rc
= gss_init_sec_context(&minor_status
,
418 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
419 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
424 * As some gssapi krb5 mech implementations
425 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
426 * to req_flags internaly, it's not possible to
427 * use plain or signing only connection via
428 * the gssapi interface.
430 * Because of this we need to check it the ret_flags
431 * has more flags as req_flags and correct the value
432 * of ads->ldap.wrap_type.
434 * I ads->auth.flags has ADS_AUTH_SASL_FORCE
435 * we need to give an error.
437 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
438 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
440 if (req_tmp
== ret_tmp
) {
441 /* everythings fine... */
443 } else if (req_flags
& GSS_C_CONF_FLAG
) {
445 * here we wanted sealing but didn't got it
446 * from the gssapi library
448 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
451 } else if ((req_flags
& GSS_C_INTEG_FLAG
) &&
452 !(ret_flags
& GSS_C_INTEG_FLAG
)) {
454 * here we wanted siging but didn't got it
455 * from the gssapi library
457 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
460 } else if (ret_flags
& GSS_C_CONF_FLAG
) {
462 * here we didn't want sealing
463 * but the gssapi library forces it
464 * so correct the needed wrap_type if
465 * the caller didn't forced siging only
467 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
468 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
472 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
473 req_flags
= ret_flags
;
475 } else if (ret_flags
& GSS_C_INTEG_FLAG
) {
477 * here we didn't want signing
478 * but the gssapi library forces it
479 * so correct the needed wrap_type if
480 * the caller didn't forced plain
482 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
483 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
487 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
488 req_flags
= ret_flags
;
491 * This could (should?) not happen
493 status
= ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
498 /* and wrap that in a shiny SPNEGO wrapper */
499 unwrapped
= data_blob_const(output_token
.value
, output_token
.length
);
500 wrapped
= gen_negTokenTarg(spnego_mechs
, unwrapped
);
501 gss_release_buffer(&minor_status
, &output_token
);
502 if (unwrapped
.length
> wrapped
.length
) {
503 status
= ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
507 cred
.bv_val
= (char *)wrapped
.data
;
508 cred
.bv_len
= wrapped
.length
;
510 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
,
512 data_blob_free(&wrapped
);
513 if (rc
!= LDAP_SUCCESS
) {
514 status
= ADS_ERROR(rc
);
519 wrapped
= data_blob_const(scred
->bv_val
, scred
->bv_len
);
521 wrapped
= data_blob_null
;
524 ok
= spnego_parse_auth_response(wrapped
, NT_STATUS_OK
,
527 if (scred
) ber_bvfree(scred
);
529 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
533 input_token
.value
= unwrapped
.data
;
534 input_token
.length
= unwrapped
.length
;
537 * As we asked for mutal authentication
538 * we need to pass the servers response
541 gss_rc
= gss_init_sec_context(&minor_status
,
554 data_blob_free(&unwrapped
);
556 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
560 gss_release_buffer(&minor_status
, &output_token
);
563 * If we the sign and seal options
564 * doesn't match after getting the response
565 * from the server, we don't want to use the connection
567 req_tmp
= req_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
568 ret_tmp
= ret_flags
& (GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
);
570 if (req_tmp
!= ret_tmp
) {
571 /* everythings fine... */
572 status
= ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
576 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
577 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
579 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
580 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
582 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
584 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
588 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
589 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
590 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
591 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
592 if (!ADS_ERR_OK(status
)) {
593 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
594 ads_errstr(status
)));
597 /* make sure we don't free context_handle */
598 context_handle
= GSS_C_NO_CONTEXT
;
601 status
= ADS_SUCCESS
;
604 if (context_handle
!= GSS_C_NO_CONTEXT
)
605 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
609 #endif /* HAVE_GSSAPI */
612 struct ads_service_principal
{
619 static void ads_free_service_principal(struct ads_service_principal
*p
)
621 SAFE_FREE(p
->string
);
626 gss_release_name(&minor_status
, &p
->name
);
632 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
633 const char *given_principal
,
634 struct ads_service_principal
*p
)
638 gss_buffer_desc input_name
;
639 /* GSS_KRB5_NT_PRINCIPAL_NAME */
640 gss_OID_desc nt_principal
=
641 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
648 /* I've seen a child Windows 2000 domain not send
649 the principal name back in the first round of
650 the SASL bind reply. So we guess based on server
651 name and realm. --jerry */
652 /* Also try best guess when we get the w2k8 ignore principal
653 back, or when we are configured to ignore it - gd,
656 if (!lp_client_use_spnego_principal() ||
658 strequal(given_principal
, ADS_IGNORE_PRINCIPAL
)) {
660 status
= ads_guess_service_principal(ads
, &p
->string
);
661 if (!ADS_ERR_OK(status
)) {
665 p
->string
= SMB_STRDUP(given_principal
);
667 return ADS_ERROR(LDAP_NO_MEMORY
);
672 input_name
.value
= p
->string
;
673 input_name
.length
= strlen(p
->string
);
675 gss_rc
= gss_import_name(&minor_status
, &input_name
, &nt_principal
, &p
->name
);
677 ads_free_service_principal(p
);
678 return ADS_ERROR_GSS(gss_rc
, minor_status
);
686 perform a LDAP/SASL/SPNEGO/KRB5 bind
688 static ADS_STATUS
ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT
*ads
, const char *principal
)
690 DATA_BLOB blob
= data_blob_null
;
691 struct berval cred
, *scred
= NULL
;
692 DATA_BLOB session_key
= data_blob_null
;
695 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
696 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
699 rc
= spnego_gen_negTokenTarg(principal
, ads
->auth
.time_offset
, &blob
, &session_key
, 0,
700 &ads
->auth
.tgs_expire
);
703 return ADS_ERROR_KRB5(rc
);
706 /* now send the auth packet and we should be done */
707 cred
.bv_val
= (char *)blob
.data
;
708 cred
.bv_len
= blob
.length
;
710 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", &cred
, NULL
, NULL
, &scred
);
712 data_blob_free(&blob
);
713 data_blob_free(&session_key
);
717 return ADS_ERROR(rc
);
720 static ADS_STATUS
ads_sasl_spnego_krb5_bind(ADS_STRUCT
*ads
,
721 struct ads_service_principal
*p
)
725 * we only use the gsskrb5 based implementation
726 * when sasl sign or seal is requested.
728 * This has the following reasons:
729 * - it's likely that the gssapi krb5 mech implementation
730 * doesn't support to negotiate plain connections
731 * - the ads_sasl_spnego_rawkrb5_bind is more robust
732 * against clock skew errors
734 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
735 return ads_sasl_spnego_gsskrb5_bind(ads
, p
->name
);
738 return ads_sasl_spnego_rawkrb5_bind(ads
, p
->string
);
740 #endif /* HAVE_KRB5 */
743 this performs a SASL/SPNEGO bind
745 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
)
747 struct berval
*scred
=NULL
;
751 char *given_principal
= NULL
;
752 char *OIDs
[ASN1_MAX_OIDS
];
754 bool got_kerberos_mechanism
= False
;
757 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSS-SPNEGO", NULL
, NULL
, NULL
, &scred
);
759 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
760 status
= ADS_ERROR(rc
);
764 blob
= data_blob(scred
->bv_val
, scred
->bv_len
);
769 file_save("sasl_spnego.dat", blob
.data
, blob
.length
);
772 /* the server sent us the first part of the SPNEGO exchange in the negprot
774 if (!spnego_parse_negTokenInit(blob
, OIDs
, &given_principal
) ||
776 data_blob_free(&blob
);
777 status
= ADS_ERROR(LDAP_OPERATIONS_ERROR
);
780 data_blob_free(&blob
);
782 /* make sure the server understands kerberos */
783 for (i
=0;OIDs
[i
];i
++) {
784 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs
[i
]));
786 if (strcmp(OIDs
[i
], OID_KERBEROS5_OLD
) == 0 ||
787 strcmp(OIDs
[i
], OID_KERBEROS5
) == 0) {
788 got_kerberos_mechanism
= True
;
791 talloc_free(OIDs
[i
]);
793 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal
));
796 if (!(ads
->auth
.flags
& ADS_AUTH_DISABLE_KERBEROS
) &&
797 got_kerberos_mechanism
)
799 struct ads_service_principal p
;
801 status
= ads_generate_service_principal(ads
, given_principal
, &p
);
802 TALLOC_FREE(given_principal
);
803 if (!ADS_ERR_OK(status
)) {
807 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
808 if (ADS_ERR_OK(status
)) {
809 ads_free_service_principal(&p
);
813 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
814 "calling kinit\n", ads_errstr(status
)));
816 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
818 if (ADS_ERR_OK(status
)) {
819 status
= ads_sasl_spnego_krb5_bind(ads
, &p
);
820 if (!ADS_ERR_OK(status
)) {
821 DEBUG(0,("kinit succeeded but "
822 "ads_sasl_spnego_krb5_bind failed: %s\n",
823 ads_errstr(status
)));
827 ads_free_service_principal(&p
);
829 /* only fallback to NTLMSSP if allowed */
830 if (ADS_ERR_OK(status
) ||
831 !(ads
->auth
.flags
& ADS_AUTH_ALLOW_NTLMSSP
)) {
837 TALLOC_FREE(given_principal
);
840 /* lets do NTLMSSP ... this has the big advantage that we don't need
841 to sync clocks, and we don't rely on special versions of the krb5
842 library for HMAC_MD4 encryption */
843 return ads_sasl_spnego_ntlmssp_bind(ads
);
850 #define MAX_GSS_PASSES 3
852 /* this performs a SASL/gssapi bind
853 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
854 is very dependent on correctly configured DNS whereas
855 this routine is much less fragile
856 see RFC2078 and RFC2222 for details
858 static ADS_STATUS
ads_sasl_gssapi_do_bind(ADS_STRUCT
*ads
, const gss_name_t serv_name
)
861 gss_ctx_id_t context_handle
= GSS_C_NO_CONTEXT
;
862 gss_OID mech_type
= GSS_C_NULL_OID
;
863 gss_buffer_desc output_token
, input_token
;
864 uint32 req_flags
, ret_flags
;
867 struct berval
*scred
= NULL
;
871 uint32 max_msg_size
= ADS_SASL_WRAPPING_OUT_MAX_WRAPPED
;
872 uint8 wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
875 input_token
.value
= NULL
;
876 input_token
.length
= 0;
879 * Note: here we always ask the gssapi for sign and seal
880 * as this is negotiated later after the mutal
883 req_flags
= GSS_C_MUTUAL_FLAG
| GSS_C_REPLAY_FLAG
| GSS_C_INTEG_FLAG
| GSS_C_CONF_FLAG
;
885 for (i
=0; i
< MAX_GSS_PASSES
; i
++) {
886 gss_rc
= gss_init_sec_context(&minor_status
,
903 if (gss_rc
&& gss_rc
!= GSS_S_CONTINUE_NEEDED
) {
904 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
908 cred
.bv_val
= (char *)output_token
.value
;
909 cred
.bv_len
= output_token
.length
;
911 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
913 if (rc
!= LDAP_SASL_BIND_IN_PROGRESS
) {
914 status
= ADS_ERROR(rc
);
918 if (output_token
.value
) {
919 gss_release_buffer(&minor_status
, &output_token
);
923 input_token
.value
= scred
->bv_val
;
924 input_token
.length
= scred
->bv_len
;
926 input_token
.value
= NULL
;
927 input_token
.length
= 0;
930 if (gss_rc
== 0) break;
933 gss_rc
= gss_unwrap(&minor_status
,context_handle
,&input_token
,&output_token
,
940 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
944 p
= (uint8
*)output_token
.value
;
947 file_save("sasl_gssapi.dat", output_token
.value
, output_token
.length
);
951 wrap_type
= CVAL(p
,0);
953 max_msg_size
= RIVAL(p
,0);
956 gss_release_buffer(&minor_status
, &output_token
);
958 if (!(wrap_type
& ads
->ldap
.wrap_type
)) {
960 * the server doesn't supports the wrap
963 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
964 ads
->ldap
.wrap_type
, wrap_type
));
965 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
966 status
= ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
970 /* 0x58 is the minimum windows accepts */
971 if (max_msg_size
< 0x58) {
975 output_token
.length
= 4;
976 output_token
.value
= SMB_MALLOC(output_token
.length
);
977 p
= (uint8
*)output_token
.value
;
979 RSIVAL(p
,0,max_msg_size
);
980 SCVAL(p
,0,ads
->ldap
.wrap_type
);
983 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
984 * but using ads->config.bind_path is the wrong! It should be
985 * the DN of the user object!
987 * w2k3 gives an error when we send an incorrect DN, but sending nothing
988 * is ok and matches the information flow used in GSS-SPNEGO.
991 gss_rc
= gss_wrap(&minor_status
, context_handle
,0,GSS_C_QOP_DEFAULT
,
992 &output_token
, &conf_state
,
995 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
999 free(output_token
.value
);
1001 cred
.bv_val
= (char *)input_token
.value
;
1002 cred
.bv_len
= input_token
.length
;
1004 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, "GSSAPI", &cred
, NULL
, NULL
,
1006 gss_release_buffer(&minor_status
, &input_token
);
1007 status
= ADS_ERROR(rc
);
1008 if (!ADS_ERR_OK(status
)) {
1012 if (ads
->ldap
.wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
1013 gss_rc
= gss_wrap_size_limit(&minor_status
, context_handle
,
1014 (ads
->ldap
.wrap_type
== ADS_SASLWRAP_TYPE_SEAL
),
1016 max_msg_size
, &ads
->ldap
.out
.max_unwrapped
);
1018 status
= ADS_ERROR_GSS(gss_rc
, minor_status
);
1022 ads
->ldap
.out
.sig_size
= max_msg_size
- ads
->ldap
.out
.max_unwrapped
;
1023 ads
->ldap
.in
.min_wrapped
= 0x2C; /* taken from a capture with LDAP unbind */
1024 ads
->ldap
.in
.max_wrapped
= max_msg_size
;
1025 status
= ads_setup_sasl_wrapping(ads
, &ads_sasl_gssapi_ops
, context_handle
);
1026 if (!ADS_ERR_OK(status
)) {
1027 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1028 ads_errstr(status
)));
1031 /* make sure we don't free context_handle */
1032 context_handle
= GSS_C_NO_CONTEXT
;
1037 if (context_handle
!= GSS_C_NO_CONTEXT
)
1038 gss_delete_sec_context(&minor_status
, &context_handle
, GSS_C_NO_BUFFER
);
1045 static ADS_STATUS
ads_sasl_gssapi_bind(ADS_STRUCT
*ads
)
1048 struct ads_service_principal p
;
1050 status
= ads_generate_service_principal(ads
, NULL
, &p
);
1051 if (!ADS_ERR_OK(status
)) {
1055 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1056 if (ADS_ERR_OK(status
)) {
1057 ads_free_service_principal(&p
);
1061 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1062 "calling kinit\n", ads_errstr(status
)));
1064 status
= ADS_ERROR_KRB5(ads_kinit_password(ads
));
1066 if (ADS_ERR_OK(status
)) {
1067 status
= ads_sasl_gssapi_do_bind(ads
, p
.name
);
1070 ads_free_service_principal(&p
);
1075 #endif /* HAVE_GSSAPI */
1077 /* mapping between SASL mechanisms and functions */
1080 ADS_STATUS (*fn
)(ADS_STRUCT
*);
1081 } sasl_mechanisms
[] = {
1082 {"GSS-SPNEGO", ads_sasl_spnego_bind
},
1084 {"GSSAPI", ads_sasl_gssapi_bind
}, /* doesn't work with .NET RC1. No idea why */
1089 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
)
1091 const char *attrs
[] = {"supportedSASLMechanisms", NULL
};
1097 /* get a list of supported SASL mechanisms */
1098 status
= ads_do_search(ads
, "", LDAP_SCOPE_BASE
, "(objectclass=*)", attrs
, &res
);
1099 if (!ADS_ERR_OK(status
)) return status
;
1101 values
= ldap_get_values(ads
->ldap
.ld
, res
, "supportedSASLMechanisms");
1103 if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
1104 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
1105 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
1106 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
1108 ads
->ldap
.wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
1111 /* try our supported mechanisms in order */
1112 for (i
=0;sasl_mechanisms
[i
].name
;i
++) {
1113 /* see if the server supports it */
1114 for (j
=0;values
&& values
[j
];j
++) {
1115 if (strcmp(values
[j
], sasl_mechanisms
[i
].name
) == 0) {
1116 DEBUG(4,("Found SASL mechanism %s\n", values
[j
]));
1117 status
= sasl_mechanisms
[i
].fn(ads
);
1118 ldap_value_free(values
);
1125 ldap_value_free(values
);
1127 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED
);
1130 #endif /* HAVE_LDAP */