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