~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/auth/gensec/gensec_gssapi.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
   Kerberos backend for GENSEC
 
5
   
 
6
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
 
7
   Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
 
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
   
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#include "includes.h"
 
25
#include "lib/events/events.h"
 
26
#include "system/kerberos.h"
 
27
#include "auth/kerberos/kerberos.h"
 
28
#include "librpc/gen_ndr/krb5pac.h"
 
29
#include "auth/auth.h"
 
30
#include "lib/ldb/include/ldb.h"
 
31
#include "auth/auth_sam.h"
 
32
#include "librpc/rpc/dcerpc.h"
 
33
#include "auth/credentials/credentials.h"
 
34
#include "auth/credentials/credentials_krb5.h"
 
35
#include "auth/gensec/gensec.h"
 
36
#include "auth/gensec/gensec_proto.h"
 
37
#include "param/param.h"
 
38
#include "auth/session_proto.h"
 
39
#include <gssapi/gssapi.h>
 
40
#include <gssapi/gssapi_krb5.h>
 
41
#include "auth/gensec/gensec_gssapi.h"
 
42
 
 
43
static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
 
44
static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
 
45
 
 
46
static char *gssapi_error_string(TALLOC_CTX *mem_ctx, 
 
47
                                 OM_uint32 maj_stat, OM_uint32 min_stat, 
 
48
                                 const gss_OID mech)
 
49
{
 
50
        OM_uint32 disp_min_stat, disp_maj_stat;
 
51
        gss_buffer_desc maj_error_message;
 
52
        gss_buffer_desc min_error_message;
 
53
        char *maj_error_string, *min_error_string;
 
54
        OM_uint32 msg_ctx = 0;
 
55
 
 
56
        char *ret;
 
57
 
 
58
        maj_error_message.value = NULL;
 
59
        min_error_message.value = NULL;
 
60
        maj_error_message.length = 0;
 
61
        min_error_message.length = 0;
 
62
        
 
63
        disp_maj_stat = gss_display_status(&disp_min_stat, maj_stat, GSS_C_GSS_CODE,
 
64
                           mech, &msg_ctx, &maj_error_message);
 
65
        disp_maj_stat = gss_display_status(&disp_min_stat, min_stat, GSS_C_MECH_CODE,
 
66
                           mech, &msg_ctx, &min_error_message);
 
67
        
 
68
        maj_error_string = talloc_strndup(mem_ctx, (char *)maj_error_message.value, maj_error_message.length);
 
69
 
 
70
        min_error_string = talloc_strndup(mem_ctx, (char *)min_error_message.value, min_error_message.length);
 
71
 
 
72
        ret = talloc_asprintf(mem_ctx, "%s: %s", maj_error_string, min_error_string);
 
73
 
 
74
        talloc_free(maj_error_string);
 
75
        talloc_free(min_error_string);
 
76
 
 
77
        gss_release_buffer(&disp_min_stat, &maj_error_message);
 
78
        gss_release_buffer(&disp_min_stat, &min_error_message);
 
79
 
 
80
        return ret;
 
81
}
 
82
 
 
83
 
 
84
static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
 
85
{
 
86
        OM_uint32 maj_stat, min_stat;
 
87
        
 
88
        if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
 
89
                maj_stat = gss_release_cred(&min_stat, 
 
90
                                            &gensec_gssapi_state->delegated_cred_handle);
 
91
        }
 
92
 
 
93
        if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
 
94
                maj_stat = gss_delete_sec_context (&min_stat,
 
95
                                                   &gensec_gssapi_state->gssapi_context,
 
96
                                                   GSS_C_NO_BUFFER);
 
97
        }
 
98
 
 
99
        if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
 
100
                maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->server_name);
 
101
        }
 
102
        if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
 
103
                maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
 
104
        }
 
105
 
 
106
        if (gensec_gssapi_state->lucid) {
 
107
                gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
 
108
        }
 
109
 
 
110
        return 0;
 
111
}
 
112
 
 
113
static NTSTATUS gensec_gssapi_init_lucid(struct gensec_gssapi_state *gensec_gssapi_state)
 
114
{
 
115
        OM_uint32 maj_stat, min_stat;
 
116
 
 
117
        if (gensec_gssapi_state->lucid) {
 
118
                return NT_STATUS_OK;
 
119
        }
 
120
 
 
121
        maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
 
122
                                                     &gensec_gssapi_state->gssapi_context,
 
123
                                                     1,
 
124
                                                     (void **)&gensec_gssapi_state->lucid);
 
125
        if (maj_stat != GSS_S_COMPLETE) {
 
126
                DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
 
127
                        gssapi_error_string(gensec_gssapi_state,
 
128
                                            maj_stat, min_stat,
 
129
                                            gensec_gssapi_state->gss_oid)));
 
130
                return NT_STATUS_INTERNAL_ERROR;
 
131
        }
 
132
 
 
133
        if (gensec_gssapi_state->lucid->version != 1) {
 
134
                DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
 
135
                        gensec_gssapi_state->lucid->version));
 
136
                gss_krb5_free_lucid_sec_context(&min_stat, gensec_gssapi_state->lucid);
 
137
                gensec_gssapi_state->lucid = NULL;
 
138
                return NT_STATUS_INTERNAL_ERROR;
 
139
        }
 
140
 
 
141
        return NT_STATUS_OK;
 
142
}
 
143
 
 
144
static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
 
145
{
 
146
        struct gensec_gssapi_state *gensec_gssapi_state;
 
147
        krb5_error_code ret;
 
148
        struct gsskrb5_send_to_kdc send_to_kdc;
 
149
 
 
150
        gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
 
151
        if (!gensec_gssapi_state) {
 
152
                return NT_STATUS_NO_MEMORY;
 
153
        }
 
154
        
 
155
        gensec_gssapi_state->gss_exchange_count = 0;
 
156
        gensec_gssapi_state->max_wrap_buf_size
 
157
                = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
 
158
                
 
159
        gensec_gssapi_state->sasl = false;
 
160
        gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
 
161
 
 
162
        gensec_security->private_data = gensec_gssapi_state;
 
163
 
 
164
        gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
 
165
        gensec_gssapi_state->server_name = GSS_C_NO_NAME;
 
166
        gensec_gssapi_state->client_name = GSS_C_NO_NAME;
 
167
        gensec_gssapi_state->lucid = NULL;
 
168
 
 
169
        /* TODO: Fill in channel bindings */
 
170
        gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
 
171
        
 
172
        gensec_gssapi_state->want_flags = 0;
 
173
        if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
 
174
                gensec_gssapi_state->want_flags |= GSS_C_MUTUAL_FLAG;
 
175
        }
 
176
        if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", true)) {
 
177
                gensec_gssapi_state->want_flags |= GSS_C_DELEG_FLAG;
 
178
        }
 
179
        if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
 
180
                gensec_gssapi_state->want_flags |= GSS_C_REPLAY_FLAG;
 
181
        }
 
182
        if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
 
183
                gensec_gssapi_state->want_flags |= GSS_C_SEQUENCE_FLAG;
 
184
        }
 
185
 
 
186
        gensec_gssapi_state->got_flags = 0;
 
187
 
 
188
        gensec_gssapi_state->session_key = data_blob(NULL, 0);
 
189
        gensec_gssapi_state->pac = data_blob(NULL, 0);
 
190
 
 
191
        gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
 
192
        gensec_gssapi_state->sig_size = 0;
 
193
 
 
194
        talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
 
195
 
 
196
        if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 
197
                gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
 
198
        }
 
199
        if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
 
200
                gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
 
201
        }
 
202
        if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
 
203
                gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
 
204
        }
 
205
 
 
206
        gensec_gssapi_state->gss_oid = GSS_C_NULL_OID;
 
207
        
 
208
        send_to_kdc.func = smb_krb5_send_and_recv_func;
 
209
        send_to_kdc.ptr = gensec_security->event_ctx;
 
210
 
 
211
        ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
 
