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 1937650 : bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct gensec_security *security)
47 : {
48 1937650 : bool ok = lpcfg_parm_bool(security->settings->lp_ctx,
49 : NULL,
50 : "gensec",
51 428795 : ops->name,
52 1937650 : ops->enabled);
53 :
54 2227750 : if (ops->weak_crypto &&
55 290100 : lpcfg_weak_crypto(security->settings->lp_ctx) != SAMBA_WEAK_CRYPTO_ALLOWED) {
56 0 : ok = false;
57 : }
58 :
59 1937650 : 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 compplex.
80 : */
81 :
82 418402 : 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 : const struct gensec_security_ops **new_gensec_list;
89 : int i, j, num_mechs_in;
90 :
91 1593703 : for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
92 : /* noop */
93 : }
94 :
95 418402 : new_gensec_list = talloc_array(mem_ctx,
96 : const struct gensec_security_ops *,
97 : num_mechs_in + 1);
98 418402 : if (!new_gensec_list) {
99 0 : return NULL;
100 : }
101 :
102 418402 : j = 0;
103 5024180 : for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
104 4605778 : bool keep = false;
105 :
106 : /*
107 : * We want to keep SPNGEO and other backends
108 : */
109 4605778 : keep = old_gensec_list[i]->glue;
110 :
111 4605778 : if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
112 365425 : keep = keep_schannel;
113 : }
114 :
115 4605778 : switch (use_kerberos) {
116 3991857 : case CRED_USE_KERBEROS_DESIRED:
117 3991857 : keep = true;
118 3991857 : break;
119 :
120 328347 : case CRED_USE_KERBEROS_DISABLED:
121 328347 : if (old_gensec_list[i]->kerberos == false) {
122 212495 : keep = true;
123 : }
124 :
125 328347 : break;
126 :
127 285574 : case CRED_USE_KERBEROS_REQUIRED:
128 285574 : if (old_gensec_list[i]->kerberos == true) {
129 100905 : keep = true;
130 : }
131 :
132 285574 : break;
133 0 : default:
134 : /* Can't happen or invalid parameter */
135 0 : return NULL;
136 : }
137 :
138 4605778 : if (!keep) {
139 258381 : continue;
140 : }
141 :
142 4347397 : new_gensec_list[j] = old_gensec_list[i];
143 4347397 : j++;
144 : }
145 418402 : new_gensec_list[j] = NULL;
146 :
147 418402 : return new_gensec_list;
148 : }
149 :
150 418402 : _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs(
151 : struct gensec_security *gensec_security,
152 : TALLOC_CTX *mem_ctx)
153 : {
154 418402 : const struct gensec_security_ops * const *backends =
155 : generic_security_ops;
156 418402 : enum credentials_use_kerberos use_kerberos = CRED_USE_KERBEROS_DESIRED;
157 418402 : bool keep_schannel = false;
158 :
159 418402 : if (gensec_security != NULL) {
160 240154 : struct cli_credentials *creds = NULL;
161 :
162 240154 : creds = gensec_get_credentials(gensec_security);
163 240154 : if (creds != NULL) {
164 240152 : use_kerberos = cli_credentials_get_kerberos_state(creds);
165 240152 : if (cli_credentials_get_netlogon_creds(creds) != NULL) {
166 2141 : keep_schannel = true;
167 : }
168 :
169 : /*
170 : * Even if Kerberos is set to REQUIRED, keep the
171 : * schannel auth mechanism that machine accounts are
172 : * able to authenticate via netlogon.
173 : */
174 240152 : if (gensec_security->gensec_role == GENSEC_SERVER) {
175 140211 : keep_schannel = true;
176 : }
177 : }
178 :
179 240154 : if (gensec_security->settings->backends) {
180 17393 : backends = gensec_security->settings->backends;
181 : }
182 : }
183 :
184 418402 : return gensec_use_kerberos_mechs(mem_ctx, backends,
185 : use_kerberos, keep_schannel);
186 :
187 : }
188 :
189 41684 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_oid(
190 : struct gensec_security *gensec_security,
191 : const char *oid_string)
192 : {
193 : int i, j;
194 : const struct gensec_security_ops **backends;
195 : const struct gensec_security_ops *backend;
196 41684 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
197 41684 : if (!mem_ctx) {
198 0 : return NULL;
199 : }
200 41684 : backends = gensec_security_mechs(gensec_security, mem_ctx);
201 105142 : for (i=0; backends && backends[i]; i++) {
202 133767 : if (gensec_security != NULL &&
203 40845 : !gensec_security_ops_enabled(backends[i],
204 : gensec_security))
205 85 : continue;
206 105009 : if (backends[i]->oid) {
207 141122 : for (j=0; backends[i]->oid[j]; j++) {
208 164744 : if (backends[i]->oid[j] &&
209 101275 : (strcmp(backends[i]->oid[j], oid_string) == 0)) {
210 41636 : backend = backends[i];
211 41636 : talloc_free(mem_ctx);
212 41636 : return backend;
213 : }
214 : }
215 : }
216 : }
217 48 : talloc_free(mem_ctx);
218 :
219 48 : return NULL;
220 : }
221 :
222 19575 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_sasl_name(
223 : struct gensec_security *gensec_security,
224 : const char *sasl_name)
225 : {
226 : int i;
227 : const struct gensec_security_ops **backends;
228 : const struct gensec_security_ops *backend;
229 19575 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
230 19575 : if (!mem_ctx) {
231 0 : return NULL;
232 : }
233 19575 : backends = gensec_security_mechs(gensec_security, mem_ctx);
234 20565 : for (i=0; backends && backends[i]; i++) {
235 36423 : if (gensec_security != NULL &&
236 20565 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
237 330 : continue;
238 : }
239 20235 : if (backends[i]->sasl_name
240 19905 : && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
241 19575 : backend = backends[i];
242 19575 : talloc_free(mem_ctx);
243 19575 : return backend;
244 : }
245 : }
246 0 : talloc_free(mem_ctx);
247 :
248 0 : return NULL;
249 : }
250 :
251 28158 : _PUBLIC_ const struct gensec_security_ops *gensec_security_by_auth_type(
252 : struct gensec_security *gensec_security,
253 : uint32_t auth_type)
254 : {
255 : int i;
256 : const struct gensec_security_ops **backends;
257 : const struct gensec_security_ops *backend;
258 : TALLOC_CTX *mem_ctx;
259 :
260 28158 : if (auth_type == DCERPC_AUTH_TYPE_NONE) {
261 0 : return NULL;
262 : }
263 :
264 28158 : mem_ctx = talloc_new(gensec_security);
265 28158 : if (!mem_ctx) {
266 0 : return NULL;
267 : }
268 28158 : backends = gensec_security_mechs(gensec_security, mem_ctx);
269 153805 : for (i=0; backends && backends[i]; i++) {
270 183499 : if (gensec_security != NULL &&
271 35678 : !gensec_security_ops_enabled(backends[i], gensec_security)) {
272 5862 : continue;
273 : }
274 147897 : if (backends[i]->auth_type == auth_type) {
275 28112 : backend = backends[i];
276 28112 : talloc_free(mem_ctx);
277 28112 : return backend;
278 : }
279 : }
280 46 : talloc_free(mem_ctx);
281 :
282 46 : return NULL;
283 : }
284 :
285 150895 : const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
286 : const char *name)
287 : {
288 : int i;
289 : const struct gensec_security_ops **backends;
290 : const struct gensec_security_ops *backend;
291 150895 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
292 150895 : if (!mem_ctx) {
293 0 : return NULL;
294 : }
295 150895 : backends = gensec_security_mechs(gensec_security, mem_ctx);
296 1132207 : for (i=0; backends && backends[i]; i++) {
297 991783 : if (gensec_security != NULL &&
298 6047 : !gensec_security_ops_enabled(backends[i], gensec_security))
299 1199 : continue;
300 984597 : if (backends[i]->name
301 984597 : && (strcmp(backends[i]->name, name) == 0)) {
302 4484 : backend = backends[i];
303 4484 : talloc_free(mem_ctx);
304 4484 : return backend;
305 : }
306 : }
307 146411 : talloc_free(mem_ctx);
308 146411 : return NULL;
309 : }
310 :
311 38936 : 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 38936 : const char **sasl_names = NULL;
317 38936 : size_t i, sasl_names_count = 0;
318 :
319 38936 : if (ops == NULL) {
320 0 : return NULL;
321 : }
322 :
323 38936 : sasl_names = talloc_array(mem_ctx, const char *, 1);
324 38936 : if (sasl_names == NULL) {
325 0 : return NULL;
326 : }
327 :
328 584040 : for (i = 0; ops[i] != NULL; i++) {
329 545104 : enum gensec_role role = GENSEC_SERVER;
330 545104 : const char **tmp = NULL;
331 :
332 545104 : if (ops[i]->sasl_name == NULL) {
333 350424 : continue;
334 : }
335 :
336 194680 : if (gensec_security != NULL) {
337 194680 : if (!gensec_security_ops_enabled(ops[i],
338 : gensec_security)) {
339 38936 : continue;
340 : }
341 :
342 155744 : role = gensec_security->gensec_role;
343 : }
344 :
345 155744 : switch (role) {
346 0 : case GENSEC_CLIENT:
347 0 : if (ops[i]->client_start == NULL) {
348 0 : continue;
349 : }
350 0 : break;
351 155744 : case GENSEC_SERVER:
352 155744 : if (ops[i]->server_start == NULL) {
353 38936 : continue;
354 : }
355 116808 : break;
356 : }
357 :
358 116808 : tmp = talloc_realloc(mem_ctx,
359 : sasl_names,
360 : const char *,
361 : sasl_names_count + 2);
362 116808 : if (tmp == NULL) {
363 0 : TALLOC_FREE(sasl_names);
364 0 : return NULL;
365 : }
366 116808 : sasl_names = tmp;
367 :
368 116808 : sasl_names[sasl_names_count] = ops[i]->sasl_name;
369 116808 : sasl_names_count++;
370 : }
371 38936 : sasl_names[sasl_names_count] = NULL;
372 :
373 38936 : 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 38936 : const char **gensec_security_sasl_names(struct gensec_security *gensec_security,
387 : TALLOC_CTX *mem_ctx)
388 : {
389 38936 : const struct gensec_security_ops **ops = NULL;
390 :
391 38936 : ops = gensec_security_mechs(gensec_security, mem_ctx);
392 :
393 38936 : 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 19365 : 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 : const struct gensec_security_ops **backends_out;
412 : const struct gensec_security_ops **backends;
413 : int i, k, sasl_idx;
414 19365 : int num_backends_out = 0;
415 :
416 19365 : if (!sasl_names) {
417 0 : return NULL;
418 : }
419 :
420 19365 : backends = gensec_security_mechs(gensec_security, mem_ctx);
421 :
422 19365 : backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
423 19365 : if (!backends_out) {
424 0 : return NULL;
425 : }
426 19365 : backends_out[0] = NULL;
427 :
428 : /* Find backends in our preferred order, by walking our list,
429 : * then looking in the supplied list */
430 241427 : for (i=0; backends && backends[i]; i++) {
431 390629 : if (gensec_security != NULL &&
432 222062 : !gensec_security_ops_enabled(backends[i], gensec_security))
433 26076 : continue;
434 783598 : for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
435 737575 : if (!backends[i]->sasl_name ||
436 198302 : !(strcmp(backends[i]->sasl_name,
437 198302 : sasl_names[sasl_idx]) == 0)) {
438 538332 : continue;
439 : }
440 :
441 89830 : for (k=0; backends_out[k]; k++) {
442 40550 : if (backends_out[k] == backends[i]) {
443 0 : break;
444 : }
445 : }
446 :
447 49280 : if (k < num_backends_out) {
448 : /* already in there */
449 0 : continue;
450 : }
451 :
452 49280 : backends_out = talloc_realloc(mem_ctx, backends_out,
453 : const struct gensec_security_ops *,
454 : num_backends_out + 2);
455 49280 : if (!backends_out) {
456 0 : return NULL;
457 : }
458 :
459 49280 : backends_out[num_backends_out] = backends[i];
460 49280 : num_backends_out++;
461 49280 : backends_out[num_backends_out] = NULL;
462 : }
463 : }
464 19365 : 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 75873 : _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 : struct gensec_security_ops_wrapper *backends_out;
483 : const struct gensec_security_ops **backends;
484 : int i, j, k, oid_idx;
485 75873 : int num_backends_out = 0;
486 :
487 75873 : if (!oid_strings) {
488 0 : return NULL;
489 : }
490 :
491 75873 : backends = gensec_security_mechs(gensec_security, gensec_security);
492 :
493 75873 : backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
494 75873 : if (!backends_out) {
495 0 : return NULL;
496 : }
497 75873 : backends_out[0].op = NULL;
498 75873 : 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 1003201 : for (i=0; backends && backends[i]; i++) {
503 1654978 : if (gensec_security != NULL &&
504 927328 : !gensec_security_ops_enabled(backends[i], gensec_security))
505 124769 : continue;
506 802559 : if (!backends[i]->oid) {
507 589433 : continue;
508 : }
509 730097 : for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
510 516971 : if (strcmp(oid_strings[oid_idx], skip) == 0) {
511 0 : continue;
512 : }
513 :
514 1205357 : for (j=0; backends[i]->oid[j]; j++) {
515 1227306 : if (!backends[i]->oid[j] ||
516 688386 : !(strcmp(backends[i]->oid[j],
517 688386 : oid_strings[oid_idx]) == 0)) {
518 509050 : continue;
519 : }
520 :
521 224740 : for (k=0; backends_out[k].op; k++) {
522 103465 : if (backends_out[k].op == backends[i]) {
523 58061 : break;
524 : }
525 : }
526 :
527 179336 : if (k < num_backends_out) {
528 : /* already in there */
529 58061 : continue;
530 : }
531 :
532 121275 : backends_out = talloc_realloc(mem_ctx, backends_out,
533 : struct gensec_security_ops_wrapper,
534 : num_backends_out + 2);
535 121275 : if (!backends_out) {
536 0 : return NULL;
537 : }
538 :
539 121275 : backends_out[num_backends_out].op = backends[i];
540 121275 : backends_out[num_backends_out].oid = backends[i]->oid[j];
541 121275 : num_backends_out++;
542 121275 : backends_out[num_backends_out].op = NULL;
543 121275 : backends_out[num_backends_out].oid = NULL;
544 : }
545 : }
546 : }
547 75873 : return backends_out;
548 : }
549 :
550 : /**
551 : * Return OIDS from the security subsystems listed
552 : */
553 :
554 43693 : 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 : int i;
561 43693 : int j = 0;
562 : int k;
563 : const char **oid_list;
564 43693 : if (!ops) {
565 0 : return NULL;
566 : }
567 43693 : oid_list = talloc_array(mem_ctx, const char *, 1);
568 43693 : if (!oid_list) {
569 0 : return NULL;
570 : }
571 :
572 533730 : for (i=0; ops && ops[i]; i++) {
573 873510 : if (gensec_security != NULL &&
574 490037 : !gensec_security_ops_enabled(ops[i], gensec_security)) {
575 63309 : continue;
576 : }
577 426728 : if (!ops[i]->oid) {
578 310049 : continue;
579 : }
580 :
581 269203 : for (k = 0; ops[i]->oid[k]; k++) {
582 152524 : if (skip && strcmp(skip, ops[i]->oid[k])==0) {
583 : } else {
584 108831 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
585 108831 : if (!oid_list) {
586 0 : return NULL;
587 : }
588 108831 : oid_list[j] = ops[i]->oid[k];
589 108831 : j++;
590 : }
591 : }
592 : }
593 43693 : oid_list[j] = NULL;
594 43693 : return oid_list;
595 : }
596 :
597 :
598 : /**
599 : * Return OIDS from the security subsystems listed
600 : */
601 :
602 35573 : _PUBLIC_ const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
603 : const struct gensec_security_ops_wrapper *wops)
604 : {
605 : int i;
606 35573 : int j = 0;
607 : int k;
608 : const char **oid_list;
609 35573 : if (!wops) {
610 0 : return NULL;
611 : }
612 35573 : oid_list = talloc_array(mem_ctx, const char *, 1);
613 35573 : if (!oid_list) {
614 0 : return NULL;
615 : }
616 :
617 94852 : for (i=0; wops[i].op; i++) {
618 59279 : if (!wops[i].op->oid) {
619 0 : continue;
620 : }
621 :
622 145958 : for (k = 0; wops[i].op->oid[k]; k++) {
623 86679 : oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
624 86679 : if (!oid_list) {
625 0 : return NULL;
626 : }
627 86679 : oid_list[j] = wops[i].op->oid[k];
628 86679 : j++;
629 : }
630 : }
631 35573 : oid_list[j] = NULL;
632 35573 : 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 43693 : _PUBLIC_ const char **gensec_security_oids(struct gensec_security *gensec_security,
645 : TALLOC_CTX *mem_ctx,
646 : const char *skip)
647 : {
648 : const struct gensec_security_ops **ops;
649 :
650 43693 : ops = gensec_security_mechs(gensec_security, mem_ctx);
651 :
652 43693 : return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
653 : }
654 :
655 199214 : static int gensec_security_destructor(struct gensec_security *gctx)
656 : {
657 199214 : if (gctx->parent_security != NULL) {
658 32 : if (gctx->parent_security->child_security == gctx) {
659 32 : gctx->parent_security->child_security = NULL;
660 : }
661 32 : gctx->parent_security = NULL;
662 : }
663 :
664 199214 : if (gctx->child_security != NULL) {
665 63237 : if (gctx->child_security->parent_security == gctx) {
666 63237 : gctx->child_security->parent_security = NULL;
667 : }
668 63237 : gctx->child_security = NULL;
669 : }
670 :
671 199214 : 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 121138 : 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 121138 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
688 121138 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
689 :
690 121138 : (*gensec_security)->max_update_size = 0;
691 :
692 121138 : SMB_ASSERT(settings->lp_ctx != NULL);
693 121138 : (*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 121138 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
699 :
700 121138 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
701 121138 : 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 78269 : _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
713 : struct gensec_security *parent,
714 : struct gensec_security **gensec_security)
715 : {
716 78269 : if (parent->child_security != NULL) {
717 0 : return NT_STATUS_INTERNAL_ERROR;
718 : }
719 :
720 78269 : (*gensec_security) = talloc_zero(mem_ctx, struct gensec_security);
721 78269 : NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
722 :
723 78269 : (**gensec_security) = *parent;
724 78269 : (*gensec_security)->ops = NULL;
725 78269 : (*gensec_security)->private_data = NULL;
726 78269 : (*gensec_security)->update_busy_ptr = NULL;
727 :
728 78269 : (*gensec_security)->subcontext = true;
729 78269 : (*gensec_security)->want_features = parent->want_features;
730 78269 : (*gensec_security)->max_update_size = parent->max_update_size;
731 78269 : (*gensec_security)->dcerpc_auth_level = parent->dcerpc_auth_level;
732 78269 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
733 78269 : (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
734 78269 : (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
735 :
736 78269 : talloc_set_destructor((*gensec_security), gensec_security_destructor);
737 78269 : return NT_STATUS_OK;
738 : }
739 :
740 63351 : _PUBLIC_ NTSTATUS gensec_child_ready(struct gensec_security *parent,
741 : struct gensec_security *child)
742 : {
743 63351 : if (parent->child_security != NULL) {
744 0 : return NT_STATUS_INTERNAL_ERROR;
745 : }
746 :
747 63351 : if (child->parent_security != NULL) {
748 0 : return NT_STATUS_INTERNAL_ERROR;
749 : }
750 :
751 63351 : parent->child_security = child;
752 63351 : child->parent_security = parent;
753 63351 : 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 35614 : _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
763 : struct gensec_security **gensec_security,
764 : struct gensec_settings *settings)
765 : {
766 : NTSTATUS status;
767 :
768 35614 : if (settings == NULL) {
769 0 : DEBUG(0,("gensec_client_start: no settings given!\n"));
770 0 : return NT_STATUS_INTERNAL_ERROR;
771 : }
772 :
773 35614 : status = gensec_start(mem_ctx, settings, NULL, gensec_security);
774 35614 : if (!NT_STATUS_IS_OK(status)) {
775 0 : return status;
776 : }
777 35614 : (*gensec_security)->gensec_role = GENSEC_CLIENT;
778 :
779 35614 : 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 85524 : _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 : NTSTATUS status;
796 :
797 85524 : if (!settings) {
798 0 : DEBUG(0,("gensec_server_start: no settings given!\n"));
799 0 : return NT_STATUS_INTERNAL_ERROR;
800 : }
801 :
802 85524 : status = gensec_start(mem_ctx, settings, auth_context, gensec_security);
803 85524 : if (!NT_STATUS_IS_OK(status)) {
804 0 : return status;
805 : }
806 85524 : (*gensec_security)->gensec_role = GENSEC_SERVER;
807 :
808 85524 : return status;
809 : }
810 :
811 159594 : static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
812 : {
813 : NTSTATUS status;
814 :
815 : /*
816 : * Callers sometimes just reuse a context, we should
817 : * clear the internal state before starting it again.
818 : */
819 159594 : talloc_unlink(gensec_security, gensec_security->private_data);
820 159594 : gensec_security->private_data = NULL;
821 :
822 159594 : 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 159594 : if (gensec_security->credentials) {
832 159593 : const char *forced_mech = cli_credentials_get_forced_sasl_mech(gensec_security->credentials);
833 159593 : 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 159594 : DEBUG(5, ("Starting GENSEC %smechanism %s\n",
845 : gensec_security->subcontext ? "sub" : "",
846 : gensec_security->ops->name));
847 159594 : switch (gensec_security->gensec_role) {
848 69482 : case GENSEC_CLIENT:
849 69482 : if (gensec_security->ops->client_start) {
850 69482 : status = gensec_security->ops->client_start(gensec_security);
851 69482 : if (!NT_STATUS_IS_OK(status)) {
852 1922 : 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 69482 : return status;
856 : }
857 0 : break;
858 90112 : case GENSEC_SERVER:
859 90112 : if (gensec_security->ops->server_start) {
860 90112 : status = gensec_security->ops->server_start(gensec_security);
861 90112 : if (!NT_STATUS_IS_OK(status)) {
862 8 : DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
863 : gensec_security->ops->name, nt_errstr(status)));
864 : }
865 90112 : 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 mechansim structure, used in SPNEGO
874 : *
875 : */
876 :
877 97633 : NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
878 : const struct gensec_security_ops *ops)
879 : {
880 97633 : gensec_security->ops = ops;
881 97633 : 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 14146 : _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
893 : uint8_t auth_type, uint8_t auth_level)
894 : {
895 14146 : gensec_security->ops = gensec_security_by_auth_type(gensec_security, auth_type);
896 14146 : if (!gensec_security->ops) {
897 23 : DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
898 23 : return NT_STATUS_INVALID_PARAMETER;
899 : }
900 14123 : 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 14123 : gensec_security->want_features &= ~GENSEC_FEATURE_SIGN;
906 14123 : gensec_security->want_features &= ~GENSEC_FEATURE_SEAL;
907 14123 : gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
908 14123 : gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
909 14123 : if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
910 4817 : if (gensec_security->gensec_role == GENSEC_CLIENT) {
911 2432 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
912 : }
913 9306 : } 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 232 : if (gensec_security->gensec_role == GENSEC_CLIENT) {
919 155 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
920 : }
921 9074 : } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
922 8044 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
923 8044 : gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
924 1030 : } 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 14120 : return gensec_start_mech(gensec_security);
933 : }
934 :
935 26 : _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
936 : {
937 : const struct gensec_security_ops *ops;
938 26 : ops = gensec_security_by_auth_type(gensec_security, authtype);
939 26 : if (ops) {
940 3 : return ops->name;
941 : }
942 23 : return NULL;
943 : }
944 :
945 :
946 26 : _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
947 : const char *oid_string)
948 : {
949 : const struct gensec_security_ops *ops;
950 26 : ops = gensec_security_by_oid(gensec_security, oid_string);
951 26 : if (ops) {
952 2 : return ops->name;
953 : }
954 24 : 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 27066 : _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
965 : const char *mech_oid)
966 : {
967 27066 : SMB_ASSERT(gensec_security != NULL);
968 :
969 27066 : gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
970 27066 : if (!gensec_security->ops) {
971 24 : DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
972 24 : return NT_STATUS_INVALID_PARAMETER;
973 : }
974 27042 : return gensec_start_mech(gensec_security);
975 : }
976 :
977 : /**
978 : * Start a GENSEC sub-mechanism by a well know SASL name
979 : *
980 : */
981 :
982 19575 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
983 : const char *sasl_name)
984 : {
985 19575 : gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
986 19575 : if (!gensec_security->ops) {
987 0 : DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
988 0 : return NT_STATUS_INVALID_PARAMETER;
989 : }
990 19575 : 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 19365 : _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
999 : const char **sasl_names)
1000 : {
1001 19365 : NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
1002 19365 : TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
1003 : const struct gensec_security_ops **ops;
1004 : int i;
1005 19365 : if (!mem_ctx) {
1006 0 : return NT_STATUS_NO_MEMORY;
1007 : }
1008 19365 : ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
1009 19365 : 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 19365 : for (i=0; ops[i]; i++) {
1017 19365 : nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
1018 19365 : if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
1019 19365 : break;
1020 : }
1021 : }
1022 19365 : talloc_free(mem_ctx);
1023 19365 : return nt_status;
1024 : }
1025 :
1026 : /**
1027 : * Start a GENSEC sub-mechanism by an internal name
1028 : *
1029 : */
1030 :
1031 1225 : _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
1032 : const char *name)
1033 : {
1034 1225 : gensec_security->ops = gensec_security_by_name(gensec_security, name);
1035 1225 : if (!gensec_security->ops) {
1036 1 : DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
1037 1 : return NT_STATUS_INVALID_PARAMETER;
1038 : }
1039 1224 : 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 122724 : _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
1048 : {
1049 122724 : gensec_security->credentials = talloc_reference(gensec_security, credentials);
1050 122724 : NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1051 122724 : gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1052 122724 : 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 146410 : _PUBLIC_ NTSTATUS gensec_register(TALLOC_CTX *ctx,
1062 : const struct gensec_security_ops *ops)
1063 : {
1064 146410 : 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 146410 : generic_security_ops = talloc_realloc(ctx,
1072 : generic_security_ops,
1073 : const struct gensec_security_ops *,
1074 : gensec_num_backends+2);
1075 146410 : if (!generic_security_ops) {
1076 0 : return NT_STATUS_NO_MEMORY;
1077 : }
1078 :
1079 146410 : generic_security_ops[gensec_num_backends] = ops;
1080 146410 : gensec_num_backends++;
1081 146410 : generic_security_ops[gensec_num_backends] = NULL;
1082 :
1083 146410 : DEBUG(3,("GENSEC backend '%s' registered\n",
1084 : ops->name));
1085 :
1086 146410 : 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 : 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 344807 : static int sort_gensec(const struct gensec_security_ops **gs1, const struct gensec_security_ops **gs2) {
1106 344807 : return (*gs2)->priority - (*gs1)->priority;
1107 : }
1108 :
1109 123924 : int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
1110 : {
1111 123924 : return lpcfg_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1112 : }
1113 :
1114 608957 : bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
1115 : {
1116 608957 : return lpcfg_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1117 : }
1118 :
1119 : /*
1120 : initialise the GENSEC subsystem
1121 : */
1122 45983 : _PUBLIC_ NTSTATUS gensec_init(void)
1123 : {
1124 : static bool initialized = false;
1125 : #define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
1126 : #ifdef STATIC_gensec_MODULES
1127 : STATIC_gensec_MODULES_PROTO;
1128 45983 : init_module_fn static_init[] = { STATIC_gensec_MODULES };
1129 : #else
1130 : init_module_fn *static_init = NULL;
1131 : #endif
1132 : init_module_fn *shared_init;
1133 :
1134 45983 : if (initialized) return NT_STATUS_OK;
1135 10471 : initialized = true;
1136 :
1137 10471 : shared_init = load_samba_modules(NULL, "gensec");
1138 :
1139 10471 : run_init_functions(NULL, static_init);
1140 10471 : run_init_functions(NULL, shared_init);
1141 :
1142 10471 : talloc_free(shared_init);
1143 :
1144 10471 : TYPESAFE_QSORT(generic_security_ops, gensec_num_backends, sort_gensec);
1145 :
1146 10471 : return NT_STATUS_OK;
1147 : }
|