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 "auth/credentials/credentials.h"
22 #include "auth/gensec/gensec.h"
23 #include "auth_generic.h"
26 #include "system/gssapi.h"
27 #include "lib/param/param.h"
28 #include "lib/util/asn1.h"
30 NTSTATUS
ads_simple_creds(TALLOC_CTX
*mem_ctx
,
31 const char *account_domain
,
32 const char *account_name
,
34 struct cli_credentials
**_creds
)
36 TALLOC_CTX
*frame
= talloc_stackframe();
37 struct cli_credentials
*creds
= NULL
;
38 struct loadparm_context
*lp_ctx
= NULL
;
41 lp_ctx
= loadparm_init_s3(frame
, loadparm_s3_helpers());
43 DBG_ERR("loadparm_init_s3 failed\n");
45 return NT_STATUS_INVALID_SERVER_STATE
;
48 creds
= cli_credentials_init(mem_ctx
);
51 return NT_STATUS_NO_MEMORY
;
53 talloc_steal(frame
, creds
);
55 ok
= cli_credentials_guess(creds
, lp_ctx
);
58 return NT_STATUS_INTERNAL_ERROR
;
61 if (account_domain
!= NULL
&& account_domain
[0] != '\0') {
62 ok
= cli_credentials_set_domain(creds
,
67 return NT_STATUS_NO_MEMORY
;
70 if (password
!= NULL
) {
71 ok
= cli_credentials_set_password(creds
,
76 return NT_STATUS_NO_MEMORY
;
80 cli_credentials_parse_string(creds
,
84 *_creds
= talloc_move(mem_ctx
, &creds
);
91 static ADS_STATUS
ads_sasl_gensec_wrap(struct ads_saslwrap
*wrap
,
92 uint8_t *buf
, uint32_t len
)
94 struct gensec_security
*gensec_security
=
95 talloc_get_type_abort(wrap
->wrap_private_data
,
96 struct gensec_security
);
98 DATA_BLOB unwrapped
, wrapped
;
99 TALLOC_CTX
*frame
= talloc_stackframe();
101 unwrapped
= data_blob_const(buf
, len
);
103 nt_status
= gensec_wrap(gensec_security
, frame
, &unwrapped
, &wrapped
);
104 if (!NT_STATUS_IS_OK(nt_status
)) {
106 return ADS_ERROR_NT(nt_status
);
109 if ((wrap
->out
.size
- 4) < wrapped
.length
) {
111 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
114 /* copy the wrapped blob to the right location */
115 memcpy(wrap
->out
.buf
+ 4, wrapped
.data
, wrapped
.length
);
117 /* set how many bytes must be written to the underlying socket */
118 wrap
->out
.left
= 4 + wrapped
.length
;
125 static ADS_STATUS
ads_sasl_gensec_unwrap(struct ads_saslwrap
*wrap
)
127 struct gensec_security
*gensec_security
=
128 talloc_get_type_abort(wrap
->wrap_private_data
,
129 struct gensec_security
);
131 DATA_BLOB unwrapped
, wrapped
;
132 TALLOC_CTX
*frame
= talloc_stackframe();
134 wrapped
= data_blob_const(wrap
->in
.buf
+ 4, wrap
->in
.ofs
- 4);
136 nt_status
= gensec_unwrap(gensec_security
, frame
, &wrapped
, &unwrapped
);
137 if (!NT_STATUS_IS_OK(nt_status
)) {
139 return ADS_ERROR_NT(nt_status
);
142 if (wrapped
.length
< unwrapped
.length
) {
144 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
147 /* copy the wrapped blob to the right location */
148 memcpy(wrap
->in
.buf
+ 4, unwrapped
.data
, unwrapped
.length
);
150 /* set how many bytes must be written to the underlying socket */
151 wrap
->in
.left
= unwrapped
.length
;
159 static void ads_sasl_gensec_disconnect(struct ads_saslwrap
*wrap
)
161 struct gensec_security
*gensec_security
=
162 talloc_get_type_abort(wrap
->wrap_private_data
,
163 struct gensec_security
);
165 TALLOC_FREE(gensec_security
);
167 wrap
->wrap_ops
= NULL
;
168 wrap
->wrap_private_data
= NULL
;
171 static const struct ads_saslwrap_ops ads_sasl_gensec_ops
= {
173 .wrap
= ads_sasl_gensec_wrap
,
174 .unwrap
= ads_sasl_gensec_unwrap
,
175 .disconnect
= ads_sasl_gensec_disconnect
179 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
180 we fit on one socket??)
182 static ADS_STATUS
ads_sasl_spnego_gensec_bind(ADS_STRUCT
*ads
,
183 struct cli_credentials
*creds
,
184 const char *target_service
,
185 const char *target_hostname
)
187 DATA_BLOB blob_in
= data_blob_null
;
188 DATA_BLOB blob_out
= data_blob_null
;
192 struct auth_generic_state
*auth_generic_state
;
193 const char *sasl
= "GSS-SPNEGO";
194 const char *sasl_list
[] = { sasl
, NULL
};
195 struct ads_saslwrap
*wrap
= &ads
->ldap_wrap_data
;
196 const DATA_BLOB
*tls_cb
= NULL
;
198 nt_status
= auth_generic_client_prepare(NULL
, &auth_generic_state
);
199 if (!NT_STATUS_IS_OK(nt_status
)) {
200 return ADS_ERROR_NT(nt_status
);
203 if (!NT_STATUS_IS_OK(nt_status
= auth_generic_set_creds(auth_generic_state
, creds
))) {
204 return ADS_ERROR_NT(nt_status
);
207 if (target_service
!= NULL
) {
208 nt_status
= gensec_set_target_service(
209 auth_generic_state
->gensec_security
,
211 if (!NT_STATUS_IS_OK(nt_status
)) {
212 return ADS_ERROR_NT(nt_status
);
216 if (target_hostname
!= NULL
) {
217 nt_status
= gensec_set_target_hostname(
218 auth_generic_state
->gensec_security
,
220 if (!NT_STATUS_IS_OK(nt_status
)) {
221 return ADS_ERROR_NT(nt_status
);
225 tls_cb
= ads_tls_channel_bindings(&ads
->ldap_tls_data
);
226 if (tls_cb
!= NULL
) {
227 uint32_t initiator_addrtype
= 0;
228 const DATA_BLOB
*initiator_address
= NULL
;
229 uint32_t acceptor_addrtype
= 0;
230 const DATA_BLOB
*acceptor_address
= NULL
;
231 const DATA_BLOB
*application_data
= tls_cb
;
233 nt_status
= gensec_set_channel_bindings(auth_generic_state
->gensec_security
,
239 if (!NT_STATUS_IS_OK(nt_status
)) {
240 DBG_WARNING("Failed to set GENSEC channel bindings: %s\n",
241 nt_errstr(nt_status
));
242 return ADS_ERROR_NT(nt_status
);
246 switch (wrap
->wrap_type
) {
247 case ADS_SASLWRAP_TYPE_SEAL
:
248 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
249 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SEAL
);
251 case ADS_SASLWRAP_TYPE_SIGN
:
252 if (ads
->auth
.flags
& ADS_AUTH_SASL_FORCE
) {
253 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
256 * windows servers are broken with sign only,
257 * so we let the NTLMSSP backend to seal here,
258 * via GENSEC_FEATURE_LDAP_STYLE.
260 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_SIGN
);
261 gensec_want_feature(auth_generic_state
->gensec_security
, GENSEC_FEATURE_LDAP_STYLE
);
264 case ADS_SASLWRAP_TYPE_PLAIN
:
268 nt_status
= auth_generic_client_start_by_sasl(auth_generic_state
,
270 if (!NT_STATUS_IS_OK(nt_status
)) {
271 return ADS_ERROR_NT(nt_status
);
274 rc
= LDAP_SASL_BIND_IN_PROGRESS
;
275 blob_in
= data_blob_null
;
276 blob_out
= data_blob_null
;
279 struct berval cred
, *scred
= NULL
;
281 nt_status
= gensec_update(auth_generic_state
->gensec_security
,
282 talloc_tos(), blob_in
, &blob_out
);
283 data_blob_free(&blob_in
);
284 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)
285 && !NT_STATUS_IS_OK(nt_status
))
287 TALLOC_FREE(auth_generic_state
);
288 data_blob_free(&blob_out
);
289 return ADS_ERROR_NT(nt_status
);
292 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_out
.length
== 0) {
296 cred
.bv_val
= (char *)blob_out
.data
;
297 cred
.bv_len
= blob_out
.length
;
299 rc
= ldap_sasl_bind_s(ads
->ldap
.ld
, NULL
, sasl
, &cred
, NULL
, NULL
, &scred
);
300 data_blob_free(&blob_out
);
301 if ((rc
!= LDAP_SASL_BIND_IN_PROGRESS
) && (rc
!= 0)) {
306 TALLOC_FREE(auth_generic_state
);
307 return ADS_ERROR(rc
);
310 blob_in
= data_blob_talloc(talloc_tos(),
313 if (blob_in
.length
!= scred
->bv_len
) {
315 TALLOC_FREE(auth_generic_state
);
316 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
320 blob_in
= data_blob_null
;
322 if (NT_STATUS_IS_OK(nt_status
) && rc
== 0 && blob_in
.length
== 0) {
327 data_blob_free(&blob_in
);
328 data_blob_free(&blob_out
);
330 if (wrap
->wrap_type
>= ADS_SASLWRAP_TYPE_SEAL
) {
333 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
334 GENSEC_FEATURE_SEAL
);
336 DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
337 TALLOC_FREE(auth_generic_state
);
338 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
341 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
342 GENSEC_FEATURE_SIGN
);
344 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
345 TALLOC_FREE(auth_generic_state
);
346 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
349 } else if (wrap
->wrap_type
>= ADS_SASLWRAP_TYPE_SIGN
) {
352 ok
= gensec_have_feature(auth_generic_state
->gensec_security
,
353 GENSEC_FEATURE_SIGN
);
355 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
356 TALLOC_FREE(auth_generic_state
);
357 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE
);
361 ads
->auth
.expire_time
= gensec_expire_time(auth_generic_state
->gensec_security
);
363 if (wrap
->wrap_type
> ADS_SASLWRAP_TYPE_PLAIN
) {
365 gensec_max_wrapped_size(auth_generic_state
->gensec_security
);
366 wrap
->out
.max_unwrapped
=
367 gensec_max_input_size(auth_generic_state
->gensec_security
);
369 wrap
->out
.sig_size
= max_wrapped
- wrap
->out
.max_unwrapped
;
371 * Note that we have to truncate this to 0x2C
372 * (taken from a capture with LDAP unbind), as the
373 * signature size is not constant for Kerberos with
376 wrap
->in
.min_wrapped
= MIN(wrap
->out
.sig_size
, 0x2C);
377 wrap
->in
.max_wrapped
= ADS_SASL_WRAPPING_IN_MAX_WRAPPED
;
378 status
= ads_setup_sasl_wrapping(wrap
, ads
->ldap
.ld
,
379 &ads_sasl_gensec_ops
,
380 auth_generic_state
->gensec_security
);
381 if (!ADS_ERR_OK(status
)) {
382 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
383 ads_errstr(status
)));
384 TALLOC_FREE(auth_generic_state
);
387 /* Only keep the gensec_security element around long-term */
388 talloc_steal(NULL
, auth_generic_state
->gensec_security
);
390 TALLOC_FREE(auth_generic_state
);
392 return ADS_ERROR(rc
);
396 struct ads_service_principal
{
402 static void ads_free_service_principal(struct ads_service_principal
*p
)
404 SAFE_FREE(p
->service
);
405 SAFE_FREE(p
->hostname
);
406 SAFE_FREE(p
->string
);
410 static ADS_STATUS
ads_guess_target(ADS_STRUCT
*ads
,
415 ADS_STATUS status
= ADS_ERROR(LDAP_NO_MEMORY
);
422 frame
= talloc_stackframe();
424 return ADS_ERROR(LDAP_NO_MEMORY
);
427 if (ads
->server
.realm
&& ads
->server
.ldap_server
) {
428 server
= strlower_talloc(frame
, ads
->server
.ldap_server
);
429 if (server
== NULL
) {
433 realm
= strupper_talloc(frame
, ads
->server
.realm
);
439 * If we got a name which is bigger than a NetBIOS name,
440 * but isn't a FQDN, create one.
442 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
445 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
446 if (dnsdomain
== NULL
) {
450 server
= talloc_asprintf(frame
,
453 if (server
== NULL
) {
457 } else if (ads
->config
.realm
&& ads
->config
.ldap_server_name
) {
458 server
= strlower_talloc(frame
, ads
->config
.ldap_server_name
);
459 if (server
== NULL
) {
463 realm
= strupper_talloc(frame
, ads
->config
.realm
);
469 * If we got a name which is bigger than a NetBIOS name,
470 * but isn't a FQDN, create one.
472 if (strlen(server
) > 15 && strstr(server
, ".") == NULL
) {
475 dnsdomain
= strlower_talloc(frame
, ads
->server
.realm
);
476 if (dnsdomain
== NULL
) {
480 server
= talloc_asprintf(frame
,
483 if (server
== NULL
) {
489 if (server
== NULL
|| realm
== NULL
) {
493 *service
= SMB_STRDUP("ldap");
494 if (*service
== NULL
) {
495 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
498 *hostname
= SMB_STRDUP(server
);
499 if (*hostname
== NULL
) {
501 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
504 rc
= asprintf(&princ
, "ldap/%s@%s", server
, realm
);
505 if (rc
== -1 || princ
== NULL
) {
507 SAFE_FREE(*hostname
);
508 status
= ADS_ERROR(LDAP_PARAM_ERROR
);
514 status
= ADS_SUCCESS
;
520 static ADS_STATUS
ads_generate_service_principal(ADS_STRUCT
*ads
,
521 struct ads_service_principal
*p
)
527 status
= ads_guess_target(ads
,
531 if (!ADS_ERR_OK(status
)) {
538 #endif /* HAVE_KRB5 */
541 this performs a SASL/SPNEGO bind
543 static ADS_STATUS
ads_sasl_spnego_bind(ADS_STRUCT
*ads
,
544 struct cli_credentials
*creds
)
546 TALLOC_CTX
*frame
= talloc_stackframe();
547 struct ads_service_principal p
= {0};
549 const char *debug_username
= NULL
;
551 status
= ads_generate_service_principal(ads
, &p
);
552 if (!ADS_ERR_OK(status
)) {
556 debug_username
= cli_credentials_get_unparsed_name(creds
, frame
);
557 if (debug_username
== NULL
) {
558 status
= ADS_ERROR_SYSTEM(errno
);
562 status
= ads_sasl_spnego_gensec_bind(ads
,
566 if (!ADS_ERR_OK(status
)) {
567 DBG_WARNING("ads_sasl_spnego_gensec_bind() failed "
568 "for %s/%s with user[%s]: %s\n",
569 p
.service
, p
.hostname
,
576 ads_free_service_principal(&p
);
581 ADS_STATUS
ads_sasl_bind(ADS_STRUCT
*ads
, struct cli_credentials
*creds
)
584 struct ads_saslwrap
*wrap
= &ads
->ldap_wrap_data
;
587 if (ads
->auth
.flags
& ADS_AUTH_SASL_LDAPS
) {
589 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
590 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_STARTTLS
) {
592 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
593 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SEAL
) {
594 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SEAL
;
595 } else if (ads
->auth
.flags
& ADS_AUTH_SASL_SIGN
) {
596 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
598 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_PLAIN
;
602 const DATA_BLOB
*tls_cb
= NULL
;
604 tls_cb
= ads_tls_channel_bindings(&ads
->ldap_tls_data
);
605 if (tls_cb
== NULL
) {
606 DBG_ERR("No TLS channel bindings available\n");
607 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR
);
612 status
= ads_sasl_spnego_bind(ads
, creds
);
613 if (status
.error_type
== ENUM_ADS_ERROR_LDAP
&&
614 status
.err
.rc
== LDAP_STRONG_AUTH_REQUIRED
&&
616 wrap
->wrap_type
== ADS_SASLWRAP_TYPE_PLAIN
)
618 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
619 "retrying with signing enabled\n"));
620 wrap
->wrap_type
= ADS_SASLWRAP_TYPE_SIGN
;
626 #endif /* HAVE_LDAP */