212
        if (ret) {
 
213
                DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
 
214
                talloc_free(gensec_gssapi_state);
 
215
                return NT_STATUS_INTERNAL_ERROR;
 
216
        }
 
217
        if (lp_realm(gensec_security->settings->lp_ctx) && *lp_realm(gensec_security->settings->lp_ctx)) {
 
218
                char *upper_realm = strupper_talloc(gensec_gssapi_state, lp_realm(gensec_security->settings->lp_ctx));
 
219
                if (!upper_realm) {
 
220
                        DEBUG(1,("gensec_krb5_start: could not uppercase realm: %s\n", lp_realm(gensec_security->settings->lp_ctx)));
 
221
                        talloc_free(gensec_gssapi_state);
 
222
                        return NT_STATUS_NO_MEMORY;
 
223
                }
 
224
                ret = gsskrb5_set_default_realm(upper_realm);
 
225
                talloc_free(upper_realm);
 
226
                if (ret) {
 
227
                        DEBUG(1,("gensec_krb5_start: gsskrb5_set_default_realm failed\n"));
 
228
                        talloc_free(gensec_gssapi_state);
 
229
                        return NT_STATUS_INTERNAL_ERROR;
 
230
                }
 
231
        }
 
232
 
 
233
        /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
 
234
        ret = gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security->settings, "krb5", "set_dns_canonicalize", false));
 
235
        if (ret) {
 
236
                DEBUG(1,("gensec_krb5_start: gsskrb5_set_dns_canonicalize failed\n"));
 
237
                talloc_free(gensec_gssapi_state);
 
238
                return NT_STATUS_INTERNAL_ERROR;
 
239
        }
 
240
 
 
241
        ret = smb_krb5_init_context(gensec_gssapi_state, 
 
242
                                    gensec_security->event_ctx,
 
243
                                    gensec_security->settings->lp_ctx,
 
244
                                    &gensec_gssapi_state->smb_krb5_context);
 
245
        if (ret) {
 
246
                DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
 
247
                         error_message(ret)));
 
248
                talloc_free(gensec_gssapi_state);
 
249
                return NT_STATUS_INTERNAL_ERROR;
 
250
        }
 
251
        return NT_STATUS_OK;
 
252
}
 
253
 
 
254
static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
 
255
{
 
256
        NTSTATUS nt_status;
 
257
        int ret;
 
258
        struct gensec_gssapi_state *gensec_gssapi_state;
 
259
        struct cli_credentials *machine_account;
 
260
        struct gssapi_creds_container *gcc;
 
261
 
 
262
        nt_status = gensec_gssapi_start(gensec_security);
 
263
        if (!NT_STATUS_IS_OK(nt_status)) {
 
264
                return nt_status;
 
265
        }
 
266
 
 
267
        gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
268
 
 
269
        machine_account = gensec_get_credentials(gensec_security);
 
270
        
 
271
        if (!machine_account) {
 
272
                DEBUG(3, ("No machine account credentials specified\n"));
 
273
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
274
        } else {
 
275
                ret = cli_credentials_get_server_gss_creds(machine_account, 
 
276
                                                           gensec_security->event_ctx, 
 
277
                                                           gensec_security->settings->lp_ctx, &gcc);
 
278
                if (ret) {
 
279
                        DEBUG(1, ("Aquiring acceptor credentials failed: %s\n", 
 
280
                                  error_message(ret)));
 
281
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
 
282
                }
 
283
        }
 
284
 
 
285
        gensec_gssapi_state->server_cred = gcc;
 
286
        return NT_STATUS_OK;
 
287
 
 
288
}
 
289
 
 
290
static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
 
291
{
 
292
        NTSTATUS nt_status;
 
293
        struct gensec_gssapi_state *gensec_gssapi_state;
 
294
        nt_status = gensec_gssapi_server_start(gensec_security);
 
295
 
 
296
        if (NT_STATUS_IS_OK(nt_status)) {
 
297
                gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
298
                gensec_gssapi_state->sasl = true;
 
299
        }
 
300
        return nt_status;
 
301
}
 
302
 
 
303
static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
 
304
{
 
305
        struct gensec_gssapi_state *gensec_gssapi_state;
 
306
        struct cli_credentials *creds = gensec_get_credentials(gensec_security);
 
307
        krb5_error_code ret;
 
308
        NTSTATUS nt_status;
 
309
        gss_buffer_desc name_token;
 
310
        gss_OID name_type;
 
311
        OM_uint32 maj_stat, min_stat;
 
312
        const char *hostname = gensec_get_target_hostname(gensec_security);
 
313
        const char *principal;
 
314
        struct gssapi_creds_container *gcc;
 
315
 
 
316
        if (!hostname) {
 
317
                DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
 
318
                return NT_STATUS_INVALID_PARAMETER;
 
319
        }
 
320
        if (is_ipaddress(hostname)) {
 
321
                DEBUG(2, ("Cannot do GSSAPI to an IP address\n"));
 
322
                return NT_STATUS_INVALID_PARAMETER;
 
323
        }
 
324
        if (strcmp(hostname, "localhost") == 0) {
 
325
                DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n"));
 
326
                return NT_STATUS_INVALID_PARAMETER;
 
327
        }
 
328
 
 
329
        nt_status = gensec_gssapi_start(gensec_security);
 
330
        if (!NT_STATUS_IS_OK(nt_status)) {
 
331
                return nt_status;
 
332
        }
 
333
 
 
334
        gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
335
 
 
336
        gensec_gssapi_state->gss_oid = gss_mech_krb5;
 
337
 
 
338
        principal = gensec_get_target_principal(gensec_security);
 
339
        if (principal && lp_client_use_spnego_principal(gensec_security->settings->lp_ctx)) {
 
340
                name_type = GSS_C_NULL_OID;
 
341
        } else {
 
342
                principal = talloc_asprintf(gensec_gssapi_state, "%s@%s", 
 
343
                                            gensec_get_target_service(gensec_security), 
 
344
                                            hostname);
 
345
 
 
346
                name_type = GSS_C_NT_HOSTBASED_SERVICE;
 
347
        }               
 
348
        name_token.value  = discard_const_p(uint8_t, principal);
 
349
        name_token.length = strlen(principal);
 
350
 
 
351
 
 
352
        maj_stat = gss_import_name (&min_stat,
 
353
                                    &name_token,
 
354
                                    name_type,
 
355
                                    &gensec_gssapi_state->server_name);
 
356
        if (maj_stat) {
 
357
                DEBUG(2, ("GSS Import name of %s failed: %s\n",
 
358
                          (char *)name_token.value,
 
359
                          gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
360
                return NT_STATUS_INVALID_PARAMETER;
 
361
        }
 
362
 
 
363
        ret = cli_credentials_get_client_gss_creds(creds, 
 
364
                                                   gensec_security->event_ctx, 
 
365
                                                   gensec_security->settings->lp_ctx, &gcc);
 
366
        switch (ret) {
 
367
        case 0:
 
368
                break;
 
369
        case KRB5KDC_ERR_PREAUTH_FAILED:
 
370
                return NT_STATUS_LOGON_FAILURE;
 
371
        case KRB5_KDC_UNREACH:
 
372
                DEBUG(3, ("Cannot reach a KDC we require to contact %s\n", principal));
 
373
                return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 
374
        default:
 
375
                DEBUG(1, ("Aquiring initiator credentials failed\n"));
 
376
                return NT_STATUS_UNSUCCESSFUL;
 
377
        }
 
378
 
 
379
        gensec_gssapi_state->client_cred = gcc;
 
380
        if (!talloc_reference(gensec_gssapi_state, gcc)) {
 
381
                return NT_STATUS_NO_MEMORY;
 
382
        }
 
383
        
 
384
        return NT_STATUS_OK;
 
385
}
 
386
 
 
387
static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
 
388
{
 
389
        NTSTATUS nt_status;
 
390
        struct gensec_gssapi_state *gensec_gssapi_state;
 
391
        nt_status = gensec_gssapi_client_start(gensec_security);
 
392
 
 
393
        if (NT_STATUS_IS_OK(nt_status)) {
 
394
                gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
395
                gensec_gssapi_state->sasl = true;
 
396
        }
 
397
        return nt_status;
 
398
}
 
399
 
 
400
 
 
401
/**
 
402
 * Check if the packet is one for this mechansim
 
403
 * 
 
404
 * @param gensec_security GENSEC state
 
405
 * @param in The request, as a DATA_BLOB
 
406
 * @return Error, INVALID_PARAMETER if it's not a packet for us
 
407
 *                or NT_STATUS_OK if the packet is ok. 
 
408
 */
 
409
 
 
410
static NTSTATUS gensec_gssapi_magic(struct gensec_security *gensec_security, 
 
411
                                    const DATA_BLOB *in) 
 
412
{
 
413
        if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
 
414
                return NT_STATUS_OK;
 
415
        } else {
 
416
                return NT_STATUS_INVALID_PARAMETER;
 
417
        }
 
418
}
 
419
 
 
420
 
 
421
/**
 
422
 * Next state function for the GSSAPI GENSEC mechanism
 
423
 * 
 
424
 * @param gensec_gssapi_state GSSAPI State
 
425
 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
 
426
 * @param in The request, as a DATA_BLOB
 
427
 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
 
428
 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
 
429
 *                or NT_STATUS_OK if the user is authenticated. 
 
430
 */
 
431
 
 
432
static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, 
 
433
                                   TALLOC_CTX *out_mem_ctx, 
 
434
                                   const DATA_BLOB in, DATA_BLOB *out) 
 
