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 3839483 : bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security)
47 : {
48 3930997 : bool ok = lpcfg_parm_bool(security->settings->lp_ctx,
49 : NULL,
50 : "gensec",
51 3839483 : ops->name,
52 3839483 : ops->enabled);
53 :
54 4541996 : if (ops->weak_crypto &&
55 702513 : lpcfg_weak_crypto(security->settings->lp_ctx) != SAMBA_WEAK_CRYPTO_ALLOWED) {
56 0 : ok = false;
57 : }
58 :
59 3839483 : 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 1763198 : 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 18378512 : for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
92 : /* noop */
93 260862 : }
94 :
95 1763198 : new_gensec_list = talloc_array(mem_ctx,
96 : const struct gensec_security_ops *,
97 : num_mechs_in + 1);
98 1763198 : if (!new_gensec_list) {
99 0 : return NULL;
100 : }
101 :
102 1735505 : j = 0;
103 18378512 : for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
104 16615314 : bool keep = false;
105 :
106 : /*
107 : * We want to keep SPNEGO and other backends
108 : */
109 16615314 : keep = old_gensec_list[i]->glue;
110 :
111 16615314 : if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
112 1501099 : keep = keep_schannel;
113 : }
114 :
115 16615314 : switch (use_kerberos) {
116 14829336 : case CRED_USE_KERBEROS_DESIRED:
117 14829336 : keep = true;
118 14829336 : break;
119 :
120 1213410 : case CRED_USE_KERBEROS_DISABLED:
121 1213410 : if (old_gensec_list[i]->kerberos == false) {
122 889875 : keep = true;
123 : }
124 :
125 1201118 : break;
126 :
127 336136 : case CRED_USE_KERBEROS_REQUIRED:
128 336136 : if (old_gensec_list[i]->kerberos == true) {
129 113293 : keep = true;
130 : }
131 :
132 323998 : break;
133 0 : default:
134 : /* Can't happen or invalid parameter */
135 0 : return NULL;
136 : }
137 :
138 16366645 : if (!keep) {
139 484433 : continue;
140 : }
141 :
142 16130881 : new_gensec_list[j] = old_gensec_list[i];
143 16130881 : j++;
144 : }
145 1763198 : new_gensec_list[j] = NULL;
146 :
147 1763198 : return new_gensec_list;
148 : }
149 :
150 1763198 : _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
151 : struct gensec_security *gensec_security,
152 : TALLOC_CTX *mem_ctx)
153 : {
154 1763198 : const struct gensec_security_ops * const *backends =
155 : generic_security_ops;
156 1763198 : enum credentials_use_kerberos use_kerberos = CRED_USE_KERBEROS_DESIRED;
157 1763198 : bool keep_schannel = false;
158 :
159 1763198 : if (gensec_security != NULL) {
160 567830 : struct cli_credentials *creds = NULL;
161 :
162 567830 : creds = gensec_get_credentials(gensec_security);
163 567830 : if (creds != NULL) {
164 567826 : use_kerberos = cli_credentials_get_kerberos_state(creds);
165 567826 : if (cli_credentials_get_netlogon_creds(creds) != NULL) {
166 5627 : 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 567826 : if (gensec_security->gensec_role == GENSEC_SERVER) {
175 350689 : keep_schannel = true;
176 : }
177 : }
178 :
179 567830 : if (gensec_security->settings->backends) {
180 206631 : backends = gensec_security->settings->backends;
181 : }
182 : }
183 :
184 1763198 : return gensec_use_kerberos_mechs(mem_ctx, backends,
185 : use_kerberos, keep_schannel);
186 :
187 : }
188 :
189 362571 : _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 362571 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
197 362571 : if (!mem_ctx) {
198 0 : return NULL;
199 : }
200 362571 : backends = gensec_security_mechs(gensec_security, mem_ctx);
201 1120464 : for (i=0; backends && backends[i]; i++) {
202 1120334 : if (gensec_security != NULL &&
203 241817 : !gensec_security_ops_enabled(backends[i],
204 : gensec_security))
205 240 : continue;
206 1116884 : if (backends[i]->oid) {
207 1476357 : for (j=0; backends[i]->oid[j]; j++) {
208 1001246 : if (backends[i]->oid[j] &&
209 1001246 : (strcmp(backends[i]->oid[j], oid_string) == 0)) {
210 362427 : backend = backends[i];
211 362427 : talloc_free(mem_ctx);
212 362427 : return backend;
213 : }
214 : }
215 : }
216 : }
217 144 : talloc_free(mem_ctx);
218 :
219 144 : return NULL;
220 : }
221 :
222 26812 : _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 26812 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
230 26812 : if (!mem_ctx) {
231 0 : return NULL;
232 : }
233 26812 : backends = gensec_security_mechs(gensec_security, mem_ctx);
234 27732 : for (i=0; backends && backends[i]; i++) {
235 27730 : if (gensec_security != NULL &&
236 27608 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
237 260 : continue;
238 : }
239 27348 : if (backends[i]->sasl_name
240 27076 : && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
241 26810 : backend = backends[i];
242 26810 : talloc_free(mem_ctx);
243 26810 : return backend;
244 : }
245 : }
246 2 : talloc_free(mem_ctx);
247 :
248 2 : return NULL;
249 : }
250 :
251 254518 : _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 254518 : if (auth_type == DCERPC_AUTH_TYPE_NONE) {
261 0 : return NULL;
262 : }
263 :
264 254518 : mem_ctx = talloc_new(gensec_security);
265 254518 : if (!mem_ctx) {
266 0 : return NULL;
267 : }
268 254518 : backends = gensec_security_mechs(gensec_security, mem_ctx);
269 1689305 : for (i=0; backends && backends[i]; i++) {
270 1693171 : if (gensec_security != NULL &&
271 59474 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
272 11264 : continue;
273 : }
274 1677109 : if (backends[i]->auth_type == auth_type) {
275 254440 : backend = backends[i];
276 254440 : talloc_free(mem_ctx);
277 254440 : return backend;
278 : }
279 : }
280 78 : talloc_free(mem_ctx);
281 :
282 78 : return NULL;
283 : }
284 :
285 725273 : 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 725273 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
292 725273 : if (!mem_ctx) {
293 0 : return NULL;
294 : }
295 725273 : backends = gensec_security_mechs(gensec_security, mem_ctx);
296 5058788 : for (i=0; backends && backends[i]; i++) {
297 4377286 : if (gensec_security != NULL &&
298 6749 : !gensec_security_ops_enabled(backends[i], gensec_security))
299 1292 : continue;
300 4375994 : if (backends[i]->name
301 4375994 : && (strcmp(backends[i]->name, name) == 0)) {
302 60683 : backend = backends[i];
303 60683 : talloc_free(mem_ctx);
304 60683 : return backend;
305 : }
306 : }
307 664590 : talloc_free(mem_ctx);
308 664590 : return NULL;
309 : }
310 :
311 53623 : 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 53623 : const char **sasl_names = NULL;
317 53623 : size_t i, sasl_names_count = 0;
318 :
319 53623 : if (ops == NULL) {
320 0 : return NULL;
321 : }
322 :
323 53623 : sasl_names = talloc_array(mem_ctx, const char *, 1);
324 53623 : if (sasl_names == NULL) {
325 0 : return NULL;
326 : }
327 :
328 804345 : for (i = 0; ops[i] != NULL; i++) {
329 750722 : enum gensec_role role = GENSEC_SERVER;
330 750722 : const char **tmp = NULL;
331 :
332 750722 : if (ops[i]->sasl_name == NULL) {
333 482607 : continue;
334 : }
335 :
336 268115 : if (gensec_security != NULL) {
337 268115 : if (!gensec_security_ops_enabled(ops[i],
338 : gensec_security)) {
339 53623 : continue;
340 : }
341 :
342 214492 : role = gensec_security->gensec_role;
343 : }
344 :
345 214492 : switch (role) {
346 0 : case GENSEC_CLIENT:
347 0 : if (ops[i]->client_start == NULL) {
348 0 : continue;
349 : }
350 0 : break;
351 214492 : case GENSEC_SERVER:
352 214492 : if (ops[i]->server_start == NULL) {
353 53623 : continue;
354 : }
355 160137 : break;
356 : }
357 :
358 160869 : tmp = talloc_realloc(mem_ctx,
359 : sasl_names,
360 : const char *,
361 : sasl_names_count + 2);
362 160869 : if (tmp == NULL) {
363 0 : TALLOC_FREE(sasl_names);
364 0 : return NULL;
365 : }
366 160869 : sasl_names = tmp;
367 :
368 160869 : sasl_names[sasl_names_count] = ops[i]->sasl_name;
369 160869 : sasl_names_count++;
370 : }
371 53623 : sasl_names[sasl_names_count] = NULL;
372 :
373 53623 : 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 53623 : const char **gensec_security_sasl_names(struct gensec_security *gensec_security,
387 : TALLOC_CTX *mem_ctx)
388 : {
389 53623 : const struct gensec_security_ops **ops = NULL;
390 :
391 53623 : ops = gensec_security_mechs(gensec_security, mem_ctx);
392 :
393 53623 : 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 26541 : 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 26541 : int num_backends_out = 0;
415 :
416 26541 : if (!sasl_names) {
417 0 : return NULL;
418 : }
419 :
420 26541 : backends = gensec_security_mechs(gensec_security, mem_ctx);
421 :
422 26541 : backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
423 26541 : if (!backends_out) {
424 0 : return NULL;
425 : }
426 26541 : backends_out[0] = NULL;
427 :
428 : /* Find backends in our preferred order, by walking our list,
429 : * then looking in the supplied list */
430 335084 : for (i=0; backends && backends[i]; i++) {
431 310251 : if (gensec_security != NULL &&
432 308543 : !gensec_security_ops_enabled(backends[i], gensec_security))
433 35644 : continue;
434 1090346 : for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
435 817447 : if (!backends[i]->sasl_name ||
436 275052 : !(strcmp(backends[i]->sasl_name,
437 273588 : sasl_names[sasl_idx]) == 0)) {
438 749320 : continue;
439 : }
440 :
441 125069 : for (k=0; backends_out[k]; k++) {
442 56942 : if (backends_out[k] == backends[i]) {
443 0 : break;
444 : }
445 : }
446 :
447 68127 : if (k < num_backends_out) {
448 : /* already in there */
449 0 : continue;
450 : }
451 :
452 68127 : backends_out = talloc_realloc(mem_ctx, backends_out,
453 : const struct gensec_security_ops *,
454 : num_backends_out + 2);
455 68127 : if (!backends_out) {
456 0 : return NULL;
457 : }
458 :
459 68127 : backends_out[num_backends_out] = backends[i];
460 68127 : num_backends_out++;
461 68127 : backends_out[num_backends_out] = NULL;
462 : }
463 : }
464 26419 : 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 191382 : _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 191382 : int num_backends_out = 0;
486 :
487 191382 : if (!oid_strings) {
488 0 : return NULL;
489 : }
490 :
491 191382 : backends = gensec_security_mechs(gensec_security, gensec_security);
492 :
493 191382 : backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
494 191382 : if (!backends_out) {
495 0 : return NULL;
496 : }
497 191382 : backends_out[0].op = NULL;
498 191382 : 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 2018884 : for (i=0; backends && backends[i]; i++) {
503 1874933 : if (gensec_security != NULL &&
504 1827502 : !gensec_security_ops_enabled(backends[i], gensec_security))
505 199055 : continue;
506 1628447 : if (!backends[i]->oid) {
507 1128916 : continue;
508 : }
509 1606345 : for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
510 1106814 : if (strcmp(oid_strings[oid_idx], skip) == 0) {
511 0 : continue;
512 : }
513 :
514 2543399 : for (j=0; backends[i]->oid[j]; j++) {
515 1464233 : if (!backends[i]->oid[j] ||
516 1436585 : !(strcmp(backends[i]->oid[j],
517 1399335 : oid_strings[oid_idx]) == 0)) {
518 1040144 : continue;
519 : }
520 :
521 491515 : for (k=0; backends_out[k].op; k++) {
522 205062 : if (backends_out[k].op == backends[i]) {
523 106790 : break;
524 : }
525 : }
526 :
527 396441 : if (k < num_backends_out) {
528 : /* already in there */
529 109988 : continue;
530 : }
531 :
532 286453 : backends_out = talloc_realloc(mem_ctx, backends_out,
533 : struct gensec_security_ops_wrapper,
534 : num_backends_out + 2);
535 286453 : if (!backends_out) {
536 0 : return NULL;
537 : }
538 :
539 286453 : backends_out[num_backends_out].op = backends[i];
540 286453 : backends_out[num_backends_out].oid = backends[i]->oid[j];
541 286453 : num_backends_out++;
542 286453 : backends_out[num_backends_out].op = NULL;
543 286453 : backends_out[num_backends_out].oid = NULL;
544 : }
545 : }
546 : }
547 187746 : return backends_out;
548 : }
549 :
550 : /**
551 : * Return OIDS from the security subsystems listed
552 : */
553 :
554 122331 : 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 122331 : int j = 0;
562 2607 : int k;
563 2607 : const char **oid_list;
564 122331 : if (!ops) {
565 0 : return NULL;
566 : }
567 122331 : oid_list = talloc_array(mem_ctx, const char *, 1);
568 122331 : if (!oid_list) {
569 0 : return NULL;
570 : }
571 :
572 1221661 : for (i=0; ops && ops[i]; i++) {
573 1132355 : if (gensec_security != NULL &&
574 1099330 : !gensec_security_ops_enabled(ops[i], gensec_security)) {
575 108959 : continue;
576 : }
577 990371 : if (!ops[i]->oid) {
578 675650 : continue;
579 : }
580 :
581 707410 : for (k = 0; ops[i]->oid[k]; k++) {
582 392689 : if (skip && strcmp(skip, ops[i]->oid[k])==0) {
583 : } else {
584 270358 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
585 270358 : if (!oid_list) {
586 0 : return NULL;
587 : }
588 270358 : oid_list[j] = ops[i]->oid[k];
589 270358 : j++;
590 : }
591 : }
592 : }
593 122331 : oid_list[j] = NULL;
594 122331 : return oid_list;
595 : }
596 :
597 :
598 : /**
599 : * Return OIDS from the security subsystems listed
600 : */
601 :
602 83825 : _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 83825 : int j = 0;
607 1500 : int k;
608 1500 : const char **oid_list;
609 83825 : if (!wops) {
610 0 : return NULL;
611 : }
612 83825 : oid_list = talloc_array(mem_ctx, const char *, 1);
613 83825 : if (!oid_list) {
614 0 : return NULL;
615 : }
616 :
617 205132 : for (i=0; wops[i].op; i++) {
618 121307 : if (!wops[i].op->oid) {
619 0 : continue;
620 : }
621 :
622 284083 : for (k = 0; wops[i].op->oid[k]; k++) {
623 162776 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
624 162776 : if (!oid_list) {
625 0 : return NULL;
626 : }
627 162776 : oid_list[j] = wops[i].op->oid[k];
628 162776 : j++;
629 : }
630 : }
631 83825 : oid_list[j] = NULL;
632 83825 : 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 122331 : _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 122331 : ops = gensec_security_mechs(gensec_security, mem_ctx);
651 :
652 122331 : return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
653 : }
654 :
655 510610 : static int gensec_security_destructor(struct gensec_security *gctx)
656 : {
657 510610 : 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 510610 : if (gctx->child_security != NULL) {
665 129384 : if (gctx->child_security->parent_security == gctx) {
666 129384 : gctx->child_security->parent_security = NULL;
667 : }
668 129384 : gctx->child_security = NULL;
669 : }
670 :
671 510610 : 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 295459 : 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 295459 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
688 295459 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
689 :
690 295459 : (*gensec_security)->max_update_size = 0;
691 :
692 295459 : SMB_ASSERT(settings->lp_ctx != NULL);
693 295459 : (*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 295459 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
699 :
700 295459 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
701 295459 : 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 216662 : _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
713 : struct gensec_security *parent,
714 : struct gensec_security **gensec_security)
715 : {
716 216662 : if (parent->child_security != NULL) {
717 0 : return NT_STATUS_INTERNAL_ERROR;
718 : }
719 :
720 216662 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
721 216662 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
722 :
723 216662 : (**gensec_security) = *parent;
724 216662 : (*gensec_security)->ops = NULL;
725 216662 : (*gensec_security)->private_data = NULL;
726 216662 : (*gensec_security)->update_busy_ptr = NULL;
727 :
728 216662 : (*gensec_security)->subcontext = true;
729 216662 : (*gensec_security)->want_features = parent->want_features;
730 216662 : (*gensec_security)->max_update_size = parent->max_update_size;
731 216662 : (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
732 216662 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
733 216662 : (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
734 216662 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
735 :
736 216662 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
737 216662 : return NT_STATUS_OK;
738 : }
739 :
740 130198 : _PUBLIC_ NTSTATUS gensec_child_ready(struct gensec_security *parent,
741 : struct gensec_security *child)
742 : {
743 130198 : if (parent->child_security != NULL) {
744 0 : return NT_STATUS_INTERNAL_ERROR;
745 : }
746 :
747 130198 : if (child->parent_security != NULL) {
748 0 : return NT_STATUS_INTERNAL_ERROR;
749 : }
750 :
751 130198 : parent->child_security = child;
752 130198 : child->parent_security = parent;
753 130198 : 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 116700 : _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 116700 : if (settings == NULL) {
769 0 : DEBUG(0,("gensec_client_start: no settings given!\n"));
770 0 : return NT_STATUS_INTERNAL_ERROR;
771 : }
772 :
773 116700 : status = gensec_start(mem_ctx, settings, NULL, gensec_security);
774 116700 : if (!NT_STATUS_IS_OK(status)) {
775 0 : return status;
776 : }
777 116700 : (*gensec_security)->gensec_role = GENSEC_CLIENT;
778 :
779 116700 : 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 178759 : _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 178759 : if (!settings) {
798 0 : DEBUG(0,("gensec_server_start: no settings given!\n"));
799 0 : return NT_STATUS_INTERNAL_ERROR;
800 : }
801 :
802 178759 : status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
803 178759 : if (!NT_STATUS_IS_OK(status)) {
804 0 : return status;
805 : }
806 178759 : (*gensec_security)->gensec_role = GENSEC_SERVER;
807 :
808 178759 : return status;
809 : }
810 :
811 416769 : 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 416769 : talloc_unlink(gensec_security, gensec_security->private_data);
820 416769 : gensec_security->private_data = NULL;
821 :
822 416769 : 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 416769 : if (gensec_security->credentials) {
832 416767 : const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
833 416767 : 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 416769 : DEBUG(5, ("Starting GENSEC %smechanism %s\n",
845 : gensec_security->subcontext ? "sub" : "",
846 : gensec_security->ops->name));
847 416769 : switch (gensec_security->gensec_role) {
848 171088 : case GENSEC_CLIENT:
849 171088 : if (gensec_security->ops->client_start) {
850 171088 : status = gensec_security->ops->client_start(gensec_security);
851 171088 : if (!NT_STATUS_IS_OK(status)) {
852 23890 : 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 171088 : return status;
856 : }
857 0 : break;
858 245681 : case GENSEC_SERVER:
859 245681 : if (gensec_security->ops->server_start) {
860 245681 : status = gensec_security->ops->server_start(gensec_security);
861 245681 : 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 245681 : 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 243201 : NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
878 : const struct gensec_security_ops *ops)
879 : {
880 243201 : gensec_security->ops = ops;
881 243201 : 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 18992 : _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
893 : uint8_t auth_type, uint8_t auth_level)
894 : {
895 18992 : gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
896 18992 : 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 18953 : 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 18953 : gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
906 18953 : gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
907 18953 : gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
908 18953 : gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
909 18953 : if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
910 6473 : if (gensec_security->gensec_role == GENSEC_CLIENT) {
911 3313 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
912 : }
913 12480 : } 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 12072 : } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
922 10626 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
923 10626 : 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 18950 : 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 126509 : _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
965 : const char *mech_oid)
966 : {
967 126509 : SMB_ASSERT(gensec_security != NULL);
968 :
969 126509 : gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
970 126509 : 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 126437 : 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 26812 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
983 : const char *sasl_name)
984 : {
985 26812 : gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
986 26812 : 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 26810 : 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 26541 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
999 : const char **sasl_names)
1000 : {
1001 26541 : NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
1002 26541 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
1003 122 : const struct gensec_security_ops **ops;
1004 122 : int i;
1005 26541 : if (!mem_ctx) {
1006 0 : return NT_STATUS_NO_MEMORY;
1007 : }
1008 26541 : ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
1009 26541 : 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 26541 : for (i=0; ops[i]; i++) {
1017 26541 : nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
1018 26541 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
1019 26419 : break;
1020 : }
1021 : }
1022 26541 : talloc_free(mem_ctx);
1023 26541 : return nt_status;
1024 : }
1025 :
1026 : /**
1027 : * Start a GENSEC sub-mechanism by an internal name
1028 : *
1029 : */
1030 :
1031 1375 : _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
1032 : const char *name)
1033 : {
1034 1375 : gensec_security->ops = gensec_security_by_name(gensec_security, name);
1035 1375 : 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 1371 : 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 295873 : _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
1048 : {
1049 295873 : gensec_security->credentials = talloc_reference(gensec_security, credentials);
1050 295873 : NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1051 295873 : gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1052 295873 : 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 664586 : _PUBLIC_ NTSTATUS gensec_register(TALLOC_CTX *ctx,
1062 : const struct gensec_security_ops *ops)
1063 : {
1064 664586 : 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 664586 : generic_security_ops = talloc_realloc(ctx,
1072 : generic_security_ops,
1073 : const struct gensec_security_ops *,
1074 : gensec_num_backends+2);
1075 664586 : if (!generic_security_ops) {
1076 0 : return NT_STATUS_NO_MEMORY;
1077 : }
1078 :
1079 664586 : generic_security_ops[gensec_num_backends] = ops;
1080 664586 : gensec_num_backends++;
1081 664586 : generic_security_ops[gensec_num_backends] = NULL;
1082 :
1083 664586 : DEBUG(3,("GENSEC backend '%s' registered\n",
1084 : ops->name));
1085 :
1086 664586 : 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 1455651 : static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
1106 1455651 : return (*gs2)->priority - (*gs1)->priority;
1107 : }
1108 :
1109 182206 : int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1110 : {
1111 182206 : return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1112 : }
1113 :
1114 1594367 : bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1115 : {
1116 1594367 : return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1117 : }
1118 :
1119 : /*
1120 : initialise the GENSEC subsystem
1121 : */
1122 199656 : _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 199656 : 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 199656 : if (initialized) return NT_STATUS_OK;
1135 52291 : initialized = true;
1136 :
1137 52291 : shared_init = load_samba_modules(NULL, "gensec");
1138 :
1139 52291 : run_init_functions(NULL, static_init);
1140 52291 : run_init_functions(NULL, shared_init);
1141 :
1142 52291 : talloc_free(shared_init);
1143 :
1144 52291 : TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
1145 :
1146 52291 : return NT_STATUS_OK;
1147 : }
|