1 /*
2 Unix SMB/CIFS implementation.
3 ads sasl code
4 Copyright (C) Andrew Tridgell 2001
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "../libcli/auth/spnego.h"
22 #include "auth/credentials/credentials.h"
23 #include "auth/gensec/gensec.h"
24 #include "auth_generic.h"
25 #include "ads.h"
26 #include "smb_krb5.h"
27 #include "system/gssapi.h"
28 #include "lib/param/loadparm.h"
29 #include "krb5_env.h"
30
31 #ifdef HAVE_LDAP
32
ads_sasl_gensec_wrap(struct ads_saslwrap * wrap,uint8_t * buf,uint32_t len)33 static ADS_STATUS ads_sasl_gensec_wrap(struct ads_saslwrap *wrap,
34 uint8_t *buf, uint32_t len)
35 {
36 struct gensec_security *gensec_security =
37 talloc_get_type_abort(wrap->wrap_private_data,
38 struct gensec_security);
39 NTSTATUS nt_status;
40 DATA_BLOB unwrapped, wrapped;
41 TALLOC_CTX *frame = talloc_stackframe();
42
43 unwrapped = data_blob_const(buf, len);
44
45 nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped);
46 if (!NT_STATUS_IS_OK(nt_status)) {
47 TALLOC_FREE(frame);
48 return ADS_ERROR_NT(nt_status);
49 }
50
51 if ((wrap->out.size - 4) < wrapped.length) {
52 TALLOC_FREE(frame);
53 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
54 }
55
56 /* copy the wrapped blob to the right location */
57 memcpy(wrap->out.buf + 4, wrapped.data, wrapped.length);
58
59 /* set how many bytes must be written to the underlying socket */
60 wrap->out.left = 4 + wrapped.length;
61
62 TALLOC_FREE(frame);
63
64 return ADS_SUCCESS;
65 }
66
ads_sasl_gensec_unwrap(struct ads_saslwrap * wrap)67 static ADS_STATUS ads_sasl_gensec_unwrap(struct ads_saslwrap *wrap)
68 {
69 struct gensec_security *gensec_security =
70 talloc_get_type_abort(wrap->wrap_private_data,
71 struct gensec_security);
72 NTSTATUS nt_status;
73 DATA_BLOB unwrapped, wrapped;
74 TALLOC_CTX *frame = talloc_stackframe();
75
76 wrapped = data_blob_const(wrap->in.buf + 4, wrap->in.ofs - 4);
77
78 nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
79 if (!NT_STATUS_IS_OK(nt_status)) {
80 TALLOC_FREE(frame);
81 return ADS_ERROR_NT(nt_status);
82 }
83
84 if (wrapped.length < unwrapped.length) {
85 TALLOC_FREE(frame);
86 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
87 }
88
89 /* copy the wrapped blob to the right location */
90 memcpy(wrap->in.buf + 4, unwrapped.data, unwrapped.length);
91
92 /* set how many bytes must be written to the underlying socket */
93 wrap->in.left = unwrapped.length;
94 wrap->in.ofs = 4;
95
96 TALLOC_FREE(frame);
97
98 return ADS_SUCCESS;
99 }
100
ads_sasl_gensec_disconnect(struct ads_saslwrap * wrap)101 static void ads_sasl_gensec_disconnect(struct ads_saslwrap *wrap)
102 {
103 struct gensec_security *gensec_security =
104 talloc_get_type_abort(wrap->wrap_private_data,
105 struct gensec_security);
106
107 TALLOC_FREE(gensec_security);
108
109 wrap->wrap_ops = NULL;
110 wrap->wrap_private_data = NULL;
111 }
112
113 static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
114 .name = "gensec",
115 .wrap = ads_sasl_gensec_wrap,
116 .unwrap = ads_sasl_gensec_unwrap,
117 .disconnect = ads_sasl_gensec_disconnect
118 };
119
120 /*
121 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
122 we fit on one socket??)
123 */
ads_sasl_spnego_gensec_bind(ADS_STRUCT * ads,const char * sasl,enum credentials_use_kerberos krb5_state,const char * target_service,const char * target_hostname,const DATA_BLOB server_blob)124 static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
125 const char *sasl,
126 enum credentials_use_kerberos krb5_state,
127 const char *target_service,
128 const char *target_hostname,
129 const DATA_BLOB server_blob)
130 {
131 DATA_BLOB blob_in = data_blob_null;
132 DATA_BLOB blob_out = data_blob_null;
133 int rc;
134 NTSTATUS nt_status;
135 ADS_STATUS status;
136 struct auth_generic_state *auth_generic_state;
137 bool use_spnego_principal = lp_client_use_spnego_principal();
138 const char *sasl_list[] = { sasl, NULL };
139 NTTIME end_nt_time;
140 struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
141
142 nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
143 if (!NT_STATUS_IS_OK(nt_status)) {
144 return ADS_ERROR_NT(nt_status);
145 }
146
147 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
148 return ADS_ERROR_NT(nt_status);
149 }
150 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
151 return ADS_ERROR_NT(nt_status);
152 }
153 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
154 return ADS_ERROR_NT(nt_status);
155 }
156
157 if (server_blob.length == 0) {
158 use_spnego_principal = false;
159 }
160
161 if (krb5_state == CRED_DONT_USE_KERBEROS) {
162 use_spnego_principal = false;
163 }
164
165 cli_credentials_set_kerberos_state(auth_generic_state->credentials,
166 krb5_state);
167
168 if (target_service != NULL) {
169 nt_status = gensec_set_target_service(
170 auth_generic_state->gensec_security,
171 target_service);
172 if (!NT_STATUS_IS_OK(nt_status)) {
173 return ADS_ERROR_NT(nt_status);
174 }
175 }
176
177 if (target_hostname != NULL) {
178 nt_status = gensec_set_target_hostname(
179 auth_generic_state->gensec_security,
180 target_hostname);
181 if (!NT_STATUS_IS_OK(nt_status)) {
182 return ADS_ERROR_NT(nt_status);
183 }
184 }
185
186 if (target_service != NULL && target_hostname != NULL) {
187 use_spnego_principal = false;
188 }
189
190 switch (wrap->wrap_type) {
191 case ADS_SASLWRAP_TYPE_SEAL:
192 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
193 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
194 break;
195 case ADS_SASLWRAP_TYPE_SIGN:
196 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
197 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
198 } else {
199 /*
200 * windows servers are broken with sign only,
201 * so we let the NTLMSSP backend to seal here,
202 * via GENSEC_FEATURE_LDAP_STYLE.
203 */
204 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
205 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
206 }
207 break;
208 case ADS_SASLWRAP_TYPE_PLAIN:
209 break;
210 }
211
212 nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
213 sasl_list);
214 if (!NT_STATUS_IS_OK(nt_status)) {
215 return ADS_ERROR_NT(nt_status);
216 }
217
218 rc = LDAP_SASL_BIND_IN_PROGRESS;
219 if (use_spnego_principal) {
220 blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
221 if (blob_in.length == 0) {
222 TALLOC_FREE(auth_generic_state);
223 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
224 }
225 } else {
226 blob_in = data_blob_null;
227 }
228 blob_out = data_blob_null;
229
230 while (true) {
231 struct berval cred, *scred = NULL;
232
233 nt_status = gensec_update(auth_generic_state->gensec_security,
234 talloc_tos(), blob_in, &blob_out);
235 data_blob_free(&blob_in);
236 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
237 && !NT_STATUS_IS_OK(nt_status))
238 {
239 TALLOC_FREE(auth_generic_state);
240 data_blob_free(&blob_out);
241 return ADS_ERROR_NT(nt_status);
242 }
243
244 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
245 break;
246 }
247
248 cred.bv_val = (char *)blob_out.data;
249 cred.bv_len = blob_out.length;
250 scred = NULL;
251 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
252 data_blob_free(&blob_out);
253 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
254 if (scred) {
255 ber_bvfree(scred);
256 }
257
258 TALLOC_FREE(auth_generic_state);
259 return ADS_ERROR(rc);
260 }
261 if (scred) {
262 blob_in = data_blob_talloc(talloc_tos(),
263 scred->bv_val,
264 scred->bv_len);
265 if (blob_in.length != scred->bv_len) {
266 ber_bvfree(scred);
267 TALLOC_FREE(auth_generic_state);
268 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
269 }
270 ber_bvfree(scred);
271 } else {
272 blob_in = data_blob_null;
273 }
274 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
275 break;
276 }
277 }
278
279 data_blob_free(&blob_in);
280 data_blob_free(&blob_out);
281
282 if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
283 bool ok;
284
285 ok = gensec_have_feature(auth_generic_state->gensec_security,
286 GENSEC_FEATURE_SEAL);
287 if (!ok) {
288 DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
289 TALLOC_FREE(auth_generic_state);
290 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
291 }
292
293 ok = gensec_have_feature(auth_generic_state->gensec_security,
294 GENSEC_FEATURE_SIGN);
295 if (!ok) {
296 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
297 TALLOC_FREE(auth_generic_state);
298 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
299 }
300
301 } else if (wrap->wrap_type >= ADS_SASLWRAP_TYPE_SIGN) {
302 bool ok;
303
304 ok = gensec_have_feature(auth_generic_state->gensec_security,
305 GENSEC_FEATURE_SIGN);
306 if (!ok) {
307 DEBUG(0,("The gensec feature signing request, but unavailable\n"));
308 TALLOC_FREE(auth_generic_state);
309 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
310 }
311 }
312
313 ads->auth.tgs_expire = LONG_MAX;
314 end_nt_time = gensec_expire_time(auth_generic_state->gensec_security);
315 if (end_nt_time != GENSEC_EXPIRE_TIME_INFINITY) {
316 struct timeval tv;
317 nttime_to_timeval(&tv, end_nt_time);
318 ads->auth.tgs_expire = tv.tv_sec;
319 }
320
321 if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
322 size_t max_wrapped =
323 gensec_max_wrapped_size(auth_generic_state->gensec_security);
324 wrap->out.max_unwrapped =
325 gensec_max_input_size(auth_generic_state->gensec_security);
326
327 wrap->out.sig_size = max_wrapped - wrap->out.max_unwrapped;
328 /*
329 * Note that we have to truncate this to 0x2C
330 * (taken from a capture with LDAP unbind), as the
331 * signature size is not constant for Kerberos with
332 * arcfour-hmac-md5.
333 */
334 wrap->in.min_wrapped = MIN(wrap->out.sig_size, 0x2C);
335 wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
336 status = ads_setup_sasl_wrapping(wrap, ads->ldap.ld,
337 &ads_sasl_gensec_ops,
338 auth_generic_state->gensec_security);
339 if (!ADS_ERR_OK(status)) {
340 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
341 ads_errstr(status)));
342 TALLOC_FREE(auth_generic_state);
343 return status;
344 }
345 /* Only keep the gensec_security element around long-term */
346 talloc_steal(NULL, auth_generic_state->gensec_security);
347 }
348 TALLOC_FREE(auth_generic_state);
349
350 return ADS_ERROR(rc);
351 }
352
353 #ifdef HAVE_KRB5
ads_init_gssapi_cred(ADS_STRUCT * ads,gss_cred_id_t * cred)354 static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred)
355 {
356 ADS_STATUS status;
357 krb5_context kctx;
358 krb5_error_code kerr;
359 krb5_ccache kccache = NULL;
360 uint32_t maj, min;
361
362 *cred = GSS_C_NO_CREDENTIAL;
363
364 if (!ads->auth.ccache_name) {
365 return ADS_SUCCESS;
366 }
367
368 kerr = smb_krb5_init_context_common(&kctx);
369 if (kerr) {
370 DBG_ERR("kerberos init context failed (%s)\n",
371 error_message(kerr));
372 return ADS_ERROR_KRB5(kerr);
373 }
374
375 kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache);
376 if (kerr) {
377 status = ADS_ERROR_KRB5(kerr);
378 goto done;
379 }
380
381 maj = smb_gss_krb5_import_cred(&min, kctx, kccache, NULL, NULL, cred);
382 if (maj != GSS_S_COMPLETE) {
383 status = ADS_ERROR_GSS(maj, min);
384 goto done;
385 }
386
387 status = ADS_SUCCESS;
388
389 done:
390 if (!ADS_ERR_OK(status) && kccache != NULL) {
391 krb5_cc_close(kctx, kccache);
392 }
393 krb5_free_context(kctx);
394 return status;
395 }
396
ads_sasl_gssapi_wrap(struct ads_saslwrap * wrap,uint8_t * buf,uint32_t len)397 static ADS_STATUS ads_sasl_gssapi_wrap(struct ads_saslwrap *wrap, uint8_t *buf, uint32_t len)
398 {
399 gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
400 ADS_STATUS status;
401 int gss_rc;
402 uint32_t minor_status;
403 gss_buffer_desc unwrapped, wrapped;
404 int conf_req_flag, conf_state;
405
406 unwrapped.value = buf;
407 unwrapped.length = len;
408
409 /* for now request sign and seal */
410 conf_req_flag = (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL);
411
412 gss_rc = gss_wrap(&minor_status, context_handle,
413 conf_req_flag, GSS_C_QOP_DEFAULT,
414 &unwrapped, &conf_state,
415 &wrapped);
416 status = ADS_ERROR_GSS(gss_rc, minor_status);
417 if (!ADS_ERR_OK(status)) return status;
418
419 if (conf_req_flag && conf_state == 0) {
420 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
421 }
422
423 if ((wrap->out.size - 4) < wrapped.length) {
424 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
425 }
426
427 /* copy the wrapped blob to the right location */
428 memcpy(wrap->out.buf + 4, wrapped.value, wrapped.length);
429
430 /* set how many bytes must be written to the underlying socket */
431 wrap->out.left = 4 + wrapped.length;
432
433 gss_release_buffer(&minor_status, &wrapped);
434
435 return ADS_SUCCESS;
436 }
437
ads_sasl_gssapi_unwrap(struct ads_saslwrap * wrap)438 static ADS_STATUS ads_sasl_gssapi_unwrap(struct ads_saslwrap *wrap)
439 {
440 gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
441 ADS_STATUS status;
442 int gss_rc;
443 uint32_t minor_status;
444 gss_buffer_desc unwrapped, wrapped;
445 int conf_state;
446
447 wrapped.value = wrap->in.buf + 4;
448 wrapped.length = wrap->in.ofs - 4;
449
450 gss_rc = gss_unwrap(&minor_status, context_handle,
451 &wrapped, &unwrapped,
452 &conf_state, GSS_C_QOP_DEFAULT);
453 status = ADS_ERROR_GSS(gss_rc, minor_status);
454 if (!ADS_ERR_OK(status)) return status;
455
456 if (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL && conf_state == 0) {
457 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
458 }
459
460 if (wrapped.length < unwrapped.length) {
461 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
462 }
463
464 /* copy the wrapped blob to the right location */
465 memcpy(wrap->in.buf + 4, unwrapped.value, unwrapped.length);
466
467 /* set how many bytes must be written to the underlying socket */
468 wrap->in.left = unwrapped.length;
469 wrap->in.ofs = 4;
470
471 gss_release_buffer(&minor_status, &unwrapped);
472
473 return ADS_SUCCESS;
474 }
475
ads_sasl_gssapi_disconnect(struct ads_saslwrap * wrap)476 static void ads_sasl_gssapi_disconnect(struct ads_saslwrap *wrap)
477 {
478 gss_ctx_id_t context_handle = (gss_ctx_id_t)wrap->wrap_private_data;
479 uint32_t minor_status;
480
481 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
482
483 wrap->wrap_ops = NULL;
484 wrap->wrap_private_data = NULL;
485 }
486
487 static const struct ads_saslwrap_ops ads_sasl_gssapi_ops = {
488 .name = "gssapi",
489 .wrap = ads_sasl_gssapi_wrap,
490 .unwrap = ads_sasl_gssapi_unwrap,
491 .disconnect = ads_sasl_gssapi_disconnect
492 };
493
494 #endif /* HAVE_KRB5 */
495
496 #ifdef HAVE_KRB5
497 struct ads_service_principal {
498 char *service;
499 char *hostname;
500 char *string;
501 #ifdef HAVE_KRB5
502 gss_name_t name;
503 #endif
504 };
505
ads_free_service_principal(struct ads_service_principal * p)506 static void ads_free_service_principal(struct ads_service_principal *p)
507 {
508 SAFE_FREE(p->service);
509 SAFE_FREE(p->hostname);
510 SAFE_FREE(p->string);
511
512 #ifdef HAVE_KRB5
513 if (p->name) {
514 uint32_t minor_status;
515 gss_release_name(&minor_status, &p->name);
516 }
517 #endif
518 ZERO_STRUCTP(p);
519 }
520
ads_guess_target(ADS_STRUCT * ads,char ** service,char ** hostname,char ** principal)521 static ADS_STATUS ads_guess_target(ADS_STRUCT *ads,
522 char **service,
523 char **hostname,
524 char **principal)
525 {
526 ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
527 char *princ = NULL;
528 TALLOC_CTX *frame;
529 char *server = NULL;
530 char *realm = NULL;
531 int rc;
532
533 frame = talloc_stackframe();
534 if (frame == NULL) {
535 return ADS_ERROR(LDAP_NO_MEMORY);
536 }
537
538 if (ads->server.realm && ads->server.ldap_server) {
539 server = strlower_talloc(frame, ads->server.ldap_server);
540 if (server == NULL) {
541 goto out;
542 }
543
544 realm = strupper_talloc(frame, ads->server.realm);
545 if (realm == NULL) {
546 goto out;
547 }
548
549 /*
550 * If we got a name which is bigger than a NetBIOS name,
551 * but isn't a FQDN, create one.
552 */
553 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
554 char *dnsdomain;
555
556 dnsdomain = strlower_talloc(frame, ads->server.realm);
557 if (dnsdomain == NULL) {
558 goto out;
559 }
560
561 server = talloc_asprintf(frame,
562 "%s.%s",
563 server, dnsdomain);
564 if (server == NULL) {
565 goto out;
566 }
567 }
568 } else if (ads->config.realm && ads->config.ldap_server_name) {
569 server = strlower_talloc(frame, ads->config.ldap_server_name);
570 if (server == NULL) {
571 goto out;
572 }
573
574 realm = strupper_talloc(frame, ads->config.realm);
575 if (realm == NULL) {
576 goto out;
577 }
578
579 /*
580 * If we got a name which is bigger than a NetBIOS name,
581 * but isn't a FQDN, create one.
582 */
583 if (strlen(server) > 15 && strstr(server, ".") == NULL) {
584 char *dnsdomain;
585
586 dnsdomain = strlower_talloc(frame, ads->server.realm);
587 if (dnsdomain == NULL) {
588 goto out;
589 }
590
591 server = talloc_asprintf(frame,
592 "%s.%s",
593 server, dnsdomain);
594 if (server == NULL) {
595 goto out;
596 }
597 }
598 }
599
600 if (server == NULL || realm == NULL) {
601 goto out;
602 }
603
604 *service = SMB_STRDUP("ldap");
605 if (*service == NULL) {
606 status = ADS_ERROR(LDAP_PARAM_ERROR);
607 goto out;
608 }
609 *hostname = SMB_STRDUP(server);
610 if (*hostname == NULL) {
611 SAFE_FREE(*service);
612 status = ADS_ERROR(LDAP_PARAM_ERROR);
613 goto out;
614 }
615 rc = asprintf(&princ, "ldap/%s@%s", server, realm);
616 if (rc == -1 || princ == NULL) {
617 SAFE_FREE(*service);
618 SAFE_FREE(*hostname);
619 status = ADS_ERROR(LDAP_PARAM_ERROR);
620 goto out;
621 }
622
623 *principal = princ;
624
625 status = ADS_SUCCESS;
626 out:
627 TALLOC_FREE(frame);
628 return status;
629 }
630
ads_generate_service_principal(ADS_STRUCT * ads,struct ads_service_principal * p)631 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
632 struct ads_service_principal *p)
633 {
634 ADS_STATUS status;
635 #ifdef HAVE_KRB5
636 gss_buffer_desc input_name;
637 /* GSS_KRB5_NT_PRINCIPAL_NAME */
638 gss_OID_desc nt_principal =
639 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
640 uint32_t minor_status;
641 int gss_rc;
642 #endif
643
644 ZERO_STRUCTP(p);
645
646 status = ads_guess_target(ads,
647 &p->service,
648 &p->hostname,
649 &p->string);
650 if (!ADS_ERR_OK(status)) {
651 return status;
652 }
653
654 #ifdef HAVE_KRB5
655 input_name.value = p->string;
656 input_name.length = strlen(p->string);
657
658 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name);
659 if (gss_rc) {
660 ads_free_service_principal(p);
661 return ADS_ERROR_GSS(gss_rc, minor_status);
662 }
663 #endif
664
665 return ADS_SUCCESS;
666 }
667
668 #endif /* HAVE_KRB5 */
669
670 /*
671 this performs a SASL/SPNEGO bind
672 */
ads_sasl_spnego_bind(ADS_STRUCT * ads)673 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
674 {
675 TALLOC_CTX *frame = talloc_stackframe();
676 struct ads_service_principal p = {0};
677 struct berval *scred=NULL;
678 int rc, i;
679 ADS_STATUS status;
680 DATA_BLOB blob = data_blob_null;
681 char *given_principal = NULL;
682 char *OIDs[ASN1_MAX_OIDS];
683 #ifdef HAVE_KRB5
684 bool got_kerberos_mechanism = False;
685 #endif
686 const char *mech = NULL;
687
688 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
689
690 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
691 status = ADS_ERROR(rc);
692 goto done;
693 }
694
695 blob = data_blob(scred->bv_val, scred->bv_len);
696
697 ber_bvfree(scred);
698
699 #if 0
700 file_save("sasl_spnego.dat", blob.data, blob.length);
701 #endif
702
703 /* the server sent us the first part of the SPNEGO exchange in the negprot
704 reply */
705 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
706 OIDs[0] == NULL) {
707 status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
708 goto done;
709 }
710 TALLOC_FREE(given_principal);
711
712 /* make sure the server understands kerberos */
713 for (i=0;OIDs[i];i++) {
714 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
715 #ifdef HAVE_KRB5
716 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
717 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
718 got_kerberos_mechanism = True;
719 }
720 #endif
721 talloc_free(OIDs[i]);
722 }
723
724 status = ads_generate_service_principal(ads, &p);
725 if (!ADS_ERR_OK(status)) {
726 goto done;
727 }
728
729 #ifdef HAVE_KRB5
730 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
731 got_kerberos_mechanism)
732 {
733 mech = "KRB5";
734
735 if (ads->auth.password == NULL ||
736 ads->auth.password[0] == '\0')
737 {
738
739 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
740 CRED_MUST_USE_KERBEROS,
741 p.service, p.hostname,
742 blob);
743 if (ADS_ERR_OK(status)) {
744 ads_free_service_principal(&p);
745 goto done;
746 }
747
748 DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
749 "calling kinit\n", ads_errstr(status)));
750 }
751
752 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
753
754 if (ADS_ERR_OK(status)) {
755 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
756 CRED_MUST_USE_KERBEROS,
757 p.service, p.hostname,
758 blob);
759 if (!ADS_ERR_OK(status)) {
760 DEBUG(0,("kinit succeeded but "
761 "ads_sasl_spnego_gensec_bind(KRB5) failed "
762 "for %s/%s with user[%s] realm[%s]: %s\n",
763 p.service, p.hostname,
764 ads->auth.user_name,
765 ads->auth.realm,
766 ads_errstr(status)));
767 }
768 }
769
770 /* only fallback to NTLMSSP if allowed */
771 if (ADS_ERR_OK(status) ||
772 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
773 goto done;
774 }
775
776 DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed "
777 "for %s/%s with user[%s] realm[%s]: %s, "
778 "fallback to NTLMSSP\n",
779 p.service, p.hostname,
780 ads->auth.user_name,
781 ads->auth.realm,
782 ads_errstr(status)));
783 }
784 #endif
785
786 /* lets do NTLMSSP ... this has the big advantage that we don't need
787 to sync clocks, and we don't rely on special versions of the krb5
788 library for HMAC_MD4 encryption */
789 mech = "NTLMSSP";
790 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
791 CRED_DONT_USE_KERBEROS,
792 p.service, p.hostname,
793 data_blob_null);
794 done:
795 if (!ADS_ERR_OK(status)) {
796 DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed "
797 "for %s/%s with user[%s] realm=[%s]: %s\n", mech,
798 p.service, p.hostname,
799 ads->auth.user_name,
800 ads->auth.realm,
801 ads_errstr(status)));
802 }
803 ads_free_service_principal(&p);
804 TALLOC_FREE(frame);
805 if (blob.data != NULL) {
806 data_blob_free(&blob);
807 }
808 return status;
809 }
810
811 #ifdef HAVE_KRB5
812 #define MAX_GSS_PASSES 3
813
814 /* this performs a SASL/gssapi bind
815 we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
816 is very dependent on correctly configured DNS whereas
817 this routine is much less fragile
818 see RFC2078 and RFC2222 for details
819 */
ads_sasl_gssapi_do_bind(ADS_STRUCT * ads,const gss_name_t serv_name)820 static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
821 {
822 uint32_t minor_status;
823 gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
824 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
825 gss_OID mech_type = GSS_C_NULL_OID;
826 gss_buffer_desc output_token, input_token;
827 uint32_t req_flags, ret_flags;
828 int conf_state;
829 struct berval cred;
830 struct berval *scred = NULL;
831 int i=0;
832 int gss_rc, rc;
833 uint8_t *p;
834 uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
835 uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
836 ADS_STATUS status;
837 struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
838
839 input_token.value = NULL;
840 input_token.length = 0;
841
842 status = ads_init_gssapi_cred(ads, &gss_cred);
843 if (!ADS_ERR_OK(status)) {
844 goto failed;
845 }
846
847 /*
848 * Note: here we always ask the gssapi for sign and seal
849 * as this is negotiated later after the mutal
850 * authentication
851 */
852 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
853
854 for (i=0; i < MAX_GSS_PASSES; i++) {
855 gss_rc = gss_init_sec_context(&minor_status,
856 gss_cred,
857 &context_handle,
858 serv_name,
859 mech_type,
860 req_flags,
861 0,
862 NULL,
863 &input_token,
864 NULL,
865 &output_token,
866 &ret_flags,
867 NULL);
868 if (scred) {
869 ber_bvfree(scred);
870 scred = NULL;
871 }
872 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
873 status = ADS_ERROR_GSS(gss_rc, minor_status);
874 goto failed;
875 }
876
877 cred.bv_val = (char *)output_token.value;
878 cred.bv_len = output_token.length;
879
880 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
881 &scred);
882 if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
883 status = ADS_ERROR(rc);
884 goto failed;
885 }
886
887 if (output_token.value) {
888 gss_release_buffer(&minor_status, &output_token);
889 }
890
891 if (scred) {
892 input_token.value = scred->bv_val;
893 input_token.length = scred->bv_len;
894 } else {
895 input_token.value = NULL;
896 input_token.length = 0;
897 }
898
899 if (gss_rc == 0) break;
900 }
901
902 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
903 &conf_state,NULL);
904 if (scred) {
905 ber_bvfree(scred);
906 scred = NULL;
907 }
908 if (gss_rc) {
909 status = ADS_ERROR_GSS(gss_rc, minor_status);
910 goto failed;
911 }
912
913 p = (uint8_t *)output_token.value;
914
915 #if 0
916 file_save("sasl_gssapi.dat", output_token.value, output_token.length);
917 #endif
918
919 if (p) {
920 wrap_type = CVAL(p,0);
921 SCVAL(p,0,0);
922 max_msg_size = RIVAL(p,0);
923 }
924
925 gss_release_buffer(&minor_status, &output_token);
926
927 if (!(wrap_type & wrap->wrap_type)) {
928 /*
929 * the server doesn't supports the wrap
930 * type we want :-(
931 */
932 DEBUG(0,("The ldap sasl wrap type doesn't match wanted[%d] server[%d]\n",
933 wrap->wrap_type, wrap_type));
934 DEBUGADD(0,("You may want to set the 'client ldap sasl wrapping' option\n"));
935 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
936 goto failed;
937 }
938
939 /* 0x58 is the minimum windows accepts */
940 if (max_msg_size < 0x58) {
941 max_msg_size = 0x58;
942 }
943
944 output_token.length = 4;
945 output_token.value = SMB_MALLOC(output_token.length);
946 if (!output_token.value) {
947 output_token.length = 0;
948 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
949 goto failed;
950 }
951 p = (uint8_t *)output_token.value;
952
953 RSIVAL(p,0,max_msg_size);
954 SCVAL(p,0,wrap->wrap_type);
955
956 /*
957 * we used to add sprintf("dn:%s", ads->config.bind_path) here.
958 * but using ads->config.bind_path is the wrong! It should be
959 * the DN of the user object!
960 *
961 * w2k3 gives an error when we send an incorrect DN, but sending nothing
962 * is ok and matches the information flow used in GSS-SPNEGO.
963 */
964
965 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
966 &output_token, /* used as *input* here. */
967 &conf_state,
968 &input_token); /* Used as *output* here. */
969 if (gss_rc) {
970 status = ADS_ERROR_GSS(gss_rc, minor_status);
971 output_token.length = 0;
972 SAFE_FREE(output_token.value);
973 goto failed;
974 }
975
976 /* We've finished with output_token. */
977 SAFE_FREE(output_token.value);
978 output_token.length = 0;
979
980 cred.bv_val = (char *)input_token.value;
981 cred.bv_len = input_token.length;
982
983 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSSAPI", &cred, NULL, NULL,
984 &scred);
985 gss_release_buffer(&minor_status, &input_token);
986 status = ADS_ERROR(rc);
987 if (!ADS_ERR_OK(status)) {
988 goto failed;
989 }
990
991 if (wrap->wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
992 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
993 (wrap->wrap_type == ADS_SASLWRAP_TYPE_SEAL),
994 GSS_C_QOP_DEFAULT,
995 max_msg_size, &wrap->out.max_unwrapped);
996 if (gss_rc) {
997 status = ADS_ERROR_GSS(gss_rc, minor_status);
998 goto failed;
999 }
1000
1001 wrap->out.sig_size = max_msg_size - wrap->out.max_unwrapped;
1002 wrap->in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
1003 wrap->in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
1004 status = ads_setup_sasl_wrapping(wrap->wrap_private_data, ads->ldap.ld,
1005 &ads_sasl_gssapi_ops,
1006 context_handle);
1007 if (!ADS_ERR_OK(status)) {
1008 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
1009 ads_errstr(status)));
1010 goto failed;
1011 }
1012 /* make sure we don't free context_handle */
1013 context_handle = GSS_C_NO_CONTEXT;
1014 }
1015
1016 failed:
1017 if (gss_cred != GSS_C_NO_CREDENTIAL)
1018 gss_release_cred(&minor_status, &gss_cred);
1019 if (context_handle != GSS_C_NO_CONTEXT)
1020 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
1021
1022 if(scred)
1023 ber_bvfree(scred);
1024 return status;
1025 }
1026
ads_sasl_gssapi_bind(ADS_STRUCT * ads)1027 static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
1028 {
1029 ADS_STATUS status;
1030 struct ads_service_principal p;
1031
1032 status = ads_generate_service_principal(ads, &p);
1033 if (!ADS_ERR_OK(status)) {
1034 return status;
1035 }
1036
1037 if (ads->auth.password == NULL ||
1038 ads->auth.password[0] == '\0') {
1039 status = ads_sasl_gssapi_do_bind(ads, p.name);
1040 if (ADS_ERR_OK(status)) {
1041 ads_free_service_principal(&p);
1042 return status;
1043 }
1044
1045 DEBUG(10,("ads_sasl_gssapi_do_bind failed with: %s, "
1046 "calling kinit\n", ads_errstr(status)));
1047 }
1048
1049 status = ADS_ERROR_KRB5(ads_kinit_password(ads));
1050
1051 if (ADS_ERR_OK(status)) {
1052 status = ads_sasl_gssapi_do_bind(ads, p.name);
1053 }
1054
1055 ads_free_service_principal(&p);
1056
1057 return status;
1058 }
1059
1060 #endif /* HAVE_KRB5 */
1061
1062 /* mapping between SASL mechanisms and functions */
1063 static struct {
1064 const char *name;
1065 ADS_STATUS (*fn)(ADS_STRUCT *);
1066 } sasl_mechanisms[] = {
1067 {"GSS-SPNEGO", ads_sasl_spnego_bind},
1068 #ifdef HAVE_KRB5
1069 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
1070 #endif
1071 {NULL, NULL}
1072 };
1073
ads_sasl_bind(ADS_STRUCT * ads)1074 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
1075 {
1076 const char *attrs[] = {"supportedSASLMechanisms", NULL};
1077 char **values;
1078 ADS_STATUS status;
1079 int i, j;
1080 LDAPMessage *res;
1081 struct ads_saslwrap *wrap = &ads->ldap_wrap_data;
1082
1083 /* get a list of supported SASL mechanisms */
1084 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
1085 if (!ADS_ERR_OK(status)) return status;
1086
1087 values = ldap_get_values(ads->ldap.ld, res, "supportedSASLMechanisms");
1088
1089 if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
1090 wrap->wrap_type = ADS_SASLWRAP_TYPE_SEAL;
1091 } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
1092 wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1093 } else {
1094 wrap->wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
1095 }
1096
1097 /* try our supported mechanisms in order */
1098 for (i=0;sasl_mechanisms[i].name;i++) {
1099 /* see if the server supports it */
1100 for (j=0;values && values[j];j++) {
1101 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
1102 DEBUG(4,("Found SASL mechanism %s\n", values[j]));
1103 retry:
1104 status = sasl_mechanisms[i].fn(ads);
1105 if (status.error_type == ENUM_ADS_ERROR_LDAP &&
1106 status.err.rc == LDAP_STRONG_AUTH_REQUIRED &&
1107 wrap->wrap_type == ADS_SASLWRAP_TYPE_PLAIN)
1108 {
1109 DEBUG(3,("SASL bin got LDAP_STRONG_AUTH_REQUIRED "
1110 "retrying with signing enabled\n"));
1111 wrap->wrap_type = ADS_SASLWRAP_TYPE_SIGN;
1112 goto retry;
1113 }
1114 ldap_value_free(values);
1115 ldap_msgfree(res);
1116 return status;
1117 }
1118 }
1119 }
1120
1121 ldap_value_free(values);
1122 ldap_msgfree(res);
1123 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
1124 }
1125
1126 #endif /* HAVE_LDAP */
1127
1128