Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Generic Authentication Interface
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "system/network.h"
25 : #include "tevent.h"
26 : #include "../lib/util/tevent_ntstatus.h"
27 : #include "librpc/gen_ndr/dcerpc.h"
28 : #include "auth/credentials/credentials.h"
29 : #include "auth/gensec/gensec.h"
30 : #include "auth/gensec/gensec_internal.h"
31 : #include "lib/param/param.h"
32 : #include "lib/param/loadparm.h"
33 : #include "lib/util/tsort.h"
34 : #include "lib/util/samba_modules.h"
35 : #include "lib/util/base64.h"
36 :
37 : #undef DBGC_CLASS
38 : #define DBGC_CLASS DBGC_AUTH
39 :
40 : #undef strcasecmp
41 :
42 : /* the list of currently registered GENSEC backends */
43 : static const struct gensec_security_ops **generic_security_ops;
44 : static int gensec_num_backends;
45 :
46 3780819 : bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security)
47 : {
48 3872333 : bool ok = lpcfg_parm_bool(security->settings->lp_ctx,
49 : NULL,
50 : "gensec",
51 3780819 : ops->name,
52 3780819 : ops->enabled);
53 :
54 4473961 : if (ops->weak_crypto &&
55 693142 : lpcfg_weak_crypto(security->settings->lp_ctx) != SAMBA_WEAK_CRYPTO_ALLOWED) {
56 0 : ok = false;
57 : }
58 :
59 3780819 : return ok;
60 : }
61 :
62 : /* Sometimes we want to force only kerberos, sometimes we want to
63 : * force it's avoidance. The old list could be either
64 : * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
65 : * an existing list we have trimmed down)
66 : *
67 : * The intended logic is:
68 : *
69 : * if we are in the default AUTO have kerberos:
70 : * - take a reference to the master list
71 : * otherwise
72 : * - always add spnego then:
73 : * - if we 'MUST' have kerberos:
74 : * only add kerberos mechs
75 : * - if we 'DONT' want kerberos':
76 : * only add non-kerberos mechs
77 : *
78 : * Once we get things like NegoEx or moonshot, this will of course get
79 : * more complex.
80 : */
81 :
82 1749760 : static const struct gensec_security_ops **gensec_use_kerberos_mechs(
83 : TALLOC_CTX *mem_ctx,
84 : const struct gensec_security_ops * const *old_gensec_list,
85 : enum credentials_use_kerberos use_kerberos,
86 : bool keep_schannel)
87 : {
88 27693 : const struct gensec_security_ops **new_gensec_list;
89 27693 : int i, j, num_mechs_in;
90 :
91 18220754 : for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
92 : /* noop */
93 260862 : }
94 :
95 1749760 : new_gensec_list = talloc_array(mem_ctx,
96 : const struct gensec_security_ops *,
97 : num_mechs_in + 1);
98 1749760 : if (!new_gensec_list) {
99 0 : return NULL;
100 : }
101 :
102 1722067 : j = 0;
103 18220754 : for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
104 16470994 : bool keep = false;
105 :
106 : /*
107 : * We want to keep SPNEGO and other backends
108 : */
109 16470994 : keep = old_gensec_list[i]->glue;
110 :
111 16470994 : if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
112 1488671 : keep = keep_schannel;
113 : }
114 :
115 16470994 : switch (use_kerberos) {
116 14698127 : case CRED_USE_KERBEROS_DESIRED:
117 14698127 : keep = true;
118 14698127 : break;
119 :
120 1200719 : case CRED_USE_KERBEROS_DISABLED:
121 1200719 : if (old_gensec_list[i]->kerberos == false) {
122 880583 : keep = true;
123 : }
124 :
125 1188427 : break;
126 :
127 335716 : case CRED_USE_KERBEROS_REQUIRED:
128 335716 : if (old_gensec_list[i]->kerberos == true) {
129 113143 : keep = true;
130 : }
131 :
132 323578 : break;
133 0 : default:
134 : /* Can't happen or invalid parameter */
135 0 : return NULL;
136 : }
137 :
138 16222325 : if (!keep) {
139 480830 : continue;
140 : }
141 :
142 15990164 : new_gensec_list[j] = old_gensec_list[i];
143 15990164 : j++;
144 : }
145 1749760 : new_gensec_list[j] = NULL;
146 :
147 1749760 : return new_gensec_list;
148 : }
149 :
150 1749760 : _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
151 : struct gensec_security *gensec_security,
152 : TALLOC_CTX *mem_ctx)
153 : {
154 1749760 : const struct gensec_security_ops * const *backends =
155 : generic_security_ops;
156 1749760 : enum credentials_use_kerberos use_kerberos = CRED_USE_KERBEROS_DESIRED;
157 1749760 : bool keep_schannel = false;
158 :
159 1749760 : if (gensec_security != NULL) {
160 559985 : struct cli_credentials *creds = NULL;
161 :
162 559985 : creds = gensec_get_credentials(gensec_security);
163 559985 : if (creds != NULL) {
164 559981 : use_kerberos = cli_credentials_get_kerberos_state(creds);
165 559981 : if (cli_credentials_get_netlogon_creds(creds) != NULL) {
166 5403 : keep_schannel = true;
167 : }
168 :
169 : /*
170 : * Even if Kerberos is set to REQUIRED, keep the
171 : * schannel auth mechanism so that machine accounts are
172 : * able to authenticate via netlogon.
173 : */
174 559981 : if (gensec_security->gensec_role == GENSEC_SERVER) {
175 346786 : keep_schannel = true;
176 : }
177 : }
178 :
179 559985 : if (gensec_security->settings->backends) {
180 205202 : backends = gensec_security->settings->backends;
181 : }
182 : }
183 :
184 1749760 : return gensec_use_kerberos_mechs(mem_ctx, backends,
185 : use_kerberos, keep_schannel);
186 :
187 : }
188 :
189 358251 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
190 : struct gensec_security *gensec_security,
191 : const char *oid_string)
192 : {
193 3196 : int i, j;
194 3196 : const struct gensec_security_ops **backends;
195 3196 : const struct gensec_security_ops *backend;
196 358251 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
197 358251 : if (!mem_ctx) {
198 0 : return NULL;
199 : }
200 358251 : backends = gensec_security_mechs(gensec_security, mem_ctx);
201 1111911 : for (i=0; backends && backends[i]; i++) {
202 1111781 : if (gensec_security != NULL &&
203 238165 : !gensec_security_ops_enabled(backends[i],
204 : gensec_security))
205 240 : continue;
206 1108331 : if (backends[i]->oid) {
207 1465680 : for (j=0; backends[i]->oid[j]; j++) {
208 993394 : if (backends[i]->oid[j] &&
209 993394 : (strcmp(backends[i]->oid[j], oid_string) == 0)) {
210 358107 : backend = backends[i];
211 358107 : talloc_free(mem_ctx);
212 358107 : return backend;
213 : }
214 : }
215 : }
216 : }
217 144 : talloc_free(mem_ctx);
218 :
219 144 : return NULL;
220 : }
221 :
222 26762 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
223 : struct gensec_security *gensec_security,
224 : const char *sasl_name)
225 : {
226 122 : int i;
227 122 : const struct gensec_security_ops **backends;
228 122 : const struct gensec_security_ops *backend;
229 26762 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
230 26762 : if (!mem_ctx) {
231 0 : return NULL;
232 : }
233 26762 : backends = gensec_security_mechs(gensec_security, mem_ctx);
234 27682 : for (i=0; backends && backends[i]; i++) {
235 27680 : if (gensec_security != NULL &&
236 27558 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
237 260 : continue;
238 : }
239 27298 : if (backends[i]->sasl_name
240 27026 : && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
241 26760 : backend = backends[i];
242 26760 : talloc_free(mem_ctx);
243 26760 : return backend;
244 : }
245 : }
246 2 : talloc_free(mem_ctx);
247 :
248 2 : return NULL;
249 : }
250 :
251 253010 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
252 : struct gensec_security *gensec_security,
253 : uint32_t auth_type)
254 : {
255 854 : int i;
256 854 : const struct gensec_security_ops **backends;
257 854 : const struct gensec_security_ops *backend;
258 854 : TALLOC_CTX *mem_ctx;
259 :
260 253010 : if (auth_type == DCERPC_AUTH_TYPE_NONE) {
261 0 : return NULL;
262 : }
263 :
264 253010 : mem_ctx = talloc_new(gensec_security);
265 253010 : if (!mem_ctx) {
266 0 : return NULL;
267 : }
268 253010 : backends = gensec_security_mechs(gensec_security, mem_ctx);
269 1679391 : for (i=0; backends && backends[i]; i++) {
270 1683257 : if (gensec_security != NULL &&
271 58663 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
272 11020 : continue;
273 : }
274 1667439 : if (backends[i]->auth_type == auth_type) {
275 252932 : backend = backends[i];
276 252932 : talloc_free(mem_ctx);
277 252932 : return backend;
278 : }
279 : }
280 78 : talloc_free(mem_ctx);
281 :
282 78 : return NULL;
283 : }
284 :
285 722458 : const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
286 : const char *name)
287 : {
288 16912 : int i;
289 16912 : const struct gensec_security_ops **backends;
290 16912 : const struct gensec_security_ops *backend;
291 722458 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
292 722458 : if (!mem_ctx) {
293 0 : return NULL;
294 : }
295 722458 : backends = gensec_security_mechs(gensec_security, mem_ctx);
296 5037888 : for (i=0; backends && backends[i]; i++) {
297 4359180 : if (gensec_security != NULL &&
298 6629 : !gensec_security_ops_enabled(backends[i], gensec_security))
299 1288 : continue;
300 4357892 : if (backends[i]->name
301 4357892 : && (strcmp(backends[i]->name, name) == 0)) {
302 60662 : backend = backends[i];
303 60662 : talloc_free(mem_ctx);
304 60662 : return backend;
305 : }
306 : }
307 661796 : talloc_free(mem_ctx);
308 661796 : return NULL;
309 : }
310 :
311 53525 : static const char **gensec_security_sasl_names_from_ops(
312 : struct gensec_security *gensec_security,
313 : TALLOC_CTX *mem_ctx,
314 : const struct gensec_security_ops * const *ops)
315 : {
316 53525 : const char **sasl_names = NULL;
317 53525 : size_t i, sasl_names_count = 0;
318 :
319 53525 : if (ops == NULL) {
320 0 : return NULL;
321 : }
322 :
323 53525 : sasl_names = talloc_array(mem_ctx, const char *, 1);
324 53525 : if (sasl_names == NULL) {
325 0 : return NULL;
326 : }
327 :
328 802875 : for (i = 0; ops[i] != NULL; i++) {
329 749350 : enum gensec_role role = GENSEC_SERVER;
330 749350 : const char **tmp = NULL;
331 :
332 749350 : if (ops[i]->sasl_name == NULL) {
333 481725 : continue;
334 : }
335 :
336 267625 : if (gensec_security != NULL) {
337 267625 : if (!gensec_security_ops_enabled(ops[i],
338 : gensec_security)) {
339 53525 : continue;
340 : }
341 :
342 214100 : role = gensec_security->gensec_role;
343 : }
344 :
345 214100 : switch (role) {
346 0 : case GENSEC_CLIENT:
347 0 : if (ops[i]->client_start == NULL) {
348 0 : continue;
349 : }
350 0 : break;
351 214100 : case GENSEC_SERVER:
352 214100 : if (ops[i]->server_start == NULL) {
353 53525 : continue;
354 : }
355 159843 : break;
356 : }
357 :
358 160575 : tmp = talloc_realloc(mem_ctx,
359 : sasl_names,
360 : const char *,
361 : sasl_names_count + 2);
362 160575 : if (tmp == NULL) {
363 0 : TALLOC_FREE(sasl_names);
364 0 : return NULL;
365 : }
366 160575 : sasl_names = tmp;
367 :
368 160575 : sasl_names[sasl_names_count] = ops[i]->sasl_name;
369 160575 : sasl_names_count++;
370 : }
371 53525 : sasl_names[sasl_names_count] = NULL;
372 :
373 53525 : return sasl_names;
374 : }
375 :
376 : /**
377 : * @brief Get the sasl names from the gensec security context.
378 : *
379 : * @param[in] gensec_security The gensec security context.
380 : *
381 : * @param[in] mem_ctx The memory context to allocate memory on.
382 : *
383 : * @return An allocated array with sasl names, NULL on error.
384 : */
385 : _PUBLIC_
386 53525 : const char **gensec_security_sasl_names(struct gensec_security *gensec_security,
387 : TALLOC_CTX *mem_ctx)
388 : {
389 53525 : const struct gensec_security_ops **ops = NULL;
390 :
391 53525 : ops = gensec_security_mechs(gensec_security, mem_ctx);
392 :
393 53525 : return gensec_security_sasl_names_from_ops(gensec_security,
394 : mem_ctx,
395 : ops);
396 : }
397 :
398 : /**
399 : * Return a unique list of security subsystems from those specified in
400 : * the list of SASL names.
401 : *
402 : * Use the list of enabled GENSEC mechanisms from the credentials
403 : * attached to the gensec_security, and return in our preferred order.
404 : */
405 :
406 26533 : static const struct gensec_security_ops **gensec_security_by_sasl_list(
407 : struct gensec_security *gensec_security,
408 : TALLOC_CTX *mem_ctx,
409 : const char **sasl_names)
410 : {
411 122 : const struct gensec_security_ops **backends_out;
412 122 : const struct gensec_security_ops **backends;
413 122 : int i, k, sasl_idx;
414 26533 : int num_backends_out = 0;
415 :
416 26533 : if (!sasl_names) {
417 0 : return NULL;
418 : }
419 :
420 26533 : backends = gensec_security_mechs(gensec_security, mem_ctx);
421 :
422 26533 : backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
423 26533 : if (!backends_out) {
424 0 : return NULL;
425 : }
426 26533 : backends_out[0] = NULL;
427 :
428 : /* Find backends in our preferred order, by walking our list,
429 : * then looking in the supplied list */
430 335023 : for (i=0; backends && backends[i]; i++) {
431 310198 : if (gensec_security != NULL &&
432 308490 : !gensec_security_ops_enabled(backends[i], gensec_security))
433 35632 : continue;
434 1090182 : for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
435 817324 : if (!backends[i]->sasl_name ||
436 275004 : !(strcmp(backends[i]->sasl_name,
437 273540 : sasl_names[sasl_idx]) == 0)) {
438 749212 : continue;
439 : }
440 :
441 125048 : for (k=0; backends_out[k]; k++) {
442 56936 : if (backends_out[k] == backends[i]) {
443 0 : break;
444 : }
445 : }
446 :
447 68112 : if (k < num_backends_out) {
448 : /* already in there */
449 0 : continue;
450 : }
451 :
452 68112 : backends_out = talloc_realloc(mem_ctx, backends_out,
453 : const struct gensec_security_ops *,
454 : num_backends_out + 2);
455 68112 : if (!backends_out) {
456 0 : return NULL;
457 : }
458 :
459 68112 : backends_out[num_backends_out] = backends[i];
460 68112 : num_backends_out++;
461 68112 : backends_out[num_backends_out] = NULL;
462 : }
463 : }
464 26411 : return backends_out;
465 : }
466 :
467 : /**
468 : * Return a unique list of security subsystems from those specified in
469 : * the OID list. That is, where two OIDs refer to the same module,
470 : * return that module only once.
471 : *
472 : * Use the list of enabled GENSEC mechanisms from the credentials
473 : * attached to the gensec_security, and return in our preferred order.
474 : */
475 :
476 188399 : _PUBLIC_ const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(
477 : struct gensec_security *gensec_security,
478 : TALLOC_CTX *mem_ctx,
479 : const char * const *oid_strings,
480 : const char *skip)
481 : {
482 3636 : struct gensec_security_ops_wrapper *backends_out;
483 3636 : const struct gensec_security_ops **backends;
484 3636 : int i, j, k, oid_idx;
485 188399 : int num_backends_out = 0;
486 :
487 188399 : if (!oid_strings) {
488 0 : return NULL;
489 : }
490 :
491 188399 : backends = gensec_security_mechs(gensec_security, gensec_security);
492 :
493 188399 : backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
494 188399 : if (!backends_out) {
495 0 : return NULL;
496 : }
497 188399 : backends_out[0].op = NULL;
498 188399 : backends_out[0].oid = NULL;
499 :
500 : /* Find backends in our preferred order, by walking our list,
501 : * then looking in the supplied list */
502 1983403 : for (i=0; backends && backends[i]; i++) {
503 1842435 : if (gensec_security != NULL &&
504 1795004 : !gensec_security_ops_enabled(backends[i], gensec_security))
505 195483 : continue;
506 1599521 : if (!backends[i]->oid) {
507 1108090 : continue;
508 : }
509 1580688 : for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
510 1089257 : if (strcmp(oid_strings[oid_idx], skip) == 0) {
511 0 : continue;
512 : }
513 :
514 2502988 : for (j=0; backends[i]->oid[j]; j++) {
515 1441379 : if (!backends[i]->oid[j] ||
516 1413731 : !(strcmp(backends[i]->oid[j],
517 1376481 : oid_strings[oid_idx]) == 0)) {
518 1023428 : continue;
519 : }
520 :
521 483808 : for (k=0; backends_out[k].op; k++) {
522 201907 : if (backends_out[k].op == backends[i]) {
523 105204 : break;
524 : }
525 : }
526 :
527 390303 : if (k < num_backends_out) {
528 : /* already in there */
529 108402 : continue;
530 : }
531 :
532 281901 : backends_out = talloc_realloc(mem_ctx, backends_out,
533 : struct gensec_security_ops_wrapper,
534 : num_backends_out + 2);
535 281901 : if (!backends_out) {
536 0 : return NULL;
537 : }
538 :
539 281901 : backends_out[num_backends_out].op = backends[i];
540 281901 : backends_out[num_backends_out].oid = backends[i]->oid[j];
541 281901 : num_backends_out++;
542 281901 : backends_out[num_backends_out].op = NULL;
543 281901 : backends_out[num_backends_out].oid = NULL;
544 : }
545 : }
546 : }
547 184763 : return backends_out;
548 : }
549 :
550 : /**
551 : * Return OIDS from the security subsystems listed
552 : */
553 :
554 120675 : static const char **gensec_security_oids_from_ops(
555 : struct gensec_security *gensec_security,
556 : TALLOC_CTX *mem_ctx,
557 : const struct gensec_security_ops * const *ops,
558 : const char *skip)
559 : {
560 2607 : int i;
561 120675 : int j = 0;
562 2607 : int k;
563 2607 : const char **oid_list;
564 120675 : if (!ops) {
565 0 : return NULL;
566 : }
567 120675 : oid_list = talloc_array(mem_ctx, const char *, 1);
568 120675 : if (!oid_list) {
569 0 : return NULL;
570 : }
571 :
572 1199015 : for (i=0; ops && ops[i]; i++) {
573 1111365 : if (gensec_security != NULL &&
574 1078340 : !gensec_security_ops_enabled(ops[i], gensec_security)) {
575 106627 : continue;
576 : }
577 971713 : if (!ops[i]->oid) {
578 661818 : continue;
579 : }
580 :
581 696236 : for (k = 0; ops[i]->oid[k]; k++) {
582 386341 : if (skip && strcmp(skip, ops[i]->oid[k])==0) {
583 : } else {
584 265666 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
585 265666 : if (!oid_list) {
586 0 : return NULL;
587 : }
588 265666 : oid_list[j] = ops[i]->oid[k];
589 265666 : j++;
590 : }
591 : }
592 : }
593 120675 : oid_list[j] = NULL;
594 120675 : return oid_list;
595 : }
596 :
597 :
598 : /**
599 : * Return OIDS from the security subsystems listed
600 : */
601 :
602 83448 : _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
603 : const struct gensec_security_ops_wrapper *wops)
604 : {
605 1500 : int i;
606 83448 : int j = 0;
607 1500 : int k;
608 1500 : const char **oid_list;
609 83448 : if (!wops) {
610 0 : return NULL;
611 : }
612 83448 : oid_list = talloc_array(mem_ctx, const char *, 1);
613 83448 : if (!oid_list) {
614 0 : return NULL;
615 : }
616 :
617 204015 : for (i=0; wops[i].op; i++) {
618 120567 : if (!wops[i].op->oid) {
619 0 : continue;
620 : }
621 :
622 282234 : for (k = 0; wops[i].op->oid[k]; k++) {
623 161667 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
624 161667 : if (!oid_list) {
625 0 : return NULL;
626 : }
627 161667 : oid_list[j] = wops[i].op->oid[k];
628 161667 : j++;
629 : }
630 : }
631 83448 : oid_list[j] = NULL;
632 83448 : return oid_list;
633 : }
634 :
635 :
636 : /**
637 : * Return all the security subsystems currently enabled on a GENSEC context.
638 : *
639 : * This is taken from a list attached to the cli_credentials, and
640 : * skips the OID in 'skip'. (Typically the SPNEGO OID)
641 : *
642 : */
643 :
644 120675 : _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
645 : TALLOC_CTX *mem_ctx,
646 : const char *skip)
647 : {
648 2607 : const struct gensec_security_ops **ops;
649 :
650 120675 : ops = gensec_security_mechs(gensec_security, mem_ctx);
651 :
652 120675 : return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
653 : }
654 :
655 503332 : static int gensec_security_destructor(struct gensec_security *gctx)
656 : {
657 503332 : if (gctx->parent_security != NULL) {
658 169 : if (gctx->parent_security->child_security == gctx) {
659 169 : gctx->parent_security->child_security = NULL;
660 : }
661 169 : gctx->parent_security = NULL;
662 : }
663 :
664 503332 : if (gctx->child_security != NULL) {
665 128960 : if (gctx->child_security->parent_security == gctx) {
666 128960 : gctx->child_security->parent_security = NULL;
667 : }
668 128960 : gctx->child_security = NULL;
669 : }
670 :
671 503332 : return 0;
672 : }
673 :
674 : /**
675 : Start the GENSEC system, returning a context pointer.
676 : @param mem_ctx The parent TALLOC memory context.
677 : @param gensec_security Returned GENSEC context pointer.
678 : @note The mem_ctx is only a parent and may be NULL.
679 : @note, the auth context is moved to be a referenced pointer of the
680 : @ gensec_security return
681 : */
682 292256 : static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
683 : struct gensec_settings *settings,
684 : struct auth4_context *auth_context,
685 : struct gensec_security **gensec_security)
686 : {
687 292256 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
688 292256 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
689 :
690 292256 : (*gensec_security)->max_update_size = 0;
691 :
692 292256 : SMB_ASSERT(settings->lp_ctx != NULL);
693 292256 : (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
694 :
695 : /* We need to reference this, not steal, as the caller may be
696 : * python, which won't like it if we steal it's object away
697 : * from it */
698 292256 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
699 :
700 292256 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
701 292256 : return NT_STATUS_OK;
702 : }
703 :
704 : /**
705 : * Start a GENSEC subcontext, with a copy of the properties of the parent
706 : * @param mem_ctx The parent TALLOC memory context.
707 : * @param parent The parent GENSEC context
708 : * @param gensec_security Returned GENSEC context pointer.
709 : * @note Used by SPNEGO in particular, for the actual implementation mechanism
710 : */
711 :
712 212582 : _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
713 : struct gensec_security *parent,
714 : struct gensec_security **gensec_security)
715 : {
716 212582 : if (parent->child_security != NULL) {
717 0 : return NT_STATUS_INTERNAL_ERROR;
718 : }
719 :
720 212582 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
721 212582 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
722 :
723 212582 : (**gensec_security) = *parent;
724 212582 : (*gensec_security)->ops = NULL;
725 212582 : (*gensec_security)->private_data = NULL;
726 212582 : (*gensec_security)->update_busy_ptr = NULL;
727 :
728 212582 : (*gensec_security)->subcontext = true;
729 212582 : (*gensec_security)->want_features = parent->want_features;
730 212582 : (*gensec_security)->max_update_size = parent->max_update_size;
731 212582 : (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
732 212582 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
733 212582 : (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
734 212582 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
735 :
736 212582 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
737 212582 : return NT_STATUS_OK;
738 : }
739 :
740 129772 : _PUBLIC_ NTSTATUS gensec_child_ready(struct gensec_security *parent,
741 : struct gensec_security *child)
742 : {
743 129772 : if (parent->child_security != NULL) {
744 0 : return NT_STATUS_INTERNAL_ERROR;
745 : }
746 :
747 129772 : if (child->parent_security != NULL) {
748 0 : return NT_STATUS_INTERNAL_ERROR;
749 : }
750 :
751 129772 : parent->child_security = child;
752 129772 : child->parent_security = parent;
753 129772 : return NT_STATUS_OK;
754 : }
755 :
756 : /**
757 : Start the GENSEC system, in client mode, returning a context pointer.
758 : @param mem_ctx The parent TALLOC memory context.
759 : @param gensec_security Returned GENSEC context pointer.
760 : @note The mem_ctx is only a parent and may be NULL.
761 : */
762 115337 : _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
763 : struct gensec_security **gensec_security,
764 : struct gensec_settings *settings)
765 : {
766 1716 : NTSTATUS status;
767 :
768 115337 : if (settings == NULL) {
769 0 : DEBUG(0,("gensec_client_start: no settings given!\n"));
770 0 : return NT_STATUS_INTERNAL_ERROR;
771 : }
772 :
773 115337 : status = gensec_start(mem_ctx, settings, NULL, gensec_security);
774 115337 : if (!NT_STATUS_IS_OK(status)) {
775 0 : return status;
776 : }
777 115337 : (*gensec_security)->gensec_role = GENSEC_CLIENT;
778 :
779 115337 : return status;
780 : }
781 :
782 :
783 :
784 : /**
785 : Start the GENSEC system, in server mode, returning a context pointer.
786 : @param mem_ctx The parent TALLOC memory context.
787 : @param gensec_security Returned GENSEC context pointer.
788 : @note The mem_ctx is only a parent and may be NULL.
789 : */
790 176919 : _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
791 : struct gensec_settings *settings,
792 : struct auth4_context *auth_context,
793 : struct gensec_security **gensec_security)
794 : {
795 2877 : NTSTATUS status;
796 :
797 176919 : if (!settings) {
798 0 : DEBUG(0,("gensec_server_start: no settings given!\n"));
799 0 : return NT_STATUS_INTERNAL_ERROR;
800 : }
801 :
802 176919 : status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
803 176919 : if (!NT_STATUS_IS_OK(status)) {
804 0 : return status;
805 : }
806 176919 : (*gensec_security)->gensec_role = GENSEC_SERVER;
807 :
808 176919 : return status;
809 : }
810 :
811 409581 : static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
812 : {
813 7936 : NTSTATUS status;
814 :
815 : /*
816 : * Callers sometimes just reuse a context, we should
817 : * clear the internal state before starting it again.
818 : */
819 409581 : talloc_unlink(gensec_security, gensec_security->private_data);
820 409581 : gensec_security->private_data = NULL;
821 :
822 409581 : if (gensec_security->child_security != NULL) {
823 : /*
824 : * The talloc_unlink(.., gensec_security->private_data)
825 : * should have cleared this via
826 : * gensec_security_destructor().
827 : */
828 0 : return NT_STATUS_INTERNAL_ERROR;
829 : }
830 :
831 409581 : if (gensec_security->credentials) {
832 409579 : const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
833 409579 : if (forced_mech &&
834 0 : (gensec_security->ops->sasl_name == NULL ||
835 0 : strcasecmp(forced_mech, gensec_security->ops->sasl_name) != 0)) {
836 0 : DEBUG(5, ("GENSEC mechanism %s (%s) skipped, as it "
837 : "did not match forced mechanism %s\n",
838 : gensec_security->ops->name,
839 : gensec_security->ops->sasl_name,
840 : forced_mech));
841 0 : return NT_STATUS_INVALID_PARAMETER;
842 : }
843 : }
844 409581 : DEBUG(5, ("Starting GENSEC %smechanism %s\n",
845 : gensec_security->subcontext ? "sub" : "",
846 : gensec_security->ops->name));
847 409581 : switch (gensec_security->gensec_role) {
848 167337 : case GENSEC_CLIENT:
849 167337 : if (gensec_security->ops->client_start) {
850 167337 : status = gensec_security->ops->client_start(gensec_security);
851 167337 : if (!NT_STATUS_IS_OK(status)) {
852 23182 : DEBUG(gensec_security->subcontext?4:2, ("Failed to start GENSEC client mech %s: %s\n",
853 : gensec_security->ops->name, nt_errstr(status)));
854 : }
855 167337 : return status;
856 : }
857 0 : break;
858 242244 : case GENSEC_SERVER:
859 242244 : if (gensec_security->ops->server_start) {
860 242244 : status = gensec_security->ops->server_start(gensec_security);
861 242244 : if (!NT_STATUS_IS_OK(status)) {
862 10 : DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
863 : gensec_security->ops->name, nt_errstr(status)));
864 : }
865 242244 : return status;
866 : }
867 0 : break;
868 : }
869 0 : return NT_STATUS_INVALID_PARAMETER;
870 : }
871 :
872 : /**
873 : * Start a GENSEC sub-mechanism with a specified mechanism structure, used in SPNEGO
874 : *
875 : */
876 :
877 239113 : NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
878 : const struct gensec_security_ops *ops)
879 : {
880 239113 : gensec_security->ops = ops;
881 239113 : return gensec_start_mech(gensec_security);
882 : }
883 :
884 :
885 : /**
886 : * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
887 : * @param gensec_security GENSEC context pointer.
888 : * @param auth_type DCERPC auth type
889 : * @param auth_level DCERPC auth level
890 : */
891 :
892 18882 : _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
893 : uint8_t auth_type, uint8_t auth_level)
894 : {
895 18882 : gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
896 18882 : if (!gensec_security->ops) {
897 39 : DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
898 39 : return NT_STATUS_INVALID_PARAMETER;
899 : }
900 18843 : gensec_security->dcerpc_auth_level = auth_level;
901 : /*
902 : * We need to reset sign/seal in order to reset it.
903 : * We may got some default features inherited by the credentials
904 : */
905 18843 : gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
906 18843 : gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
907 18843 : gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
908 18843 : gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
909 18843 : if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
910 6482 : if (gensec_security->gensec_role == GENSEC_CLIENT) {
911 3313 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
912 : }
913 12361 : } else if (auth_level == DCERPC_AUTH_LEVEL_PACKET) {
914 : /*
915 : * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
916 : * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
917 : */
918 408 : if (gensec_security->gensec_role == GENSEC_CLIENT) {
919 255 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
920 : }
921 11953 : } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
922 10507 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
923 10507 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
924 1446 : } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
925 : /* Default features */
926 : } else {
927 3 : DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
928 : auth_level));
929 3 : return NT_STATUS_INVALID_PARAMETER;
930 : }
931 :
932 18840 : return gensec_start_mech(gensec_security);
933 : }
934 :
935 160 : _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
936 : {
937 0 : const struct gensec_security_ops *ops;
938 160 : ops = gensec_security_by_auth_type(gensec_security, authtype);
939 160 : if (ops) {
940 121 : return ops->name;
941 : }
942 39 : return NULL;
943 : }
944 :
945 :
946 76 : _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
947 : const char *oid_string)
948 : {
949 0 : const struct gensec_security_ops *ops;
950 76 : ops = gensec_security_by_oid(gensec_security, oid_string);
951 76 : if (ops) {
952 4 : return ops->name;
953 : }
954 72 : return oid_string;
955 : }
956 :
957 : /**
958 : * Start a GENSEC sub-mechanism by OID, used in SPNEGO
959 : *
960 : * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
961 : * well-known #define to hook it in.
962 : */
963 :
964 123587 : _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
965 : const char *mech_oid)
966 : {
967 123587 : SMB_ASSERT(gensec_security != NULL);
968 :
969 123587 : gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
970 123587 : if (!gensec_security->ops) {
971 72 : DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
972 72 : return NT_STATUS_INVALID_PARAMETER;
973 : }
974 123515 : return gensec_start_mech(gensec_security);
975 : }
976 :
977 : /**
978 : * Start a GENSEC sub-mechanism by a well known SASL name
979 : *
980 : */
981 :
982 26762 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
983 : const char *sasl_name)
984 : {
985 26762 : gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
986 26762 : if (!gensec_security->ops) {
987 2 : DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
988 2 : return NT_STATUS_INVALID_PARAMETER;
989 : }
990 26760 : return gensec_start_mech(gensec_security);
991 : }
992 :
993 : /**
994 : * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
995 : *
996 : */
997 :
998 26533 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
999 : const char **sasl_names)
1000 : {
1001 26533 : NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
1002 26533 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
1003 122 : const struct gensec_security_ops **ops;
1004 122 : int i;
1005 26533 : if (!mem_ctx) {
1006 0 : return NT_STATUS_NO_MEMORY;
1007 : }
1008 26533 : ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
1009 26533 : if (!ops || !*ops) {
1010 0 : DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
1011 : str_list_join(mem_ctx,
1012 : sasl_names, ' ')));
1013 0 : talloc_free(mem_ctx);
1014 0 : return NT_STATUS_INVALID_PARAMETER;
1015 : }
1016 26533 : for (i=0; ops[i]; i++) {
1017 26533 : nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
1018 26533 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
1019 26411 : break;
1020 : }
1021 : }
1022 26533 : talloc_free(mem_ctx);
1023 26533 : return nt_status;
1024 : }
1025 :
1026 : /**
1027 : * Start a GENSEC sub-mechanism by an internal name
1028 : *
1029 : */
1030 :
1031 1357 : _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
1032 : const char *name)
1033 : {
1034 1357 : gensec_security->ops = gensec_security_by_name(gensec_security, name);
1035 1357 : if (!gensec_security->ops) {
1036 4 : DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
1037 4 : return NT_STATUS_INVALID_PARAMETER;
1038 : }
1039 1353 : return gensec_start_mech(gensec_security);
1040 : }
1041 :
1042 : /**
1043 : * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
1044 : *
1045 : */
1046 :
1047 292670 : _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
1048 : {
1049 292670 : gensec_security->credentials = talloc_reference(gensec_security, credentials);
1050 292670 : NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1051 292670 : gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1052 292670 : return NT_STATUS_OK;
1053 : }
1054 :
1055 : /*
1056 : register a GENSEC backend.
1057 :
1058 : The 'name' can be later used by other backends to find the operations
1059 : structure for this backend.
1060 : */
1061 661792 : _PUBLIC_ NTSTATUS gensec_register(TALLOC_CTX *ctx,
1062 : const struct gensec_security_ops *ops)
1063 : {
1064 661792 : if (gensec_security_by_name(NULL, ops->name) != NULL) {
1065 : /* its already registered! */
1066 0 : DEBUG(0,("GENSEC backend '%s' already registered\n",
1067 : ops->name));
1068 0 : return NT_STATUS_OBJECT_NAME_COLLISION;
1069 : }
1070 :
1071 661792 : generic_security_ops = talloc_realloc(ctx,
1072 : generic_security_ops,
1073 : const struct gensec_security_ops *,
1074 : gensec_num_backends+2);
1075 661792 : if (!generic_security_ops) {
1076 0 : return NT_STATUS_NO_MEMORY;
1077 : }
1078 :
1079 661792 : generic_security_ops[gensec_num_backends] = ops;
1080 661792 : gensec_num_backends++;
1081 661792 : generic_security_ops[gensec_num_backends] = NULL;
1082 :
1083 661792 : DEBUG(3,("GENSEC backend '%s' registered\n",
1084 : ops->name));
1085 :
1086 661792 : return NT_STATUS_OK;
1087 : }
1088 :
1089 : /*
1090 : return the GENSEC interface version, and the size of some critical types
1091 : This can be used by backends to either detect compilation errors, or provide
1092 : multiple implementations for different smbd compilation options in one module
1093 : */
1094 0 : _PUBLIC_ const struct gensec_critical_sizes *gensec_interface_version(void)
1095 : {
1096 0 : static const struct gensec_critical_sizes critical_sizes = {
1097 : GENSEC_INTERFACE_VERSION,
1098 : sizeof(struct gensec_security_ops),
1099 : sizeof(struct gensec_security),
1100 : };
1101 :
1102 0 : return &critical_sizes;
1103 : }
1104 :
1105 1449121 : static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
1106 1449121 : return (*gs2)->priority - (*gs1)->priority;
1107 : }
1108 :
1109 180752 : int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1110 : {
1111 180752 : return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1112 : }
1113 :
1114 1563195 : bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1115 : {
1116 1563195 : return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1117 : }
1118 :
1119 : /*
1120 : initialise the GENSEC subsystem
1121 : */
1122 198010 : _PUBLIC_ NTSTATUS gensec_init(void)
1123 : {
1124 2693 : static bool initialized = false;
1125 : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
1126 : #ifdef STATIC_gensec_MODULES
1127 2693 : STATIC_gensec_MODULES_PROTO;
1128 198010 : init_module_fn static_init[] = { STATIC_gensec_MODULES };
1129 : #else
1130 : init_module_fn *static_init = NULL;
1131 : #endif
1132 2693 : init_module_fn *shared_init;
1133 :
1134 198010 : if (initialized) return NT_STATUS_OK;
1135 52089 : initialized = true;
1136 :
1137 52089 : shared_init = load_samba_modules(NULL, "gensec");
1138 :
1139 52089 : run_init_functions(NULL, static_init);
1140 52089 : run_init_functions(NULL, shared_init);
1141 :
1142 52089 : talloc_free(shared_init);
1143 :
1144 52089 : TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
1145 :
1146 52089 : return NT_STATUS_OK;
1147 : }
|