435
{
 
436
        struct gensec_gssapi_state *gensec_gssapi_state
 
437
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
438
        NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
 
439
        OM_uint32 maj_stat, min_stat;
 
440
        OM_uint32 min_stat2;
 
441
        gss_buffer_desc input_token, output_token;
 
442
        gss_OID gss_oid_p = NULL;
 
443
        input_token.length = in.length;
 
444
        input_token.value = in.data;
 
445
 
 
446
        switch (gensec_gssapi_state->sasl_state) {
 
447
        case STAGE_GSS_NEG:
 
448
        {
 
449
                switch (gensec_security->gensec_role) {
 
450
                case GENSEC_CLIENT:
 
451
                {
 
452
                        maj_stat = gss_init_sec_context(&min_stat, 
 
453
                                                        gensec_gssapi_state->client_cred->creds,
 
454
                                                        &gensec_gssapi_state->gssapi_context, 
 
455
                                                        gensec_gssapi_state->server_name, 
 
456
                                                        gensec_gssapi_state->gss_oid,
 
457
                                                        gensec_gssapi_state->want_flags, 
 
458
                                                        0, 
 
459
                                                        gensec_gssapi_state->input_chan_bindings,
 
460
                                                        &input_token, 
 
461
                                                        &gss_oid_p,
 
462
                                                        &output_token, 
 
463
                                                        &gensec_gssapi_state->got_flags, /* ret flags */
 
464
                                                        NULL);
 
465
                        if (gss_oid_p) {
 
466
                                gensec_gssapi_state->gss_oid = gss_oid_p;
 
467
                        }
 
468
                        break;
 
469
                }
 
470
                case GENSEC_SERVER:
 
471
                {
 
472
                        maj_stat = gss_accept_sec_context(&min_stat, 
 
473
                                                          &gensec_gssapi_state->gssapi_context, 
 
474
                                                          gensec_gssapi_state->server_cred->creds,
 
475
                                                          &input_token, 
 
476
                                                          gensec_gssapi_state->input_chan_bindings,
 
477
                                                          &gensec_gssapi_state->client_name, 
 
478
                                                          &gss_oid_p,
 
479
                                                          &output_token, 
 
480
                                                          &gensec_gssapi_state->got_flags, 
 
481
                                                          NULL, 
 
482
                                                          &gensec_gssapi_state->delegated_cred_handle);
 
483
                        if (gss_oid_p) {
 
484
                                gensec_gssapi_state->gss_oid = gss_oid_p;
 
485
                        }
 
486
                        break;
 
487
                }
 
488
                default:
 
489
                        return NT_STATUS_INVALID_PARAMETER;
 
490
                        
 
491
                }
 
492
 
 
493
                gensec_gssapi_state->gss_exchange_count++;
 
494
 
 
495
                if (maj_stat == GSS_S_COMPLETE) {
 
496
                        *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 
497
                        gss_release_buffer(&min_stat2, &output_token);
 
498
                        
 
499
                        if (gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG) {
 
500
                                DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
 
501
                        } else {
 
502
                                DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
 
503
                        }
 
504
 
 
505
                        /* We may have been invoked as SASL, so there
 
506
                         * is more work to do */
 
507
                        if (gensec_gssapi_state->sasl) {
 
508
                                /* Due to a very subtle interaction
 
509
                                 * with SASL and the LDAP libs, we
 
510
                                 * must ensure the data pointer is 
 
511
                                 * != NULL, but the length is 0.  
 
512
                                 *
 
513
                                 * This ensures we send a 'zero
 
514
                                 * length' (rather than NULL) response 
 
515
                                 */
 
516
                                
 
517
                                if (!out->data) {
 
518
                                        out->data = (uint8_t *)talloc_strdup(out_mem_ctx, "\0");
 
519
                                }
 
520
 
 
521
                                gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
 
522
                                return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
523
                        } else {
 
524
                                gensec_gssapi_state->sasl_state = STAGE_DONE;
 
525
 
 
526
                                if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
527
                                        DEBUG(5, ("GSSAPI Connection will be cryptographicly sealed\n"));
 
528
                                } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
529
                                        DEBUG(5, ("GSSAPI Connection will be cryptographicly signed\n"));
 
530
                                } else {
 
531
                                        DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
 
532
                                }
 
533
 
 
534
                                return NT_STATUS_OK;
 
535
                        }
 
536
                } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
 
537
                        *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 
538
                        gss_release_buffer(&min_stat2, &output_token);
 
539
                        
 
540
                        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
541
                } else if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
 
