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