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