542
                        switch (min_stat) {
 
543
                        case KRB5_KDC_UNREACH:
 
544
                                DEBUG(3, ("Cannot reach a KDC we require: %s\n",
 
545
                                          gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
546
                                return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 
547
                        case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
 
548
                                DEBUG(3, ("Server is not registered with our KDC: %s\n", 
 
549
                                          gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
550
                                return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
 
551
                        case KRB5KRB_AP_ERR_MSG_TYPE:
 
552
                                /* garbage input, possibly from the auto-mech detection */
 
553
                                return NT_STATUS_INVALID_PARAMETER;
 
554
                        default:
 
555
                                DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n", 
 
556
                                          gensec_gssapi_state->gss_exchange_count,
 
557
                                          gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
558
                                return nt_status;
 
559
                        }
 
560
                } else {
 
561
                        DEBUG(1, ("GSS Update(%d) failed: %s\n", 
 
562
                                  gensec_gssapi_state->gss_exchange_count,
 
563
                                  gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
564
                        return nt_status;
 
565
                }
 
566
                break;
 
567
        }
 
568
 
 
569
        /* These last two stages are only done if we were invoked as SASL */
 
570
        case STAGE_SASL_SSF_NEG:
 
571
        {
 
572
                switch (gensec_security->gensec_role) {
 
573
                case GENSEC_CLIENT:
 
574
                {
 
575
                        uint8_t maxlength_proposed[4]; 
 
576
                        uint8_t maxlength_accepted[4]; 
 
577
                        uint8_t security_supported;
 
578
                        int conf_state;
 
579
                        gss_qop_t qop_state;
 
580
                        input_token.length = in.length;
 
581
                        input_token.value = in.data;
 
582
 
 
583
                        /* As a client, we have just send a
 
584
                         * zero-length blob to the server (after the
 
585
                         * normal GSSAPI exchange), and it has replied
 
586
                         * with it's SASL negotiation */
 
587
                        
 
588
                        maj_stat = gss_unwrap(&min_stat, 
 
589
                                              gensec_gssapi_state->gssapi_context, 
 
590
                                              &input_token,
 
591
                                              &output_token, 
 
592
                                              &conf_state,
 
593
                                              &qop_state);
 
594
                        if (GSS_ERROR(maj_stat)) {
 
595
                                DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
 
596
                                          gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
597
                                return NT_STATUS_ACCESS_DENIED;
 
598
                        }
 
599
                        
 
600
                        if (output_token.length < 4) {
 
601
                                return NT_STATUS_INVALID_PARAMETER;
 
602
                        }
 
603
 
 
604
                        memcpy(maxlength_proposed, output_token.value, 4);
 
605
                        gss_release_buffer(&min_stat, &output_token);
 
606
 
 
607
                        /* first byte is the proposed security */
 
608
                        security_supported = maxlength_proposed[0];
 
609
                        maxlength_proposed[0] = '\0';
 
610
                        
 
611
                        /* Rest is the proposed max wrap length */
 
612
                        gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0), 
 
613
                                                                     gensec_gssapi_state->max_wrap_buf_size);
 
614
                        gensec_gssapi_state->sasl_protection = 0;
 
615
                        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
616
                                if (security_supported & NEG_SEAL) {
 
617
                                        gensec_gssapi_state->sasl_protection |= NEG_SEAL;
 
618
                                }
 
619
                        } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
620
                                if (security_supported & NEG_SIGN) {
 
621
                                        gensec_gssapi_state->sasl_protection |= NEG_SIGN;
 
622
                                }
 
623
                        } else if (security_supported & NEG_NONE) {
 
624
                                gensec_gssapi_state->sasl_protection |= NEG_NONE;
 
625
                        } else {
 
626
                                DEBUG(1, ("Remote server does not support unprotected connections"));
 
627
                                return NT_STATUS_ACCESS_DENIED;
 
628
                        }
 
629
 
 
630
                        /* Send back the negotiated max length */
 
631
 
 
632
                        RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
 
633
 
 
634
                        maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
 
635
                        
 
636
                        input_token.value = maxlength_accepted;
 
637
                        input_token.length = sizeof(maxlength_accepted);
 
638
 
 
639
                        maj_stat = gss_wrap(&min_stat, 
 
640
                                            gensec_gssapi_state->gssapi_context, 
 
641
                                            false,
 
642
                                            GSS_C_QOP_DEFAULT,
 
643
                                            &input_token,
 
644
                                            &conf_state,
 
645
                                            &output_token);
 
646
                        if (GSS_ERROR(maj_stat)) {
 
647
                                DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
 
648
                                          gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
649
                                return NT_STATUS_ACCESS_DENIED;
 
650
                        }
 
651
                        
 
652
                        *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 
653
                        gss_release_buffer(&min_stat, &output_token);
 
654
 
 
655
                        /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
 
656
                        gensec_gssapi_state->sasl_state = STAGE_DONE;
 
657
 
 
658
                        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
659
                                DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly sealed\n"));
 
660
                        } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
661
                                DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographicly signed\n"));
 
662
                        } else {
 
663
                                DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographicly protection\n"));
 
664
                        }
 
665
 
 
666
                        return NT_STATUS_OK;
 
667
                }
 
668
                case GENSEC_SERVER:
 
669
                {
 
670
                        uint8_t maxlength_proposed[4]; 
 
671
                        uint8_t security_supported = 0x0;
 
672
                        int conf_state;
 
673
 
 
674
                        /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
 
675
                        if (in.length != 0) {
 
676
                                DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
 
677
                        }
 
678
                        
 
679
                        /* Give the client some idea what we will support */
 
680
                          
 
681
                        RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
 
682
                        /* first byte is the proposed security */
 
683
                        maxlength_proposed[0] = '\0';
 
684
                        
 
685
                        gensec_gssapi_state->sasl_protection = 0;
 
686
                        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
687
                                security_supported |= NEG_SEAL;
 
688
                        } 
 
689
                        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
690
                                security_supported |= NEG_SIGN;
 
691
                        }
 
692
                        if (security_supported == 0) {
 
693
                                /* If we don't support anything, this must be 0 */
 
694
                                RSIVAL(maxlength_proposed, 0, 0x0);
 
695
                        }
 
696
 
 
697
                        /* TODO:  We may not wish to support this */
 
698
                        security_supported |= NEG_NONE;
 
699
                        maxlength_proposed[0] = security_supported;
 
700
                        
 
701
                        input_token.value = maxlength_proposed;
 
702
                        input_token.length = sizeof(maxlength_proposed);
 
703
 
 
704
                        maj_stat = gss_wrap(&min_stat, 
 
705
                                            gensec_gssapi_state->gssapi_context, 
 
706
                                            false,
 
707
                                            GSS_C_QOP_DEFAULT,
 
708
                                            &input_token,
 
709
                                            &conf_state,
 
710
                                            &output_token);
 
711
                        if (GSS_ERROR(maj_stat)) {
 
712
                                DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", 
 
713
                                          gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
714
                                return NT_STATUS_ACCESS_DENIED;
 
715
                        }
 
716
                        
 
717
                        *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
 
718
                        gss_release_buffer(&min_stat, &output_token);
 
719
 
 
720
                        gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
 
721
                        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
722
                }
 
723
                default:
 
724
                        return NT_STATUS_INVALID_PARAMETER;
 
725
                        
 
726
                }
 
727
        }
 
728
        /* This is s server-only stage */
 
729
        case STAGE_SASL_SSF_ACCEPT:
 
730
        {
 
731
                uint8_t maxlength_accepted[4]; 
 
732
                uint8_t security_accepted;
 
733
                int conf_state;
 
734
                gss_qop_t qop_state;
 
735
                input_token.length = in.length;
 
736
                input_token.value = in.data;
 
737
                        
 
738
                maj_stat = gss_unwrap(&min_stat, 
 
739
                                      gensec_gssapi_state->gssapi_context, 
 
740
                                      &input_token,
 
741
                                      &output_token, 
 
742
                                      &conf_state,
 
743
                                      &qop_state);
 
744
                if (GSS_ERROR(maj_stat)) {
 
745
                        DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n", 
 
746
                                  gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
747
                        return NT_STATUS_ACCESS_DENIED;
 
748
                }
 
749
                        
 
750
                if (output_token.length < 4) {
 
751
                        return NT_STATUS_INVALID_PARAMETER;
 
752
                }
 
753
 
 
754
                memcpy(maxlength_accepted, output_token.value, 4);
 
755
                gss_release_buffer(&min_stat, &output_token);
 
756
                
 
757
                /* first byte is the proposed security */
 
758
                security_accepted = maxlength_accepted[0];
 
759
                maxlength_accepted[0] = '\0';
 
760
                
 
761
                /* Rest is the proposed max wrap length */
 
762
                gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0), 
 
763
                                                             gensec_gssapi_state->max_wrap_buf_size);
 
764
 
 
765
                gensec_gssapi_state->sasl_protection = 0;
 
766
                if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
767
                        if (security_accepted & NEG_SEAL) {
 
768
                                gensec_gssapi_state->sasl_protection |= NEG_SEAL;
 
769
                        }
 
770
                } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
771
                        if (security_accepted & NEG_SIGN) {
 
772
                                gensec_gssapi_state->sasl_protection |= NEG_SIGN;
 
773
                        }
 
774
                } else if (security_accepted & NEG_NONE) {
 
775
                        gensec_gssapi_state->sasl_protection |= NEG_NONE;
 
776
                } else {
 
777
                        DEBUG(1, ("Remote client does not support unprotected connections, but we failed to negotiate anything better"));
 
778
                        return NT_STATUS_ACCESS_DENIED;
 
779
                }
 
