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