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