780
 
 
781
                /* quirk:  This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
 
782
                gensec_gssapi_state->sasl_state = STAGE_DONE;
 
783
                if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 
784
                        DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly sealed\n"));
 
785
                } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 
786
                        DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographicly signed\n"));
 
787
                } else {
 
788
                        DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
 
789
                }
 
790
 
 
791
                *out = data_blob(NULL, 0);
 
792
                return NT_STATUS_OK;    
 
793
        }
 
794
        default:
 
795
                return NT_STATUS_INVALID_PARAMETER;
 
796
        }
 
797
}
 
798
 
 
799
static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security, 
 
800
                                   TALLOC_CTX *mem_ctx, 
 
801
                                   const DATA_BLOB *in, 
 
802
                                   DATA_BLOB *out)
 
803
{
 
804
        struct gensec_gssapi_state *gensec_gssapi_state
 
805
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
806
        OM_uint32 maj_stat, min_stat;
 
807
        gss_buffer_desc input_token, output_token;
 
808
        int conf_state;
 
809
        input_token.length = in->length;
 
810
        input_token.value = in->data;
 
811
 
 
812
        maj_stat = gss_wrap(&min_stat, 
 
813
                            gensec_gssapi_state->gssapi_context, 
 
814
                            gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 
815
                            GSS_C_QOP_DEFAULT,
 
816
                            &input_token,
 
817
                            &conf_state,
 
818
                            &output_token);
 
819
        if (GSS_ERROR(maj_stat)) {
 
820
                DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", 
 
821
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
822
                return NT_STATUS_ACCESS_DENIED;
 
823
        }
 
824
 
 
825
        *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
 
826
        gss_release_buffer(&min_stat, &output_token);
 
827
 
 
828
        if (gensec_gssapi_state->sasl) {
 
829
                size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
 
830
                if (max_wrapped_size < out->length) {
 
831
                        DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
 
832
                                  (unsigned)in->length, 
 
833
                                  (unsigned)out->length, 
 
834
                                  (unsigned int)max_wrapped_size));
 
835
                        return NT_STATUS_INVALID_PARAMETER;
 
836
                }
 
837
        }
 
838
        
 
839
        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 
840
            && !conf_state) {
 
841
                return NT_STATUS_ACCESS_DENIED;
 
842
        }
 
843
        return NT_STATUS_OK;
 
844
}
 
845
 
 
846
static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security, 
 
847
                                     TALLOC_CTX *mem_ctx, 
 
848
                                     const DATA_BLOB *in, 
 
849
                                     DATA_BLOB *out)
 
850
{
 
851
        struct gensec_gssapi_state *gensec_gssapi_state
 
852
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
853
        OM_uint32 maj_stat, min_stat;
 
854
        gss_buffer_desc input_token, output_token;
 
855
        int conf_state;
 
856
        gss_qop_t qop_state;
 
857
        input_token.length = in->length;
 
858
        input_token.value = in->data;
 
859
        
 
860
        if (gensec_gssapi_state->sasl) {
 
861
                size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
 
862
                if (max_wrapped_size < in->length) {
 
863
                        DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
 
864
                        return NT_STATUS_INVALID_PARAMETER;
 
865
                }
 
866
        }
 
867
        
 
868
        maj_stat = gss_unwrap(&min_stat, 
 
869
                              gensec_gssapi_state->gssapi_context, 
 
870
                              &input_token,
 
871
                              &output_token, 
 
872
                              &conf_state,
 
873
                              &qop_state);
 
874
        if (GSS_ERROR(maj_stat)) {
 
875
                DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n", 
 
876
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
877
                return NT_STATUS_ACCESS_DENIED;
 
878
        }
 
879
 
 
880
        *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
 
881
        gss_release_buffer(&min_stat, &output_token);
 
882
        
 
883
        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 
884
            && !conf_state) {
 
885
                return NT_STATUS_ACCESS_DENIED;
 
886
        }
 
887
        return NT_STATUS_OK;
 
888
}
 
889
 
 
890
/* Find out the maximum input size negotiated on this connection */
 
891
 
 
892
static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security) 
 
893
{
 
894
        struct gensec_gssapi_state *gensec_gssapi_state
 
895
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
896
        OM_uint32 maj_stat, min_stat;
 
897
        OM_uint32 max_input_size;
 
898
 
 
899
        maj_stat = gss_wrap_size_limit(&min_stat, 
 
900
                                       gensec_gssapi_state->gssapi_context,
 
901
                                       gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 
902
                                       GSS_C_QOP_DEFAULT,
 
903
                                       gensec_gssapi_state->max_wrap_buf_size,
 
904
                                       &max_input_size);
 
905
        if (GSS_ERROR(maj_stat)) {
 
906
                TALLOC_CTX *mem_ctx = talloc_new(NULL); 
 
907
                DEBUG(1, ("gensec_gssapi_max_input_size: determinaing signature size with gss_wrap_size_limit failed: %s\n", 
 
908
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
909
                talloc_free(mem_ctx);
 
910
                return 0;
 
911
        }
 
912
 
 
913
        return max_input_size;
 
914
}
 
915
 
 
916
/* Find out the maximum output size negotiated on this connection */
 
917
static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security) 
 
918
{
 
919
        struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
 
920
        return gensec_gssapi_state->max_wrap_buf_size;
 
921
}
 
922
 
 
923
static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security, 
 
924
                                          TALLOC_CTX *mem_ctx, 
 
925
                                          uint8_t *data, size_t length, 
 
926
                                          const uint8_t *whole_pdu, size_t pdu_length, 
 
927
                                          DATA_BLOB *sig)
 
928
{
 
929
        struct gensec_gssapi_state *gensec_gssapi_state
 
930
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
931
        OM_uint32 maj_stat, min_stat;
 
932
        gss_buffer_desc input_token, output_token;
 
933
        int conf_state;
 
934
        ssize_t sig_length;
 
935
 
 
936
        input_token.length = length;
 
937
        input_token.value = data;
 
938
        
 
939
        maj_stat = gss_wrap(&min_stat, 
 
940
                            gensec_gssapi_state->gssapi_context,
 
941
                            gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
 
942
                            GSS_C_QOP_DEFAULT,
 
943
                            &input_token,
 
944
                            &conf_state,
 
945
                            &output_token);
 
946
        if (GSS_ERROR(maj_stat)) {
 
947
                DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap failed: %s\n", 
 
948
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
949
                return NT_STATUS_ACCESS_DENIED;
 
950
        }
 
951
 
 
952
        if (output_token.length < input_token.length) {
 
953
                DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n", 
 
954
                          (long)output_token.length, (long)length));
 
955
                return NT_STATUS_INTERNAL_ERROR;
 
956
        }
 
957
        sig_length = output_token.length - input_token.length;
 
958
 
 
959
        memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
 
960
        *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
 
961
 
 
962
        dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
 
963
        dump_data_pw("gensec_gssapi_seal_packet: clear\n", data, length);
 
964
        dump_data_pw("gensec_gssapi_seal_packet: sealed\n", ((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
 
965
 
 
966
        gss_release_buffer(&min_stat, &output_token);
 
967
 
 
968
        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 
969
            && !conf_state) {
 
970
                return NT_STATUS_ACCESS_DENIED;
 
971
        }
 
972
        return NT_STATUS_OK;
 
973
}
 
974
 
 
975
static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security, 
 
976
                                            TALLOC_CTX *mem_ctx, 
 
977
                                            uint8_t *data, size_t length, 
 
978
                                            const uint8_t *whole_pdu, size_t pdu_length,
 
979
                                            const DATA_BLOB *sig)
 
980
{
 
981
        struct gensec_gssapi_state *gensec_gssapi_state
 
982
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
983
        OM_uint32 maj_stat, min_stat;
 
984
        gss_buffer_desc input_token, output_token;
 
985
        int conf_state;
 
986
        gss_qop_t qop_state;
 
987
        DATA_BLOB in;
 
988
 
 
989
        dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig->data, sig->length);
 
990
 
 
991
        in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
 
992
 
 
993
        memcpy(in.data, sig->data, sig->length);
 
994
        memcpy(in.data + sig->length, data, length);
 
995
 
 
996
        input_token.length = in.length;
 
997
        input_token.value = in.data;
 
