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