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