998
        
 
999
        maj_stat = gss_unwrap(&min_stat, 
 
1000
                              gensec_gssapi_state->gssapi_context, 
 
1001
                              &input_token,
 
1002
                              &output_token, 
 
1003
                              &conf_state,
 
1004
                              &qop_state);
 
1005
        if (GSS_ERROR(maj_stat)) {
 
1006
                DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n", 
 
1007
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1008
                return NT_STATUS_ACCESS_DENIED;
 
1009
        }
 
1010
 
 
1011
        if (output_token.length != length) {
 
1012
                return NT_STATUS_INTERNAL_ERROR;
 
1013
        }
 
1014
 
 
1015
        memcpy(data, output_token.value, length);
 
1016
 
 
1017
        gss_release_buffer(&min_stat, &output_token);
 
1018
        
 
1019
        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
 
1020
            && !conf_state) {
 
1021
                return NT_STATUS_ACCESS_DENIED;
 
1022
        }
 
1023
        return NT_STATUS_OK;
 
1024
}
 
1025
 
 
1026
static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security, 
 
1027
                                          TALLOC_CTX *mem_ctx, 
 
1028
                                          const uint8_t *data, size_t length, 
 
1029
                                          const uint8_t *whole_pdu, size_t pdu_length, 
 
1030
                                          DATA_BLOB *sig)
 
1031
{
 
1032
        struct gensec_gssapi_state *gensec_gssapi_state
 
1033
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1034
        OM_uint32 maj_stat, min_stat;
 
1035
        gss_buffer_desc input_token, output_token;
 
1036
 
 
1037
        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
 
1038
                input_token.length = pdu_length;
 
1039
                input_token.value = discard_const_p(uint8_t *, whole_pdu);
 
1040
        } else {
 
1041
                input_token.length = length;
 
1042
                input_token.value = discard_const_p(uint8_t *, data);
 
1043
        }
 
1044
 
 
1045
        maj_stat = gss_get_mic(&min_stat,
 
1046
                            gensec_gssapi_state->gssapi_context,
 
1047
                            GSS_C_QOP_DEFAULT,
 
1048
                            &input_token,
 
1049
                            &output_token);
 
1050
        if (GSS_ERROR(maj_stat)) {
 
1051
                DEBUG(1, ("GSS GetMic failed: %s\n",
 
1052
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1053
                return NT_STATUS_ACCESS_DENIED;
 
1054
        }
 
1055
 
 
1056
        *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
 
1057
 
 
1058
        dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
 
1059
 
 
1060
        gss_release_buffer(&min_stat, &output_token);
 
1061
 
 
1062
        return NT_STATUS_OK;
 
1063
}
 
1064
 
 
1065
static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security, 
 
1066
                                           TALLOC_CTX *mem_ctx, 
 
1067
                                           const uint8_t *data, size_t length, 
 
1068
                                           const uint8_t *whole_pdu, size_t pdu_length, 
 
1069
                                           const DATA_BLOB *sig)
 
1070
{
 
1071
        struct gensec_gssapi_state *gensec_gssapi_state
 
1072
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1073
        OM_uint32 maj_stat, min_stat;
 
1074
        gss_buffer_desc input_token;
 
1075
        gss_buffer_desc input_message;
 
1076
        gss_qop_t qop_state;
 
1077
 
 
1078
        dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig->data, sig->length);
 
1079
 
 
1080
        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
 
1081
                input_message.length = pdu_length;
 
1082
                input_message.value = discard_const(whole_pdu);
 
1083
        } else {
 
1084
                input_message.length = length;
 
1085
                input_message.value = discard_const(data);
 
1086
        }
 
1087
 
 
1088
        input_token.length = sig->length;
 
1089
        input_token.value = sig->data;
 
1090
 
 
1091
        maj_stat = gss_verify_mic(&min_stat,
 
1092
                              gensec_gssapi_state->gssapi_context, 
 
1093
                              &input_message,
 
1094
                              &input_token,
 
1095
                              &qop_state);
 
1096
        if (GSS_ERROR(maj_stat)) {
 
1097
                DEBUG(1, ("GSS VerifyMic failed: %s\n",
 
1098
                          gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1099
                return NT_STATUS_ACCESS_DENIED;
 
1100
        }
 
1101
 
 
1102
        return NT_STATUS_OK;
 
1103
}
 
1104
 
 
1105
/* Try to figure out what features we actually got on the connection */
 
1106
static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security, 
 
1107
                                       uint32_t feature) 
 
1108
{
 
1109
        struct gensec_gssapi_state *gensec_gssapi_state
 
1110
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1111
        if (feature & GENSEC_FEATURE_SIGN) {
 
1112
                /* If we are going GSSAPI SASL, then we honour the second negotiation */
 
1113
                if (gensec_gssapi_state->sasl 
 
1114
                    && gensec_gssapi_state->sasl_state == STAGE_DONE) {
 
1115
                        return ((gensec_gssapi_state->sasl_protection & NEG_SIGN) 
 
1116
                                && (gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG));
 
1117
                }
 
1118
                return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
 
1119
        }
 
1120
        if (feature & GENSEC_FEATURE_SEAL) {
 
1121
                /* If we are going GSSAPI SASL, then we honour the second negotiation */
 
1122
                if (gensec_gssapi_state->sasl 
 
1123
                    && gensec_gssapi_state->sasl_state == STAGE_DONE) {
 
1124
                        return ((gensec_gssapi_state->sasl_protection & NEG_SEAL) 
 
1125
                                 && (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG));
 
1126
                }
 
1127
                return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
 
1128
        }
 
1129
        if (feature & GENSEC_FEATURE_SESSION_KEY) {
 
1130
                /* Only for GSSAPI/Krb5 */
 
1131
                if (gss_oid_equal(gensec_gssapi_state->gss_oid, gss_mech_krb5)) {
 
1132
                        return true;
 
1133
                }
 
1134
        }
 
1135
        if (feature & GENSEC_FEATURE_DCE_STYLE) {
 
1136
                return gensec_gssapi_state->got_flags & GSS_C_DCE_STYLE;
 
1137
        }
 
1138
        if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
 
1139
                NTSTATUS status;
 
1140
 
 
1141
                if (!(gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG)) {
 
1142
                        return false;
 
1143
                }
 
1144
 
 
1145
                if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
 
1146
                        return true;
 
1147
                }
 
1148
                if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
 
1149
                        return false;
 
1150
                }
 
1151
 
 
1152
                status = gensec_gssapi_init_lucid(gensec_gssapi_state);
 
1153
                if (!NT_STATUS_IS_OK(status)) {
 
1154
                        return false;
 
1155
                }
 
1156
 
 
1157
                if (gensec_gssapi_state->lucid->protocol == 1) {
 
1158
                        return true;
 
1159
                }
 
1160
 
 
1161
                return false;
 
1162
        }
 
1163
        /* We can always do async (rather than strict request/reply) packets.  */
 
1164
        if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
 
1165
                return true;
 
1166
        }
 
1167
        return false;
 
1168
}
 
1169
 
 
1170
/*
 
1171
 * Extract the 'sesssion key' needed by SMB signing and ncacn_np 
 
1172
 * (for encrypting some passwords).
 
1173
 * 
 
1174
 * This breaks all the abstractions, but what do you expect...
 
1175
 */
 
1176
static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security, 
 
1177
                                          DATA_BLOB *session_key) 
 
