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