~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/auth/gensec/gensec.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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