1178
{
 
1179
        struct gensec_gssapi_state *gensec_gssapi_state
 
1180
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1181
        OM_uint32 maj_stat, min_stat;
 
1182
        krb5_keyblock *subkey;
 
1183
 
 
1184
        if (gensec_gssapi_state->sasl_state != STAGE_DONE) {
 
1185
                return NT_STATUS_NO_USER_SESSION_KEY;
 
1186
        }
 
1187
 
 
1188
        if (gensec_gssapi_state->session_key.data) {
 
1189
                *session_key = gensec_gssapi_state->session_key;
 
1190
                return NT_STATUS_OK;
 
1191
        }
 
1192
 
 
1193
        maj_stat = gsskrb5_get_subkey(&min_stat,
 
1194
                                      gensec_gssapi_state->gssapi_context,
 
1195
                                      &subkey);
 
1196
        if (maj_stat != 0) {
 
1197
                DEBUG(1, ("NO session key for this mech\n"));
 
1198
                return NT_STATUS_NO_USER_SESSION_KEY;
 
1199
        }
 
1200
        
 
1201
        DEBUG(10, ("Got KRB5 session key of length %d%s\n",
 
1202
                   (int)KRB5_KEY_LENGTH(subkey),
 
1203
                   (gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":""));
 
1204
        *session_key = data_blob_talloc(gensec_gssapi_state,
 
1205
                                        KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
 
1206
        krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);
 
1207
        gensec_gssapi_state->session_key = *session_key;
 
1208
        dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
 
1209
 
 
1210
        return NT_STATUS_OK;
 
1211
}
 
1212
 
 
1213
/* Get some basic (and authorization) information about the user on
 
1214
 * this session.  This uses either the PAC (if present) or a local
 
1215
 * database lookup */
 
1216
static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
 
1217
                                           struct auth_session_info **_session_info) 
 
1218
{
 
1219
        NTSTATUS nt_status;
 
1220
        TALLOC_CTX *mem_ctx;
 
1221
        struct gensec_gssapi_state *gensec_gssapi_state
 
1222
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1223
        struct auth_serversupplied_info *server_info = NULL;
 
1224
        struct auth_session_info *session_info = NULL;
 
1225
        OM_uint32 maj_stat, min_stat;
 
1226
        gss_buffer_desc pac;
 
1227
        DATA_BLOB pac_blob;
 
1228
        
 
1229
        if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
 
1230
            || (memcmp(gensec_gssapi_state->gss_oid->elements, gss_mech_krb5->elements, 
 
1231
                       gensec_gssapi_state->gss_oid->length) != 0)) {
 
1232
                DEBUG(1, ("NO session info available for this mech\n"));
 
1233
                return NT_STATUS_INVALID_PARAMETER;
 
1234
        }
 
1235
                
 
1236
        mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context"); 
 
1237
        NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
 
1238
 
 
1239
        maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 
 
1240
                                                               gensec_gssapi_state->gssapi_context, 
 
1241
                                                               KRB5_AUTHDATA_WIN2K_PAC,
 
1242
                                                               &pac);
 
1243
        
 
1244
        
 
1245
        if (maj_stat == 0) {
 
1246
                pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);
 
1247
                gss_release_buffer(&min_stat, &pac);
 
1248
 
 
1249
        } else {
 
1250
                pac_blob = data_blob(NULL, 0);
 
1251
        }
 
1252
        
 
1253
        /* IF we have the PAC - otherwise we need to get this
 
1254
         * data from elsewere - local ldb, or (TODO) lookup of some
 
1255
         * kind... 
 
1256
         */
 
1257
        if (pac_blob.length) {
 
1258
                nt_status = kerberos_pac_blob_to_server_info(mem_ctx, 
 
1259
                                                             gensec_security->settings->iconv_convenience,
 
1260
                                                             pac_blob, 
 
1261
                                                             gensec_gssapi_state->smb_krb5_context->krb5_context,
 
1262
                                                             &server_info);
 
1263
                if (!NT_STATUS_IS_OK(nt_status)) {
 
1264
                        talloc_free(mem_ctx);
 
1265
                        return nt_status;
 
1266
                }
 
1267
        } else {
 
1268
                gss_buffer_desc name_token;
 
1269
                char *principal_string;
 
1270
 
 
1271
                maj_stat = gss_display_name (&min_stat,
 
1272
                                             gensec_gssapi_state->client_name,
 
1273
                                             &name_token,
 
1274
                                             NULL);
 
1275
                if (GSS_ERROR(maj_stat)) {
 
1276
                        DEBUG(1, ("GSS display_name failed: %s\n", 
 
1277
                                  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1278
                        talloc_free(mem_ctx);
 
1279
                        return NT_STATUS_FOOBAR;
 
1280
                }
 
1281
                
 
1282
                principal_string = talloc_strndup(mem_ctx, 
 
1283
                                                  (const char *)name_token.value, 
 
1284
                                                  name_token.length);
 
1285
                
 
1286
                gss_release_buffer(&min_stat, &name_token);
 
1287
                
 
1288
                if (!principal_string) {
 
1289
                        talloc_free(mem_ctx);
 
1290
                        return NT_STATUS_NO_MEMORY;
 
1291
                }
 
1292
 
 
1293
                if (gensec_security->auth_context && 
 
1294
                    !gensec_setting_bool(gensec_security->settings, "gensec", "require_pac", false)) {
 
1295
                        DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n",
 
1296
                                  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1297
                        nt_status = gensec_security->auth_context->get_server_info_principal(mem_ctx, 
 
1298
                                                                                             gensec_security->auth_context, 
 
1299
                                                                                             principal_string,
 
1300
                                                                                             &server_info);
 
1301
                        
 
1302
                        if (!NT_STATUS_IS_OK(nt_status)) {
 
1303
                                talloc_free(mem_ctx);
 
1304
                                return nt_status;
 
1305
                        }
 
1306
                } else {
 
1307
                        DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n",
 
1308
                                  principal_string,
 
1309
                                  gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
 
1310
                        return NT_STATUS_ACCESS_DENIED;
 
1311
                }
 
1312
        }
 
1313
 
 
1314
        /* references the server_info into the session_info */
 
1315
        nt_status = auth_generate_session_info(mem_ctx, gensec_security->event_ctx, 
 
1316
                                               gensec_security->settings->lp_ctx, server_info, &session_info);
 
1317
        if (!NT_STATUS_IS_OK(nt_status)) {
 
1318
                talloc_free(mem_ctx);
 
1319
                return nt_status;
 
1320
        }
 
1321
 
 
1322
        nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
 
1323
        if (!NT_STATUS_IS_OK(nt_status)) {
 
1324
                talloc_free(mem_ctx);
 
1325
                return nt_status;
 
1326
        }
 
1327
 
 
1328
        if (!(gensec_gssapi_state->got_flags & GSS_C_DELEG_FLAG)) {
 
1329
                DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
 
1330
        } else {
 
1331
                krb5_error_code ret;
 
1332
                DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
 
1333
                session_info->credentials = cli_credentials_init(session_info);
 
1334
                if (!session_info->credentials) {
 
1335
                        talloc_free(mem_ctx);
 
1336
                        return NT_STATUS_NO_MEMORY;
 
1337
                }
 
1338
 
 
1339
                cli_credentials_set_conf(session_info->credentials, gensec_security->settings->lp_ctx);
 
1340
                /* Just so we don't segfault trying to get at a username */
 
1341
                cli_credentials_set_anonymous(session_info->credentials);
 
1342
                
 
1343
                ret = cli_credentials_set_client_gss_creds(session_info->credentials, 
 
1344
                                                           gensec_security->event_ctx,
 
1345
                                                           gensec_security->settings->lp_ctx, 
 
1346
                                                           gensec_gssapi_state->delegated_cred_handle,
 
1347
                                                           CRED_SPECIFIED);
 
1348
                if (ret) {
 
1349
                        talloc_free(mem_ctx);
 
1350
                        return NT_STATUS_NO_MEMORY;
 
1351
                }
 
1352
                
 
1353
                /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
 
1354
                cli_credentials_set_kerberos_state(session_info->credentials, CRED_MUST_USE_KERBEROS);
 
1355
 
 
1356
                /* It has been taken from this place... */
 
1357
                gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
 
1358
        }
 
1359
        talloc_steal(gensec_gssapi_state, session_info);
 
1360
        talloc_free(mem_ctx);
 
1361
        *_session_info = session_info;
 
1362
 
 
1363
        return NT_STATUS_OK;
 
1364
}
 
1365
 
 
1366
static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
 
1367
{
 
1368
        struct gensec_gssapi_state *gensec_gssapi_state
 
1369
                = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
 
1370
        NTSTATUS status;
 
1371
 
 
1372
        if (gensec_gssapi_state->sig_size) {
 
1373
                return gensec_gssapi_state->sig_size;
 
1374
        }
 
1375
 
 
1376
        if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
 
1377
                gensec_gssapi_state->sig_size = 45;
 
1378
        } else {
 
1379
                gensec_gssapi_state->sig_size = 37;
 
1380
        }
 
1381
 
 
1382
        status = gensec_gssapi_init_lucid(gensec_gssapi_state);
 
1383
        if (!NT_STATUS_IS_OK(status)) {
 
1384
                return gensec_gssapi_state->sig_size;
 
1385
        }
 
1386
 
 
1387
        if (gensec_gssapi_state->lucid->protocol == 1) {
 
1388
                if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
 
1389
                        /*
 
1390
                         * TODO: windows uses 76 here, but we don't know
 
1391
                         *       gss_wrap works with aes keys yet
 
1392
                         */
 
1393
                        gensec_gssapi_state->sig_size = 76;
 
1394
                } else {
 
1395
                        gensec_gssapi_state->sig_size = 28;
 
1396
                }
 
1397
        } else if (gensec_gssapi_state->lucid->protocol == 0) {
 
1398
                switch (gensec_gssapi_state->lucid->rfc1964_kd.ctx_key.type) {
 
1399
                case KEYTYPE_DES:
 
1400
                case KEYTYPE_ARCFOUR:
 
1401
                case KEYTYPE_ARCFOUR_56:
 
1402
                        if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
 
1403
                                gensec_gssapi_state->sig_size = 45;
 
1404
                        } else {
 
1405
                                gensec_gssapi_state->sig_size = 37;
 
1406
                        }
 
1407
                        break;
 
1408
                case KEYTYPE_DES3:
 
1409
                        if (gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG) {
 
1410
                                gensec_gssapi_state->sig_size = 57;
 
1411
                        } else {
 
1412
                                gensec_gssapi_state->sig_size = 49;
 
1413
                        }
 
1414
                        break;
 
1415
                }
 
