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