/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- gensec_security_all
- gensec_security_ops_enabled
- gensec_use_kerberos_mechs
- gensec_security_mechs
- gensec_security_by_authtype
- gensec_security_by_oid
- gensec_security_by_sasl_name
- gensec_security_by_name
- gensec_security_by_sasl_list
- gensec_security_by_oid_list
- gensec_security_oids_from_ops
- gensec_security_oids_from_ops_wrapped
- gensec_security_oids
- gensec_start
- gensec_subcontext_start
- gensec_client_start
- gensec_server_start
- gensec_start_mech
- gensec_start_mech_by_authtype
- gensec_get_name_by_authtype
- gensec_get_name_by_oid
- gensec_start_mech_by_ops
- gensec_start_mech_by_oid
- gensec_start_mech_by_sasl_name
- gensec_start_mech_by_sasl_list
- gensec_start_mech_by_name
- gensec_unseal_packet
- gensec_check_packet
- gensec_seal_packet
- gensec_sign_packet
- gensec_sig_size
- gensec_max_wrapped_size
- gensec_max_input_size
- gensec_wrap
- gensec_unwrap
- gensec_session_key
- gensec_session_info
- gensec_update
- gensec_update_async_timed_handler
- gensec_update_send
- gensec_update_recv
- gensec_want_feature
- gensec_have_feature
- gensec_set_credentials
- gensec_get_credentials
- gensec_set_target_service
- gensec_get_target_service
- gensec_set_target_hostname
- gensec_get_target_hostname
- gensec_set_my_addr
- gensec_set_peer_addr
- gensec_get_my_addr
- gensec_get_peer_addr
- gensec_set_target_principal
- gensec_get_target_principal
- gensec_register
- gensec_interface_version
- sort_gensec
- gensec_setting_int
- gensec_setting_bool
- gensec_init
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 "auth/auth.h"
25 #include "lib/events/events.h"
26 #include "librpc/rpc/dcerpc.h"
27 #include "auth/credentials/credentials.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/gensec/gensec_proto.h"
30 #include "param/param.h"
31
32 /* the list of currently registered GENSEC backends */
33 static struct gensec_security_ops **generic_security_ops;
34 static int gensec_num_backends;
35
36 /* Return all the registered mechs. Don't modify the return pointer,
37 * but you may talloc_reference it if convient */
38 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
/* [<][>][^][v][top][bottom][index][help] */
39 {
40 return generic_security_ops;
41 }
42
43 bool gensec_security_ops_enabled(struct gensec_security_ops *ops,
/* [<][>][^][v][top][bottom][index][help] */
44 struct loadparm_context *lp_ctx)
45 {
46 return lp_parm_bool(lp_ctx, NULL, "gensec", ops->name, ops->enabled);
47 }
48
49 /* Sometimes we want to force only kerberos, sometimes we want to
50 * force it's avoidance. The old list could be either
51 * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
52 * an existing list we have trimmed down) */
53
54 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
55 struct gensec_security_ops **old_gensec_list,
56 struct cli_credentials *creds)
57 {
58 struct gensec_security_ops **new_gensec_list;
59 int i, j, num_mechs_in;
60 enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
61
62 if (creds) {
63 use_kerberos = cli_credentials_get_kerberos_state(creds);
64 }
65
66 if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
67 if (!talloc_reference(mem_ctx, old_gensec_list)) {
68 return NULL;
69 }
70 return old_gensec_list;
71 }
72
73 for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
74 /* noop */
75 }
76
77 new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
78 if (!new_gensec_list) {
79 return NULL;
80 }
81
82 j = 0;
83 for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
84 int oid_idx;
85
86 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
87 if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
88 new_gensec_list[j] = old_gensec_list[i];
89 j++;
90 break;
91 }
92 }
93 switch (use_kerberos) {
94 case CRED_DONT_USE_KERBEROS:
95 if (old_gensec_list[i]->kerberos == false) {
96 new_gensec_list[j] = old_gensec_list[i];
97 j++;
98 }
99 break;
100 case CRED_MUST_USE_KERBEROS:
101 if (old_gensec_list[i]->kerberos == true) {
102 new_gensec_list[j] = old_gensec_list[i];
103 j++;
104 }
105 break;
106 default:
107 /* Can't happen or invalid parameter */
108 return NULL;
109 }
110 }
111 new_gensec_list[j] = NULL;
112
113 return new_gensec_list;
114 }
115
116 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
117 TALLOC_CTX *mem_ctx)
118 {
119 struct gensec_security_ops **backends;
120 backends = gensec_security_all();
121 if (!gensec_security) {
122 if (!talloc_reference(mem_ctx, backends)) {
123 return NULL;
124 }
125 return backends;
126 } else {
127 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
128 if (!creds) {
129 if (!talloc_reference(mem_ctx, backends)) {
130 return NULL;
131 }
132 return backends;
133 }
134 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
135 }
136 }
137
138 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
139 uint8_t auth_type)
140 {
141 int i;
142 struct gensec_security_ops **backends;
143 const struct gensec_security_ops *backend;
144 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
145 if (!mem_ctx) {
146 return NULL;
147 }
148 backends = gensec_security_mechs(gensec_security, mem_ctx);
149 for (i=0; backends && backends[i]; i++) {
150 if (!gensec_security_ops_enabled(backends[i],
151 gensec_security->settings->lp_ctx))
152 continue;
153 if (backends[i]->auth_type == auth_type) {
154 backend = backends[i];
155 talloc_free(mem_ctx);
156 return backend;
157 }
158 }
159 talloc_free(mem_ctx);
160
161 return NULL;
162 }
163
164 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
165 const char *oid_string)
166 {
167 int i, j;
168 struct gensec_security_ops **backends;
169 const struct gensec_security_ops *backend;
170 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
171 if (!mem_ctx) {
172 return NULL;
173 }
174 backends = gensec_security_mechs(gensec_security, mem_ctx);
175 for (i=0; backends && backends[i]; i++) {
176 if (gensec_security != NULL &&
177 !gensec_security_ops_enabled(backends[i],
178 gensec_security->settings->lp_ctx))
179 continue;
180 if (backends[i]->oid) {
181 for (j=0; backends[i]->oid[j]; j++) {
182 if (backends[i]->oid[j] &&
183 (strcmp(backends[i]->oid[j], oid_string) == 0)) {
184 backend = backends[i];
185 talloc_free(mem_ctx);
186 return backend;
187 }
188 }
189 }
190 }
191 talloc_free(mem_ctx);
192
193 return NULL;
194 }
195
196 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
197 const char *sasl_name)
198 {
199 int i;
200 struct gensec_security_ops **backends;
201 const struct gensec_security_ops *backend;
202 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
203 if (!mem_ctx) {
204 return NULL;
205 }
206 backends = gensec_security_mechs(gensec_security, mem_ctx);
207 for (i=0; backends && backends[i]; i++) {
208 if (!gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
209 continue;
210 if (backends[i]->sasl_name
211 && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
212 backend = backends[i];
213 talloc_free(mem_ctx);
214 return backend;
215 }
216 }
217 talloc_free(mem_ctx);
218
219 return NULL;
220 }
221
222 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
223 const char *name)
224 {
225 int i;
226 struct gensec_security_ops **backends;
227 const struct gensec_security_ops *backend;
228 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
229 if (!mem_ctx) {
230 return NULL;
231 }
232 backends = gensec_security_mechs(gensec_security, mem_ctx);
233 for (i=0; backends && backends[i]; i++) {
234 if (gensec_security != NULL &&
235 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
236 continue;
237 if (backends[i]->name
238 && (strcmp(backends[i]->name, name) == 0)) {
239 backend = backends[i];
240 talloc_free(mem_ctx);
241 return backend;
242 }
243 }
244 talloc_free(mem_ctx);
245 return NULL;
246 }
247
248 /**
249 * Return a unique list of security subsystems from those specified in
250 * the list of SASL names.
251 *
252 * Use the list of enabled GENSEC mechanisms from the credentials
253 * attached to the gensec_security, and return in our preferred order.
254 */
255
256 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
257 TALLOC_CTX *mem_ctx,
258 const char **sasl_names)
259 {
260 const struct gensec_security_ops **backends_out;
261 struct gensec_security_ops **backends;
262 int i, k, sasl_idx;
263 int num_backends_out = 0;
264
265 if (!sasl_names) {
266 return NULL;
267 }
268
269 backends = gensec_security_mechs(gensec_security, mem_ctx);
270
271 backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
272 if (!backends_out) {
273 return NULL;
274 }
275 backends_out[0] = NULL;
276
277 /* Find backends in our preferred order, by walking our list,
278 * then looking in the supplied list */
279 for (i=0; backends && backends[i]; i++) {
280 if (gensec_security != NULL &&
281 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
282 continue;
283 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
284 if (!backends[i]->sasl_name ||
285 !(strcmp(backends[i]->sasl_name,
286 sasl_names[sasl_idx]) == 0)) {
287 continue;
288 }
289
290 for (k=0; backends_out[k]; k++) {
291 if (backends_out[k] == backends[i]) {
292 break;
293 }
294 }
295
296 if (k < num_backends_out) {
297 /* already in there */
298 continue;
299 }
300
301 backends_out = talloc_realloc(mem_ctx, backends_out,
302 const struct gensec_security_ops *,
303 num_backends_out + 2);
304 if (!backends_out) {
305 return NULL;
306 }
307
308 backends_out[num_backends_out] = backends[i];
309 num_backends_out++;
310 backends_out[num_backends_out] = NULL;
311 }
312 }
313 return backends_out;
314 }
315
316 /**
317 * Return a unique list of security subsystems from those specified in
318 * the OID list. That is, where two OIDs refer to the same module,
319 * return that module only once.
320 *
321 * Use the list of enabled GENSEC mechanisms from the credentials
322 * attached to the gensec_security, and return in our preferred order.
323 */
324
325 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
326 TALLOC_CTX *mem_ctx,
327 const char **oid_strings,
328 const char *skip)
329 {
330 struct gensec_security_ops_wrapper *backends_out;
331 struct gensec_security_ops **backends;
332 int i, j, k, oid_idx;
333 int num_backends_out = 0;
334
335 if (!oid_strings) {
336 return NULL;
337 }
338
339 backends = gensec_security_mechs(gensec_security, gensec_security);
340
341 backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
342 if (!backends_out) {
343 return NULL;
344 }
345 backends_out[0].op = NULL;
346 backends_out[0].oid = NULL;
347
348 /* Find backends in our preferred order, by walking our list,
349 * then looking in the supplied list */
350 for (i=0; backends && backends[i]; i++) {
351 if (gensec_security != NULL &&
352 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
353 continue;
354 if (!backends[i]->oid) {
355 continue;
356 }
357 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
358 if (strcmp(oid_strings[oid_idx], skip) == 0) {
359 continue;
360 }
361
362 for (j=0; backends[i]->oid[j]; j++) {
363 if (!backends[i]->oid[j] ||
364 !(strcmp(backends[i]->oid[j],
365 oid_strings[oid_idx]) == 0)) {
366 continue;
367 }
368
369 for (k=0; backends_out[k].op; k++) {
370 if (backends_out[k].op == backends[i]) {
371 break;
372 }
373 }
374
375 if (k < num_backends_out) {
376 /* already in there */
377 continue;
378 }
379
380 backends_out = talloc_realloc(mem_ctx, backends_out,
381 struct gensec_security_ops_wrapper,
382 num_backends_out + 2);
383 if (!backends_out) {
384 return NULL;
385 }
386
387 backends_out[num_backends_out].op = backends[i];
388 backends_out[num_backends_out].oid = backends[i]->oid[j];
389 num_backends_out++;
390 backends_out[num_backends_out].op = NULL;
391 backends_out[num_backends_out].oid = NULL;
392 }
393 }
394 }
395 return backends_out;
396 }
397
398 /**
399 * Return OIDS from the security subsystems listed
400 */
401
402 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
403 TALLOC_CTX *mem_ctx,
404 struct gensec_security_ops **ops,
405 const char *skip)
406 {
407 int i;
408 int j = 0;
409 int k;
410 const char **oid_list;
411 if (!ops) {
412 return NULL;
413 }
414 oid_list = talloc_array(mem_ctx, const char *, 1);
415 if (!oid_list) {
416 return NULL;
417 }
418
419 for (i=0; ops && ops[i]; i++) {
420 if (gensec_security != NULL &&
421 !gensec_security_ops_enabled(ops[i], gensec_security->settings->lp_ctx)) {
422 continue;
423 }
424 if (!ops[i]->oid) {
425 continue;
426 }
427
428 for (k = 0; ops[i]->oid[k]; k++) {
429 if (skip && strcmp(skip, ops[i]->oid[k])==0) {
430 } else {
431 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
432 if (!oid_list) {
433 return NULL;
434 }
435 oid_list[j] = ops[i]->oid[k];
436 j++;
437 }
438 }
439 }
440 oid_list[j] = NULL;
441 return oid_list;
442 }
443
444
445 /**
446 * Return OIDS from the security subsystems listed
447 */
448
449 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
450 const struct gensec_security_ops_wrapper *wops)
451 {
452 int i;
453 int j = 0;
454 int k;
455 const char **oid_list;
456 if (!wops) {
457 return NULL;
458 }
459 oid_list = talloc_array(mem_ctx, const char *, 1);
460 if (!oid_list) {
461 return NULL;
462 }
463
464 for (i=0; wops[i].op; i++) {
465 if (!wops[i].op->oid) {
466 continue;
467 }
468
469 for (k = 0; wops[i].op->oid[k]; k++) {
470 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
471 if (!oid_list) {
472 return NULL;
473 }
474 oid_list[j] = wops[i].op->oid[k];
475 j++;
476 }
477 }
478 oid_list[j] = NULL;
479 return oid_list;
480 }
481
482
483 /**
484 * Return all the security subsystems currently enabled on a GENSEC context.
485 *
486 * This is taken from a list attached to the cli_credentials, and
487 * skips the OID in 'skip'. (Typically the SPNEGO OID)
488 *
489 */
490
491 const char **gensec_security_oids(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
492 TALLOC_CTX *mem_ctx,
493 const char *skip)
494 {
495 struct gensec_security_ops **ops
496 = gensec_security_mechs(gensec_security, mem_ctx);
497 return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
498 }
499
500
501
502 /**
503 Start the GENSEC system, returning a context pointer.
504 @param mem_ctx The parent TALLOC memory context.
505 @param gensec_security Returned GENSEC context pointer.
506 @note The mem_ctx is only a parent and may be NULL.
507 */
508 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
509 struct tevent_context *ev,
510 struct gensec_settings *settings,
511 struct auth_context *auth_context,
512 struct gensec_security **gensec_security)
513 {
514 if (ev == NULL) {
515 DEBUG(0, ("No event context available!\n"));
516 return NT_STATUS_INTERNAL_ERROR;
517 }
518
519 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
520 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
521
522 (*gensec_security)->ops = NULL;
523 (*gensec_security)->private_data = NULL;
524
525 ZERO_STRUCT((*gensec_security)->target);
526 ZERO_STRUCT((*gensec_security)->peer_addr);
527 ZERO_STRUCT((*gensec_security)->my_addr);
528
529 (*gensec_security)->subcontext = false;
530 (*gensec_security)->want_features = 0;
531
532 (*gensec_security)->event_ctx = ev;
533 SMB_ASSERT(settings->lp_ctx != NULL);
534 (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
535 (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
536
537 return NT_STATUS_OK;
538 }
539
540 /**
541 * Start a GENSEC subcontext, with a copy of the properties of the parent
542 * @param mem_ctx The parent TALLOC memory context.
543 * @param parent The parent GENSEC context
544 * @param gensec_security Returned GENSEC context pointer.
545 * @note Used by SPNEGO in particular, for the actual implementation mechanism
546 */
547
548 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
549 struct gensec_security *parent,
550 struct gensec_security **gensec_security)
551 {
552 (*gensec_security) = talloc(mem_ctx, struct gensec_security);
553 NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
554
555 (**gensec_security) = *parent;
556 (*gensec_security)->ops = NULL;
557 (*gensec_security)->private_data = NULL;
558
559 (*gensec_security)->subcontext = true;
560 (*gensec_security)->want_features = parent->want_features;
561 (*gensec_security)->event_ctx = parent->event_ctx;
562 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
563 (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
564 (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
565
566 return NT_STATUS_OK;
567 }
568
569 /**
570 Start the GENSEC system, in client mode, returning a context pointer.
571 @param mem_ctx The parent TALLOC memory context.
572 @param gensec_security Returned GENSEC context pointer.
573 @note The mem_ctx is only a parent and may be NULL.
574 */
575 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
576 struct gensec_security **gensec_security,
577 struct tevent_context *ev,
578 struct gensec_settings *settings)
579 {
580 NTSTATUS status;
581
582 if (settings == NULL) {
583 DEBUG(0,("gensec_client_start: no settings given!\n"));
584 return NT_STATUS_INTERNAL_ERROR;
585 }
586
587 status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
588 if (!NT_STATUS_IS_OK(status)) {
589 return status;
590 }
591 (*gensec_security)->gensec_role = GENSEC_CLIENT;
592
593 return status;
594 }
595
596 /**
597 Start the GENSEC system, in server mode, returning a context pointer.
598 @param mem_ctx The parent TALLOC memory context.
599 @param gensec_security Returned GENSEC context pointer.
600 @note The mem_ctx is only a parent and may be NULL.
601 */
602 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
603 struct tevent_context *ev,
604 struct gensec_settings *settings,
605 struct auth_context *auth_context,
606 struct gensec_security **gensec_security)
607 {
608 NTSTATUS status;
609
610 if (!ev) {
611 DEBUG(0,("gensec_server_start: no event context given!\n"));
612 return NT_STATUS_INTERNAL_ERROR;
613 }
614
615 if (!settings) {
616 DEBUG(0,("gensec_server_start: no settings given!\n"));
617 return NT_STATUS_INTERNAL_ERROR;
618 }
619
620 status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
621 if (!NT_STATUS_IS_OK(status)) {
622 return status;
623 }
624 (*gensec_security)->gensec_role = GENSEC_SERVER;
625
626 return status;
627 }
628
629 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
630 {
631 NTSTATUS status;
632 DEBUG(5, ("Starting GENSEC %smechanism %s\n",
633 gensec_security->subcontext ? "sub" : "",
634 gensec_security->ops->name));
635 switch (gensec_security->gensec_role) {
636 case GENSEC_CLIENT:
637 if (gensec_security->ops->client_start) {
638 status = gensec_security->ops->client_start(gensec_security);
639 if (!NT_STATUS_IS_OK(status)) {
640 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
641 gensec_security->ops->name, nt_errstr(status)));
642 }
643 return status;
644 }
645 break;
646 case GENSEC_SERVER:
647 if (gensec_security->ops->server_start) {
648 status = gensec_security->ops->server_start(gensec_security);
649 if (!NT_STATUS_IS_OK(status)) {
650 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
651 gensec_security->ops->name, nt_errstr(status)));
652 }
653 return status;
654 }
655 break;
656 }
657 return NT_STATUS_INVALID_PARAMETER;
658 }
659
660 /**
661 * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number
662 * @param gensec_security GENSEC context pointer.
663 * @param auth_type DCERPC auth type
664 * @param auth_level DCERPC auth level
665 */
666
667 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
668 uint8_t auth_type, uint8_t auth_level)
669 {
670 gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
671 if (!gensec_security->ops) {
672 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
673 return NT_STATUS_INVALID_PARAMETER;
674 }
675 gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
676 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
677 if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
678 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
679 } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
680 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
681 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
682 } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
683 /* Default features */
684 } else {
685 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n",
686 auth_level));
687 return NT_STATUS_INVALID_PARAMETER;
688 }
689
690 return gensec_start_mech(gensec_security);
691 }
692
693 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype)
/* [<][>][^][v][top][bottom][index][help] */
694 {
695 const struct gensec_security_ops *ops;
696 ops = gensec_security_by_authtype(gensec_security, authtype);
697 if (ops) {
698 return ops->name;
699 }
700 return NULL;
701 }
702
703
704 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
705 const char *oid_string)
706 {
707 const struct gensec_security_ops *ops;
708 ops = gensec_security_by_oid(gensec_security, oid_string);
709 if (ops) {
710 return ops->name;
711 }
712 return oid_string;
713 }
714
715
716 /**
717 * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
718 *
719 */
720
721 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
722 const struct gensec_security_ops *ops)
723 {
724 gensec_security->ops = ops;
725 return gensec_start_mech(gensec_security);
726 }
727
728 /**
729 * Start a GENSEC sub-mechanism by OID, used in SPNEGO
730 *
731 * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
732 * well-known #define to hook it in.
733 */
734
735 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
736 const char *mech_oid)
737 {
738 SMB_ASSERT(gensec_security != NULL);
739
740 gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
741 if (!gensec_security->ops) {
742 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
743 return NT_STATUS_INVALID_PARAMETER;
744 }
745 return gensec_start_mech(gensec_security);
746 }
747
748 /**
749 * Start a GENSEC sub-mechanism by a well know SASL name
750 *
751 */
752
753 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
754 const char *sasl_name)
755 {
756 gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
757 if (!gensec_security->ops) {
758 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
759 return NT_STATUS_INVALID_PARAMETER;
760 }
761 return gensec_start_mech(gensec_security);
762 }
763
764 /**
765 * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
766 *
767 */
768
769 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
770 const char **sasl_names)
771 {
772 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
773 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
774 const struct gensec_security_ops **ops;
775 int i;
776 if (!mem_ctx) {
777 return NT_STATUS_NO_MEMORY;
778 }
779 ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
780 if (!ops || !*ops) {
781 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n",
782 str_list_join(mem_ctx,
783 sasl_names, ' ')));
784 talloc_free(mem_ctx);
785 return NT_STATUS_INVALID_PARAMETER;
786 }
787 for (i=0; ops[i]; i++) {
788 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
789 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
790 break;
791 }
792 }
793 talloc_free(mem_ctx);
794 return nt_status;
795 }
796
797 /**
798 * Start a GENSEC sub-mechanism by an internal name
799 *
800 */
801
802 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
803 const char *name)
804 {
805 gensec_security->ops = gensec_security_by_name(gensec_security, name);
806 if (!gensec_security->ops) {
807 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
808 return NT_STATUS_INVALID_PARAMETER;
809 }
810 return gensec_start_mech(gensec_security);
811 }
812
813 /*
814 wrappers for the gensec function pointers
815 */
816 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
817 TALLOC_CTX *mem_ctx,
818 uint8_t *data, size_t length,
819 const uint8_t *whole_pdu, size_t pdu_length,
820 const DATA_BLOB *sig)
821 {
822 if (!gensec_security->ops->unseal_packet) {
823 return NT_STATUS_NOT_IMPLEMENTED;
824 }
825 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
826 return NT_STATUS_INVALID_PARAMETER;
827 }
828
829 return gensec_security->ops->unseal_packet(gensec_security, mem_ctx,
830 data, length,
831 whole_pdu, pdu_length,
832 sig);
833 }
834
835 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
836 TALLOC_CTX *mem_ctx,
837 const uint8_t *data, size_t length,
838 const uint8_t *whole_pdu, size_t pdu_length,
839 const DATA_BLOB *sig)
840 {
841 if (!gensec_security->ops->check_packet) {
842 return NT_STATUS_NOT_IMPLEMENTED;
843 }
844 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
845 return NT_STATUS_INVALID_PARAMETER;
846 }
847
848 return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
849 }
850
851 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
852 TALLOC_CTX *mem_ctx,
853 uint8_t *data, size_t length,
854 const uint8_t *whole_pdu, size_t pdu_length,
855 DATA_BLOB *sig)
856 {
857 if (!gensec_security->ops->seal_packet) {
858 return NT_STATUS_NOT_IMPLEMENTED;
859 }
860 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
861 return NT_STATUS_INVALID_PARAMETER;
862 }
863
864 return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
865 }
866
867 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
868 TALLOC_CTX *mem_ctx,
869 const uint8_t *data, size_t length,
870 const uint8_t *whole_pdu, size_t pdu_length,
871 DATA_BLOB *sig)
872 {
873 if (!gensec_security->ops->sign_packet) {
874 return NT_STATUS_NOT_IMPLEMENTED;
875 }
876 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
877 return NT_STATUS_INVALID_PARAMETER;
878 }
879
880 return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
881 }
882
883 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size)
/* [<][>][^][v][top][bottom][index][help] */
884 {
885 if (!gensec_security->ops->sig_size) {
886 return 0;
887 }
888 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
889 return 0;
890 }
891
892 return gensec_security->ops->sig_size(gensec_security, data_size);
893 }
894
895 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
896 {
897 if (!gensec_security->ops->max_wrapped_size) {
898 return (1 << 17);
899 }
900
901 return gensec_security->ops->max_wrapped_size(gensec_security);
902 }
903
904 size_t gensec_max_input_size(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
905 {
906 if (!gensec_security->ops->max_input_size) {
907 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
908 }
909
910 return gensec_security->ops->max_input_size(gensec_security);
911 }
912
913 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
914 TALLOC_CTX *mem_ctx,
915 const DATA_BLOB *in,
916 DATA_BLOB *out)
917 {
918 if (!gensec_security->ops->wrap) {
919 return NT_STATUS_NOT_IMPLEMENTED;
920 }
921 return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
922 }
923
924 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
925 TALLOC_CTX *mem_ctx,
926 const DATA_BLOB *in,
927 DATA_BLOB *out)
928 {
929 if (!gensec_security->ops->unwrap) {
930 return NT_STATUS_NOT_IMPLEMENTED;
931 }
932 return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
933 }
934
935 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
936 DATA_BLOB *session_key)
937 {
938 if (!gensec_security->ops->session_key) {
939 return NT_STATUS_NOT_IMPLEMENTED;
940 }
941 if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
942 return NT_STATUS_NO_USER_SESSION_KEY;
943 }
944
945 return gensec_security->ops->session_key(gensec_security, session_key);
946 }
947
948 /**
949 * Return the credentials of a logged on user, including session keys
950 * etc.
951 *
952 * Only valid after a successful authentication
953 *
954 * May only be called once per authentication.
955 *
956 */
957
958 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
959 struct auth_session_info **session_info)
960 {
961 if (!gensec_security->ops->session_info) {
962 return NT_STATUS_NOT_IMPLEMENTED;
963 }
964 return gensec_security->ops->session_info(gensec_security, session_info);
965 }
966
967 /**
968 * Next state function for the GENSEC state machine
969 *
970 * @param gensec_security GENSEC State
971 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
972 * @param in The request, as a DATA_BLOB
973 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
974 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
975 * or NT_STATUS_OK if the user is authenticated.
976 */
977
978 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
979 const DATA_BLOB in, DATA_BLOB *out)
980 {
981 return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
982 }
983
984 static void gensec_update_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te,
/* [<][>][^][v][top][bottom][index][help] */
985 struct timeval t, void *ptr)
986 {
987 struct gensec_update_request *req = talloc_get_type(ptr, struct gensec_update_request);
988 req->status = req->gensec_security->ops->update(req->gensec_security, req, req->in, &req->out);
989 req->callback.fn(req, req->callback.private_data);
990 }
991
992 /**
993 * Next state function for the GENSEC state machine async version
994 *
995 * @param gensec_security GENSEC State
996 * @param in The request, as a DATA_BLOB
997 * @param callback The function that will be called when the operation is
998 * finished, it should return gensec_update_recv() to get output
999 * @param private_data A private pointer that will be passed to the callback function
1000 */
1001
1002 _PUBLIC_ void gensec_update_send(struct gensec_security *gensec_security, const DATA_BLOB in,
/* [<][>][^][v][top][bottom][index][help] */
1003 void (*callback)(struct gensec_update_request *req, void *private_data),
1004 void *private_data)
1005 {
1006 struct gensec_update_request *req = NULL;
1007 struct tevent_timer *te = NULL;
1008
1009 req = talloc(gensec_security, struct gensec_update_request);
1010 if (!req) goto failed;
1011 req->gensec_security = gensec_security;
1012 req->in = in;
1013 req->out = data_blob(NULL, 0);
1014 req->callback.fn = callback;
1015 req->callback.private_data = private_data;
1016
1017 te = event_add_timed(gensec_security->event_ctx, req,
1018 timeval_zero(),
1019 gensec_update_async_timed_handler, req);
1020 if (!te) goto failed;
1021
1022 return;
1023
1024 failed:
1025 talloc_free(req);
1026 callback(NULL, private_data);
1027 }
1028
1029 /**
1030 * Next state function for the GENSEC state machine
1031 *
1032 * @param req GENSEC update request state
1033 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
1034 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
1035 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
1036 * or NT_STATUS_OK if the user is authenticated.
1037 */
1038 _PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out)
/* [<][>][^][v][top][bottom][index][help] */
1039 {
1040 NTSTATUS status;
1041
1042 NT_STATUS_HAVE_NO_MEMORY(req);
1043
1044 *out = req->out;
1045 talloc_steal(out_mem_ctx, out->data);
1046 status = req->status;
1047
1048 talloc_free(req);
1049 return status;
1050 }
1051
1052 /**
1053 * Set the requirement for a certain feature on the connection
1054 *
1055 */
1056
1057 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
1058 uint32_t feature)
1059 {
1060 if (!gensec_security->ops || !gensec_security->ops->want_feature) {
1061 gensec_security->want_features |= feature;
1062 return;
1063 }
1064 gensec_security->ops->want_feature(gensec_security, feature);
1065 }
1066
1067 /**
1068 * Check the requirement for a certain feature on the connection
1069 *
1070 */
1071
1072 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
/* [<][>][^][v][top][bottom][index][help] */
1073 uint32_t feature)
1074 {
1075 if (!gensec_security->ops->have_feature) {
1076 return false;
1077 }
1078
1079 /* We might 'have' features that we don't 'want', because the
1080 * other end demanded them, or we can't neotiate them off */
1081 return gensec_security->ops->have_feature(gensec_security, feature);
1082 }
1083
1084 /**
1085 * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context
1086 *
1087 */
1088
1089 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials)
/* [<][>][^][v][top][bottom][index][help] */
1090 {
1091 gensec_security->credentials = talloc_reference(gensec_security, credentials);
1092 NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1093 gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1094 return NT_STATUS_OK;
1095 }
1096
1097 /**
1098 * Return the credentials structure associated with a GENSEC context
1099 *
1100 */
1101
1102 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1103 {
1104 if (!gensec_security) {
1105 return NULL;
1106 }
1107 return gensec_security->credentials;
1108 }
1109
1110 /**
1111 * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed
1112 *
1113 */
1114
1115 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service)
/* [<][>][^][v][top][bottom][index][help] */
1116 {
1117 gensec_security->target.service = talloc_strdup(gensec_security, service);
1118 if (!gensec_security->target.service) {
1119 return NT_STATUS_NO_MEMORY;
1120 }
1121 return NT_STATUS_OK;
1122 }
1123
1124 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1125 {
1126 if (gensec_security->target.service) {
1127 return gensec_security->target.service;
1128 }
1129
1130 return "host";
1131 }
1132
1133 /**
1134 * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed
1135 *
1136 */
1137
1138 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname)
/* [<][>][^][v][top][bottom][index][help] */
1139 {
1140 gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
1141 if (hostname && !gensec_security->target.hostname) {
1142 return NT_STATUS_NO_MEMORY;
1143 }
1144 return NT_STATUS_OK;
1145 }
1146
1147 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1148 {
1149 /* We allow the target hostname to be overriden for testing purposes */
1150 if (gensec_security->settings->target_hostname) {
1151 return gensec_security->settings->target_hostname;
1152 }
1153
1154 if (gensec_security->target.hostname) {
1155 return gensec_security->target.hostname;
1156 }
1157
1158 /* We could add use the 'set sockaddr' call, and do a reverse
1159 * lookup, but this would be both insecure (compromising the
1160 * way kerberos works) and add DNS timeouts */
1161 return NULL;
1162 }
1163
1164 /**
1165 * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context
1166 *
1167 * This is so that kerberos can include these addresses in
1168 * cryptographic tokens, to avoid certain attacks.
1169 */
1170
1171 _PUBLIC_ NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr)
/* [<][>][^][v][top][bottom][index][help] */
1172 {
1173 gensec_security->my_addr = my_addr;
1174 if (my_addr && !talloc_reference(gensec_security, my_addr)) {
1175 return NT_STATUS_NO_MEMORY;
1176 }
1177 return NT_STATUS_OK;
1178 }
1179
1180 _PUBLIC_ NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr)
/* [<][>][^][v][top][bottom][index][help] */
1181 {
1182 gensec_security->peer_addr = peer_addr;
1183 if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
1184 return NT_STATUS_NO_MEMORY;
1185 }
1186 return NT_STATUS_OK;
1187 }
1188
1189 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1190 {
1191 if (gensec_security->my_addr) {
1192 return gensec_security->my_addr;
1193 }
1194
1195 /* We could add a 'set sockaddr' call, and do a lookup. This
1196 * would avoid needing to do system calls if nothing asks. */
1197 return NULL;
1198 }
1199
1200 _PUBLIC_ struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1201 {
1202 if (gensec_security->peer_addr) {
1203 return gensec_security->peer_addr;
1204 }
1205
1206 /* We could add a 'set sockaddr' call, and do a lookup. This
1207 * would avoid needing to do system calls if nothing asks.
1208 * However, this is not appropriate for the peer addres on
1209 * datagram sockets */
1210 return NULL;
1211 }
1212
1213
1214
1215 /**
1216 * Set the target principal (assuming it it known, say from the SPNEGO reply)
1217 * - ensures it is talloc()ed
1218 *
1219 */
1220
1221 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal)
/* [<][>][^][v][top][bottom][index][help] */
1222 {
1223 gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1224 if (!gensec_security->target.principal) {
1225 return NT_STATUS_NO_MEMORY;
1226 }
1227 return NT_STATUS_OK;
1228 }
1229
1230 const char *gensec_get_target_principal(struct gensec_security *gensec_security)
/* [<][>][^][v][top][bottom][index][help] */
1231 {
1232 if (gensec_security->target.principal) {
1233 return gensec_security->target.principal;
1234 }
1235
1236 return NULL;
1237 }
1238
1239 /*
1240 register a GENSEC backend.
1241
1242 The 'name' can be later used by other backends to find the operations
1243 structure for this backend.
1244 */
1245 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
/* [<][>][^][v][top][bottom][index][help] */
1246 {
1247 if (gensec_security_by_name(NULL, ops->name) != NULL) {
1248 /* its already registered! */
1249 DEBUG(0,("GENSEC backend '%s' already registered\n",
1250 ops->name));
1251 return NT_STATUS_OBJECT_NAME_COLLISION;
1252 }
1253
1254 generic_security_ops = talloc_realloc(talloc_autofree_context(),
1255 generic_security_ops,
1256 struct gensec_security_ops *,
1257 gensec_num_backends+2);
1258 if (!generic_security_ops) {
1259 return NT_STATUS_NO_MEMORY;
1260 }
1261
1262 generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
1263 gensec_num_backends++;
1264 generic_security_ops[gensec_num_backends] = NULL;
1265
1266 DEBUG(3,("GENSEC backend '%s' registered\n",
1267 ops->name));
1268
1269 return NT_STATUS_OK;
1270 }
1271
1272 /*
1273 return the GENSEC interface version, and the size of some critical types
1274 This can be used by backends to either detect compilation errors, or provide
1275 multiple implementations for different smbd compilation options in one module
1276 */
1277 const struct gensec_critical_sizes *gensec_interface_version(void)
/* [<][>][^][v][top][bottom][index][help] */
1278 {
1279 static const struct gensec_critical_sizes critical_sizes = {
1280 GENSEC_INTERFACE_VERSION,
1281 sizeof(struct gensec_security_ops),
1282 sizeof(struct gensec_security),
1283 };
1284
1285 return &critical_sizes;
1286 }
1287
1288 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
/* [<][>][^][v][top][bottom][index][help] */
1289 return (*gs2)->priority - (*gs1)->priority;
1290 }
1291
1292 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
/* [<][>][^][v][top][bottom][index][help] */
1293 {
1294 return lp_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1295 }
1296
1297 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
/* [<][>][^][v][top][bottom][index][help] */
1298 {
1299 return lp_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1300 }
1301
1302 /*
1303 initialise the GENSEC subsystem
1304 */
1305 _PUBLIC_ NTSTATUS gensec_init(struct loadparm_context *lp_ctx)
/* [<][>][^][v][top][bottom][index][help] */
1306 {
1307 static bool initialized = false;
1308 extern NTSTATUS gensec_sasl_init(void);
1309 extern NTSTATUS gensec_krb5_init(void);
1310 extern NTSTATUS gensec_schannel_init(void);
1311 extern NTSTATUS gensec_spnego_init(void);
1312 extern NTSTATUS gensec_gssapi_init(void);
1313 extern NTSTATUS gensec_ntlmssp_init(void);
1314
1315 init_module_fn static_init[] = { STATIC_gensec_MODULES };
1316 init_module_fn *shared_init;
1317
1318 if (initialized) return NT_STATUS_OK;
1319 initialized = true;
1320
1321 shared_init = load_samba_modules(NULL, lp_ctx, "gensec");
1322
1323 run_init_functions(static_init);
1324 run_init_functions(shared_init);
1325
1326 talloc_free(shared_init);
1327
1328 qsort(generic_security_ops, gensec_num_backends, sizeof(*generic_security_ops), QSORT_CAST sort_gensec);
1329
1330 return NT_STATUS_OK;
1331 }