1416
        }
 
1417
 
 
1418
        return gensec_gssapi_state->sig_size;
 
1419
}
 
1420
 
 
1421
static const char *gensec_gssapi_krb5_oids[] = { 
 
1422
        GENSEC_OID_KERBEROS5_OLD,
 
1423
        GENSEC_OID_KERBEROS5,
 
1424
        NULL 
 
1425
};
 
1426
 
 
1427
static const char *gensec_gssapi_spnego_oids[] = { 
 
1428
        GENSEC_OID_SPNEGO,
 
1429
        NULL 
 
1430
};
 
1431
 
 
1432
/* As a server, this could in theory accept any GSSAPI mech */
 
1433
static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
 
1434
        .name           = "gssapi_spnego",
 
1435
        .sasl_name      = "GSS-SPNEGO",
 
1436
        .auth_type      = DCERPC_AUTH_TYPE_SPNEGO,
 
1437
        .oid            = gensec_gssapi_spnego_oids,
 
1438
        .client_start   = gensec_gssapi_client_start,
 
1439
        .server_start   = gensec_gssapi_server_start,
 
1440
        .magic          = gensec_gssapi_magic,
 
1441
        .update         = gensec_gssapi_update,
 
1442
        .session_key    = gensec_gssapi_session_key,
 
1443
        .session_info   = gensec_gssapi_session_info,
 
1444
        .sign_packet    = gensec_gssapi_sign_packet,
 
1445
        .check_packet   = gensec_gssapi_check_packet,
 
1446
        .seal_packet    = gensec_gssapi_seal_packet,
 
1447
        .unseal_packet  = gensec_gssapi_unseal_packet,
 
1448
        .wrap           = gensec_gssapi_wrap,
 
1449
        .unwrap         = gensec_gssapi_unwrap,
 
1450
        .have_feature   = gensec_gssapi_have_feature,
 
1451
        .enabled        = false,
 
1452
        .kerberos       = true,
 
1453
        .priority       = GENSEC_GSSAPI
 
1454
};
 
1455
 
 
1456
/* As a server, this could in theory accept any GSSAPI mech */
 
1457
static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
 
1458
        .name           = "gssapi_krb5",
 
1459
        .auth_type      = DCERPC_AUTH_TYPE_KRB5,
 
1460
        .oid            = gensec_gssapi_krb5_oids,
 
1461
        .client_start   = gensec_gssapi_client_start,
 
1462
        .server_start   = gensec_gssapi_server_start,
 
1463
        .magic          = gensec_gssapi_magic,
 
1464
        .update         = gensec_gssapi_update,
 
1465
        .session_key    = gensec_gssapi_session_key,
 
1466
        .session_info   = gensec_gssapi_session_info,
 
1467
        .sig_size       = gensec_gssapi_sig_size,
 
1468
        .sign_packet    = gensec_gssapi_sign_packet,
 
1469
        .check_packet   = gensec_gssapi_check_packet,
 
1470
        .seal_packet    = gensec_gssapi_seal_packet,
 
1471
        .unseal_packet  = gensec_gssapi_unseal_packet,
 
1472
        .wrap           = gensec_gssapi_wrap,
 
1473
        .unwrap         = gensec_gssapi_unwrap,
 
1474
        .have_feature   = gensec_gssapi_have_feature,
 
1475
        .enabled        = true,
 
1476
        .kerberos       = true,
 
1477
        .priority       = GENSEC_GSSAPI
 
1478
};
 
1479
 
 
1480
/* As a server, this could in theory accept any GSSAPI mech */
 
1481
static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
 
1482
        .name             = "gssapi_krb5_sasl",
 
1483
        .sasl_name        = "GSSAPI",
 
1484
        .client_start     = gensec_gssapi_sasl_client_start,
 
1485
        .server_start     = gensec_gssapi_sasl_server_start,
 
1486
        .update           = gensec_gssapi_update,
 
1487
        .session_key      = gensec_gssapi_session_key,
 
1488
        .session_info     = gensec_gssapi_session_info,
 
1489
        .max_input_size   = gensec_gssapi_max_input_size,
 
1490
        .max_wrapped_size = gensec_gssapi_max_wrapped_size,
 
1491
        .wrap             = gensec_gssapi_wrap,
 
1492
        .unwrap           = gensec_gssapi_unwrap,
 
1493
        .have_feature     = gensec_gssapi_have_feature,
 
1494
        .enabled          = true,
 
1495
        .kerberos         = true,
 
1496
        .priority         = GENSEC_GSSAPI
 
1497
};
 
1498
 
 
1499
_PUBLIC_ NTSTATUS gensec_gssapi_init(void)
 
1500
{
 
1501
        NTSTATUS ret;
 
1502
 
 
1503
        ret = gensec_register(&gensec_gssapi_spnego_security_ops);
 
1504
        if (!NT_STATUS_IS_OK(ret)) {
 
1505
                DEBUG(0,("Failed to register '%s' gensec backend!\n",
 
1506
                        gensec_gssapi_spnego_security_ops.name));
 
1507
                return ret;
 
1508
        }
 
1509
 
 
1510
        ret = gensec_register(&gensec_gssapi_krb5_security_ops);
 
1511
        if (!NT_STATUS_IS_OK(ret)) {
 
1512
                DEBUG(0,("Failed to register '%s' gensec backend!\n",
 
1513
                        gensec_gssapi_krb5_security_ops.name));
 
1514
                return ret;
 
1515
        }
 
1516
 
 
1517
        ret = gensec_register(&gensec_gssapi_sasl_krb5_security_ops);
 
1518
        if (!NT_STATUS_IS_OK(ret)) {
 
1519
                DEBUG(0,("Failed to register '%s' gensec backend!\n",
 
1520
                        gensec_gssapi_sasl_krb5_security_ops.name));
 
1521
                return ret;
 
1522
        }
 
1523
 
 
1524
        return ret;
 
1525
}