~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/librpc/crypto/gse.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  GSSAPI Security Extensions
 
3
 *  RPC Pipe client and server routines
 
4
 *  Copyright (C) Simo Sorce 2010.
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
/* We support only GSSAPI/KRB5 here */
 
21
 
 
22
#include "includes.h"
 
23
#include "gse.h"
 
24
 
 
25
#if defined(HAVE_KRB5) \
 
26
        && defined(HAVE_GSSAPI_GSSAPI_EXT_H) \
 
27
        && defined(HAVE_GSS_WRAP_IOV) \
 
28
        && defined(HAVE_GSS_GET_NAME_ATTRIBUTE)
 
29
 
 
30
#include "smb_krb5.h"
 
31
#include "gse_krb5.h"
 
32
 
 
33
#include <gssapi/gssapi.h>
 
34
#include <gssapi/gssapi_krb5.h>
 
35
#include <gssapi/gssapi_ext.h>
 
36
 
 
37
#ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
 
38
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
 
39
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
 
40
#endif
 
41
 
 
42
gss_OID_desc gse_sesskey_inq_oid = {
 
43
        GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
 
44
        (void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
 
45
};
 
46
 
 
47
#ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
 
48
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
 
49
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID  "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
 
50
#endif
 
51
 
 
52
gss_OID_desc gse_sesskeytype_oid = {
 
53
        GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
 
54
        (void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
 
55
};
 
56
 
 
57
#define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH 12
 
58
/*                                          EXTRACTION OID                                 AUTHZ ID */
 
59
#define GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" "\x01"
 
60
 
 
61
gss_OID_desc gse_authz_data_oid = {
 
62
        GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID_LENGTH,
 
63
        (void *)GSE_EXTRACT_RELEVANT_AUTHZ_DATA_OID
 
64
};
 
65
 
 
66
#ifndef GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID
 
67
#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 11
 
68
#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c"
 
69
#endif
 
70
 
 
71
gss_OID_desc gse_authtime_oid = {
 
72
        GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH,
 
73
        (void *)GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID
 
74
};
 
75
 
 
76
static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
 
77
 
 
78
struct gse_context {
 
79
        krb5_context k5ctx;
 
80
        krb5_ccache ccache;
 
81
        krb5_keytab keytab;
 
82
 
 
83
        gss_ctx_id_t gss_ctx;
 
84
 
 
85
        gss_OID_desc gss_mech;
 
86
        OM_uint32 gss_c_flags;
 
87
        gss_cred_id_t creds;
 
88
        gss_name_t server_name;
 
89
 
 
90
        gss_OID ret_mech;
 
91
        OM_uint32 ret_flags;
 
92
        gss_cred_id_t delegated_creds;
 
93
        gss_name_t client_name;
 
94
 
 
95
        bool more_processing;
 
96
        bool authenticated;
 
97
};
 
98
 
 
99
/* free non talloc dependent contexts */
 
100
static int gse_context_destructor(void *ptr)
 
101
{
 
102
        struct gse_context *gse_ctx;
 
103
        OM_uint32 gss_min, gss_maj;
 
104
 
 
105
        gse_ctx = talloc_get_type_abort(ptr, struct gse_context);
 
106
        if (gse_ctx->k5ctx) {
 
107
                if (gse_ctx->ccache) {
 
108
                        krb5_cc_close(gse_ctx->k5ctx, gse_ctx->ccache);
 
109
                        gse_ctx->ccache = NULL;
 
110
                }
 
111
                if (gse_ctx->keytab) {
 
112
                        krb5_kt_close(gse_ctx->k5ctx, gse_ctx->keytab);
 
113
                        gse_ctx->keytab = NULL;
 
114
                }
 
115
                krb5_free_context(gse_ctx->k5ctx);
 
116
                gse_ctx->k5ctx = NULL;
 
117
        }
 
118
        if (gse_ctx->gss_ctx != GSS_C_NO_CONTEXT) {
 
119
                gss_maj = gss_delete_sec_context(&gss_min,
 
120
                                                 &gse_ctx->gss_ctx,
 
121
                                                 GSS_C_NO_BUFFER);
 
122
        }
 
123
        if (gse_ctx->server_name) {
 
124
                gss_maj = gss_release_name(&gss_min,
 
125
                                           &gse_ctx->server_name);
 
126
        }
 
127
        if (gse_ctx->client_name) {
 
128
                gss_maj = gss_release_name(&gss_min,
 
129
                                           &gse_ctx->client_name);
 
130
        }
 
131
        if (gse_ctx->creds) {
 
132
                gss_maj = gss_release_cred(&gss_min,
 
133
                                           &gse_ctx->creds);
 
134
        }
 
135
        if (gse_ctx->delegated_creds) {
 
136
                gss_maj = gss_release_cred(&gss_min,
 
137
                                           &gse_ctx->delegated_creds);
 
138
        }
 
139
        if (gse_ctx->ret_mech) {
 
140
                gss_maj = gss_release_oid(&gss_min,
 
141
                                          &gse_ctx->ret_mech);
 
142
        }
 
143
        return 0;
 
144
}
 
145
 
 
146
static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx,
 
147
                                 bool do_sign, bool do_seal,
 
148
                                 const char *ccache_name,
 
149
                                 uint32_t add_gss_c_flags,
 
150
                                 struct gse_context **_gse_ctx)
 
151
{
 
152
        struct gse_context *gse_ctx;
 
153
        krb5_error_code k5ret;
 
154
        NTSTATUS status;
 
155
 
 
156
        gse_ctx = talloc_zero(mem_ctx, struct gse_context);
 
157
        if (!gse_ctx) {
 
158
                return NT_STATUS_NO_MEMORY;
 
159
        }
 
160
        talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
 
161
 
 
162
        memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
 
163
 
 
164
        gse_ctx->gss_c_flags = GSS_C_MUTUAL_FLAG |
 
165
                                GSS_C_DELEG_FLAG |
 
166
                                GSS_C_DELEG_POLICY_FLAG |
 
167
                                GSS_C_REPLAY_FLAG |
 
168
                                GSS_C_SEQUENCE_FLAG;
 
169
        if (do_sign) {
 
170
                gse_ctx->gss_c_flags |= GSS_C_INTEG_FLAG;
 
171
        }
 
172
        if (do_seal) {
 
173
                gse_ctx->gss_c_flags |= GSS_C_CONF_FLAG;
 
174
        }
 
175
 
 
176
        gse_ctx->gss_c_flags |= add_gss_c_flags;
 
177
 
 
178
        /* Initialize Kerberos Context */
 
179
        initialize_krb5_error_table();
 
180
 
 
181
        k5ret = krb5_init_context(&gse_ctx->k5ctx);
 
182
        if (k5ret) {
 
183
                DEBUG(0, ("Failed to initialize kerberos context! (%s)\n",
 
184
                          error_message(k5ret)));
 
185
                status = NT_STATUS_INTERNAL_ERROR;
 
186
                goto err_out;
 
187
        }
 
188
 
 
189
        if (!ccache_name) {
 
190
                ccache_name = krb5_cc_default_name(gse_ctx->k5ctx);
 
191
        }
 
192
        k5ret = krb5_cc_resolve(gse_ctx->k5ctx, ccache_name,
 
193
                                &gse_ctx->ccache);
 
194
        if (k5ret) {
 
195
                DEBUG(1, ("Failed to resolve credential cache! (%s)\n",
 
196
                          error_message(k5ret)));
 
197
                status = NT_STATUS_INTERNAL_ERROR;
 
198
                goto err_out;
 
199
        }
 
200
 
 
201
        /* TODO: Should we enforce a enc_types list ?
 
202
        ret = krb5_set_default_tgs_ktypes(gse_ctx->k5ctx, enc_types);
 
203
        */
 
204
 
 
205
        *_gse_ctx = gse_ctx;
 
206
        return NT_STATUS_OK;
 
207
 
 
208
err_out:
 
209
        TALLOC_FREE(gse_ctx);
 
210
        return status;
 
211
}
 
212
 
 
213
NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 
214
                          bool do_sign, bool do_seal,
 
215
                          const char *ccache_name,
 
216
                          const char *server,
 
217
                          const char *service,
 
218
                          const char *username,
 
219
                          const char *password,
 
220
                          uint32_t add_gss_c_flags,
 
221
                          struct gse_context **_gse_ctx)
 
222
{
 
223
        struct gse_context *gse_ctx;
 
224
        OM_uint32 gss_maj, gss_min;
 
225
        gss_buffer_desc name_buffer = {0, NULL};
 
226
        gss_OID_set_desc mech_set;
 
227
        NTSTATUS status;
 
228
 
 
229
        if (!server || !service) {
 
230
                return NT_STATUS_INVALID_PARAMETER;
 
231
        }
 
232
 
 
233
        status = gse_context_init(mem_ctx, do_sign, do_seal,
 
234
                                  ccache_name, add_gss_c_flags,
 
235
                                  &gse_ctx);
 
236
        if (!NT_STATUS_IS_OK(status)) {
 
237
                return NT_STATUS_NO_MEMORY;
 
238
        }
 
239
 
 
240
        name_buffer.value = talloc_asprintf(gse_ctx,
 
241
                                            "%s@%s", service, server);
 
242
        if (!name_buffer.value) {
 
243
                status = NT_STATUS_NO_MEMORY;
 
244
                goto err_out;
 
245
        }
 
246
        name_buffer.length = strlen((char *)name_buffer.value);
 
247
        gss_maj = gss_import_name(&gss_min, &name_buffer,
 
248
                                  GSS_C_NT_HOSTBASED_SERVICE,
 
249
                                  &gse_ctx->server_name);
 
250
        if (gss_maj) {
 
251
                DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
 
252
                          (char *)name_buffer.value,
 
253
                          gse_errstr(gse_ctx, gss_maj, gss_min)));
 
254
                status = NT_STATUS_INTERNAL_ERROR;
 
255
                goto err_out;
 
256
        }
 
257
 
 
258
        /* TODO: get krb5 ticket using username/password, if no valid
 
259
         * one already available in ccache */
 
260
 
 
261
        mech_set.count = 1;
 
262
        mech_set.elements = &gse_ctx->gss_mech;
 
263
 
 
264
        gss_maj = gss_acquire_cred(&gss_min,
 
265
                                   GSS_C_NO_NAME,
 
266
                                   GSS_C_INDEFINITE,
 
267
                                   &mech_set,
 
268
                                   GSS_C_INITIATE,
 
269
                                   &gse_ctx->creds,
 
270
                                   NULL, NULL);
 
271
        if (gss_maj) {
 
272
                DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
 
273
                          (char *)name_buffer.value,
 
274
                          gse_errstr(gse_ctx, gss_maj, gss_min)));
 
275
                status = NT_STATUS_INTERNAL_ERROR;
 
276
                goto err_out;
 
277
        }
 
278
 
 
279
        *_gse_ctx = gse_ctx;
 
280
        TALLOC_FREE(name_buffer.value);
 
281
        return NT_STATUS_OK;
 
282
 
 
283
err_out:
 
284
        TALLOC_FREE(name_buffer.value);
 
285
        TALLOC_FREE(gse_ctx);
 
286
        return status;
 
287
}
 
288
 
 
289
NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
 
290
                                   struct gse_context *gse_ctx,
 
291
                                   DATA_BLOB *token_in,
 
292
                                   DATA_BLOB *token_out)
 
293
{
 
294
        OM_uint32 gss_maj, gss_min;
 
295
        gss_buffer_desc in_data;
 
296
        gss_buffer_desc out_data;
 
297
        DATA_BLOB blob = data_blob_null;
 
298
        NTSTATUS status;
 
299
 
 
300
        in_data.value = token_in->data;
 
301
        in_data.length = token_in->length;
 
302
 
 
303
        gss_maj = gss_init_sec_context(&gss_min,
 
304
                                        gse_ctx->creds,
 
305
                                        &gse_ctx->gss_ctx,
 
306
                                        gse_ctx->server_name,
 
307
                                        &gse_ctx->gss_mech,
 
308
                                        gse_ctx->gss_c_flags,
 
309
                                        0, GSS_C_NO_CHANNEL_BINDINGS,
 
310
                                        &in_data, NULL, &out_data,
 
311
                                        NULL, NULL);
 
312
        switch (gss_maj) {
 
313
        case GSS_S_COMPLETE:
 
314
                /* we are done with it */
 
315
                gse_ctx->more_processing = false;
 
316
                status = NT_STATUS_OK;
 
317
                break;
 
318
        case GSS_S_CONTINUE_NEEDED:
 
319
                /* we will need a third leg */
 
320
                gse_ctx->more_processing = true;
 
321
                /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
 
322
                status = NT_STATUS_OK;
 
323
                break;
 
324
        default:
 
325
                DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
 
326
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
327
                status = NT_STATUS_INTERNAL_ERROR;
 
328
                goto done;
 
329
        }
 
330
 
 
331
        blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
 
332
        if (!blob.data) {
 
333
                status = NT_STATUS_NO_MEMORY;
 
334
        }
 
335
 
 
336
        gss_maj = gss_release_buffer(&gss_min, &out_data);
 
337
 
 
338
done:
 
339
        *token_out = blob;
 
340
        return status;
 
341
}
 
342
 
 
343
NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
 
344
                         bool do_sign, bool do_seal,
 
345
                         uint32_t add_gss_c_flags,
 
346
                         const char *keytab_name,
 
347
                         struct gse_context **_gse_ctx)
 
348
{
 
349
        struct gse_context *gse_ctx;
 
350
        OM_uint32 gss_maj, gss_min;
 
351
        gss_OID_set_desc mech_set;
 
352
        krb5_error_code ret;
 
353
        const char *ktname;
 
354
        NTSTATUS status;
 
355
 
 
356
        status = gse_context_init(mem_ctx, do_sign, do_seal,
 
357
                                  NULL, add_gss_c_flags, &gse_ctx);
 
358
        if (!NT_STATUS_IS_OK(status)) {
 
359
                return NT_STATUS_NO_MEMORY;
 
360
        }
 
361
 
 
362
        if (!keytab_name) {
 
363
                ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx,
 
364
                                                 &gse_ctx->keytab);
 
365
                if (ret) {
 
366
                        status = NT_STATUS_INTERNAL_ERROR;
 
367
                        goto done;
 
368
                }
 
369
                ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx,
 
370
                                           gse_ctx->keytab, &ktname);
 
371
                if (ret) {
 
372
                        status = NT_STATUS_INTERNAL_ERROR;
 
373
                        goto done;
 
374
                }
 
375
        } else {
 
376
                ktname = keytab_name;
 
377
        }
 
378
 
 
379
        /* FIXME!!!
 
380
         * This call sets the default keytab for the whole server, not
 
381
         * just for this context. Need to find a way that does not alter
 
382
         * the state of the whole server ... */
 
383
        ret = gsskrb5_register_acceptor_identity(ktname);
 
384
        if (ret) {
 
385
                status = NT_STATUS_INTERNAL_ERROR;
 
386
                goto done;
 
387
        }
 
388
 
 
389
        mech_set.count = 1;
 
390
        mech_set.elements = &gse_ctx->gss_mech;
 
391
 
 
392
        gss_maj = gss_acquire_cred(&gss_min,
 
393
                                   GSS_C_NO_NAME,
 
394
                                   GSS_C_INDEFINITE,
 
395
                                   &mech_set,
 
396
                                   GSS_C_ACCEPT,
 
397
                                   &gse_ctx->creds,
 
398
                                   NULL, NULL);
 
399
        if (gss_maj) {
 
400
                DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
 
401
                          gse_errstr(gse_ctx, gss_maj, gss_min)));
 
402
                status = NT_STATUS_INTERNAL_ERROR;
 
403
                goto done;
 
404
        }
 
405
 
 
406
        status = NT_STATUS_OK;
 
407
 
 
408
done:
 
409
        if (!NT_STATUS_IS_OK(status)) {
 
410
                TALLOC_FREE(gse_ctx);
 
411
        }
 
412
 
 
413
        *_gse_ctx = gse_ctx;
 
414
        return status;
 
415
}
 
416
 
 
417
NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
 
418
                                   struct gse_context *gse_ctx,
 
419
                                   DATA_BLOB *token_in,
 
420
                                   DATA_BLOB *token_out)
 
421
{
 
422
        OM_uint32 gss_maj, gss_min;
 
423
        gss_buffer_desc in_data;
 
424
        gss_buffer_desc out_data;
 
425
        DATA_BLOB blob = data_blob_null;
 
426
        NTSTATUS status;
 
427
 
 
428
        in_data.value = token_in->data;
 
429
        in_data.length = token_in->length;
 
430
 
 
431
        gss_maj = gss_accept_sec_context(&gss_min,
 
432
                                         &gse_ctx->gss_ctx,
 
433
                                         gse_ctx->creds,
 
434
                                         &in_data,
 
435
                                         GSS_C_NO_CHANNEL_BINDINGS,
 
436
                                         &gse_ctx->client_name,
 
437
                                         &gse_ctx->ret_mech,
 
438
                                         &out_data,
 
439
                                         &gse_ctx->ret_flags, NULL,
 
440
                                         &gse_ctx->delegated_creds);
 
441
        switch (gss_maj) {
 
442
        case GSS_S_COMPLETE:
 
443
                /* we are done with it */
 
444
                gse_ctx->more_processing = false;
 
445
                gse_ctx->authenticated = true;
 
446
                status = NT_STATUS_OK;
 
447
                break;
 
448
        case GSS_S_CONTINUE_NEEDED:
 
449
                /* we will need a third leg */
 
450
                gse_ctx->more_processing = true;
 
451
                /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
 
452
                status = NT_STATUS_OK;
 
453
                break;
 
454
        default:
 
455
                DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
 
456
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
457
 
 
458
                if (gse_ctx->gss_ctx) {
 
459
                        gss_delete_sec_context(&gss_min,
 
460
                                                &gse_ctx->gss_ctx,
 
461
                                                GSS_C_NO_BUFFER);
 
462
                }
 
463
 
 
464
                status = NT_STATUS_INTERNAL_ERROR;
 
465
                goto done;
 
466
        }
 
467
 
 
468
        /* we may be told to return nothing */
 
469
        if (out_data.length) {
 
470
                blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
 
471
                if (!blob.data) {
 
472
                        status = NT_STATUS_NO_MEMORY;
 
473
                }
 
474
                gss_maj = gss_release_buffer(&gss_min, &out_data);
 
475
        }
 
476
 
 
477
 
 
478
done:
 
479
        *token_out = blob;
 
480
        return status;
 
481
}
 
482
 
 
483
NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
 
484
{
 
485
        if (!gse_ctx->authenticated) {
 
486
                return NT_STATUS_INVALID_HANDLE;
 
487
        }
 
488
 
 
489
        if (memcmp(gse_ctx->ret_mech,
 
490
                   gss_mech_krb5, sizeof(gss_OID_desc)) != 0) {
 
491
                return NT_STATUS_ACCESS_DENIED;
 
492
        }
 
493
 
 
494
        /* GSS_C_MUTUAL_FLAG */
 
495
        if (gse_ctx->gss_c_flags & GSS_C_MUTUAL_FLAG) {
 
496
                if (!(gse_ctx->ret_flags & GSS_C_MUTUAL_FLAG)) {
 
497
                        return NT_STATUS_ACCESS_DENIED;
 
498
                }
 
499
        }
 
500
 
 
501
        /* GSS_C_DELEG_FLAG */
 
502
        /* GSS_C_DELEG_POLICY_FLAG */
 
503
        /* GSS_C_REPLAY_FLAG */
 
504
        /* GSS_C_SEQUENCE_FLAG */
 
505
 
 
506
        /* GSS_C_INTEG_FLAG */
 
507
        if (gse_ctx->gss_c_flags & GSS_C_INTEG_FLAG) {
 
508
                if (!(gse_ctx->ret_flags & GSS_C_INTEG_FLAG)) {
 
509
                        return NT_STATUS_ACCESS_DENIED;
 
510
                }
 
511
        }
 
512
 
 
513
        /* GSS_C_CONF_FLAG */
 
514
        if (gse_ctx->gss_c_flags & GSS_C_CONF_FLAG) {
 
515
                if (!(gse_ctx->ret_flags & GSS_C_CONF_FLAG)) {
 
516
                        return NT_STATUS_ACCESS_DENIED;
 
517
                }
 
518
        }
 
519
 
 
520
        return NT_STATUS_OK;
 
521
}
 
522
 
 
523
static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min)
 
524
{
 
525
        OM_uint32 gss_min, gss_maj;
 
526
        gss_buffer_desc msg_min;
 
527
        gss_buffer_desc msg_maj;
 
528
        OM_uint32 msg_ctx = 0;
 
529
 
 
530
        char *errstr = NULL;
 
531
 
 
532
        ZERO_STRUCT(msg_min);
 
533
        ZERO_STRUCT(msg_maj);
 
534
 
 
535
        gss_maj = gss_display_status(&gss_min, maj, GSS_C_GSS_CODE,
 
536
                                     GSS_C_NO_OID, &msg_ctx, &msg_maj);
 
537
        if (gss_maj) {
 
538
                goto done;
 
539
        }
 
540
        gss_maj = gss_display_status(&gss_min, min, GSS_C_MECH_CODE,
 
541
                                     (gss_OID)discard_const(gss_mech_krb5),
 
542
                                     &msg_ctx, &msg_min);
 
543
        if (gss_maj) {
 
544
                goto done;
 
545
        }
 
546
 
 
547
        errstr = talloc_strndup(mem_ctx,
 
548
                                (char *)msg_maj.value,
 
549
                                        msg_maj.length);
 
550
        if (!errstr) {
 
551
                goto done;
 
552
        }
 
553
        errstr = talloc_strdup_append_buffer(errstr, ": ");
 
554
        if (!errstr) {
 
555
                goto done;
 
556
        }
 
557
        errstr = talloc_strndup_append_buffer(errstr,
 
558
                                                (char *)msg_min.value,
 
559
                                                        msg_min.length);
 
560
        if (!errstr) {
 
561
                goto done;
 
562
        }
 
563
 
 
564
done:
 
565
        if (msg_min.value) {
 
566
                gss_maj = gss_release_buffer(&gss_min, &msg_min);
 
567
        }
 
568
        if (msg_maj.value) {
 
569
                gss_maj = gss_release_buffer(&gss_min, &msg_maj);
 
570
        }
 
571
        return errstr;
 
572
}
 
573
 
 
574
bool gse_require_more_processing(struct gse_context *gse_ctx)
 
575
{
 
576
        return gse_ctx->more_processing;
 
577
}
 
578
 
 
579
DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
 
580
                                struct gse_context *gse_ctx)
 
581
{
 
582
        OM_uint32 gss_min, gss_maj;
 
583
        gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
 
584
        DATA_BLOB ret;
 
585
 
 
586
        gss_maj = gss_inquire_sec_context_by_oid(
 
587
                                &gss_min, gse_ctx->gss_ctx,
 
588
                                &gse_sesskey_inq_oid, &set);
 
589
        if (gss_maj) {
 
590
                DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
 
591
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
592
                return data_blob_null;
 
593
        }
 
594
 
 
595
        if ((set == GSS_C_NO_BUFFER_SET) ||
 
596
            (set->count != 2) ||
 
597
            (memcmp(set->elements[1].value,
 
598
                    gse_sesskeytype_oid.elements,
 
599
                    gse_sesskeytype_oid.length) != 0)) {
 
600
                DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
 
601
                          "OID for data in results:\n"));
 
602
                dump_data(1, (uint8_t *)set->elements[1].value,
 
603
                             set->elements[1].length);
 
604
                return data_blob_null;
 
605
        }
 
606
 
 
607
        ret = data_blob_talloc(mem_ctx, set->elements[0].value,
 
608
                                        set->elements[0].length);
 
609
 
 
610
        gss_maj = gss_release_buffer_set(&gss_min, &set);
 
611
        return ret;
 
612
}
 
613
 
 
614
NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
 
615
                             TALLOC_CTX *mem_ctx, char **cli_name)
 
616
{
 
617
        OM_uint32 gss_min, gss_maj;
 
618
        gss_buffer_desc name_buffer;
 
619
 
 
620
        if (!gse_ctx->authenticated) {
 
621
                return NT_STATUS_ACCESS_DENIED;
 
622
        }
 
623
 
 
624
        if (!gse_ctx->client_name) {
 
625
                return NT_STATUS_NOT_FOUND;
 
626
        }
 
627
 
 
628
        /* TODO: check OID matches KRB5 Principal Name OID ? */
 
629
 
 
630
        gss_maj = gss_display_name(&gss_min,
 
631
                                   gse_ctx->client_name,
 
632
                                   &name_buffer, NULL);
 
633
        if (gss_maj) {
 
634
                DEBUG(0, ("gss_display_name failed [%s]\n",
 
635
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
636
                return NT_STATUS_INTERNAL_ERROR;
 
637
        }
 
638
 
 
639
        *cli_name = talloc_strndup(talloc_tos(),
 
640
                                        (char *)name_buffer.value,
 
641
                                        name_buffer.length);
 
642
 
 
643
        gss_maj = gss_release_buffer(&gss_min, &name_buffer);
 
644
 
 
645
        if (!*cli_name) {
 
646
                return NT_STATUS_NO_MEMORY;
 
647
        }
 
648
 
 
649
        return NT_STATUS_OK;
 
650
}
 
651
 
 
652
NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
 
653
                            TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
 
654
{
 
655
        OM_uint32 gss_min, gss_maj;
 
656
        gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
 
657
 
 
658
        if (!gse_ctx->authenticated) {
 
659
                return NT_STATUS_ACCESS_DENIED;
 
660
        }
 
661
 
 
662
        gss_maj = gss_inquire_sec_context_by_oid(
 
663
                                &gss_min, gse_ctx->gss_ctx,
 
664
                                &gse_authz_data_oid, &set);
 
665
        if (gss_maj) {
 
666
                DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
 
667
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
668
                return NT_STATUS_NOT_FOUND;
 
669
        }
 
670
 
 
671
        if (set == GSS_C_NO_BUFFER_SET) {
 
672
                DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
 
673
                          "data in results.\n"));
 
674
                return NT_STATUS_INTERNAL_ERROR;
 
675
        }
 
676
 
 
677
        /* for now we just hope it is the first value */
 
678
        *pac = data_blob_talloc(mem_ctx,
 
679
                                set->elements[0].value,
 
680
                                set->elements[0].length);
 
681
 
 
682
        gss_maj = gss_release_buffer_set(&gss_min, &set);
 
683
 
 
684
        return NT_STATUS_OK;
 
685
}
 
686
 
 
687
NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
 
688
                          TALLOC_CTX *mem_ctx, DATA_BLOB *pac_blob)
 
689
{
 
690
        OM_uint32 gss_min, gss_maj;
 
691
        gss_buffer_desc pac_buffer;
 
692
        gss_buffer_desc pac_display_buffer;
 
693
        gss_buffer_desc pac_name = {
 
694
                .value = discard_const_p(char, "urn:mspac:"),
 
695
                .length = sizeof("urn:mspac:") - 1
 
696
        };
 
697
        int more = -1;
 
698
        int authenticated = false;
 
699
        int complete = false;
 
700
        NTSTATUS status;
 
701
 
 
702
        if (!gse_ctx->authenticated) {
 
703
                return NT_STATUS_ACCESS_DENIED;
 
704
        }
 
705
 
 
706
        gss_maj = gss_get_name_attribute(&gss_min,
 
707
                                         gse_ctx->client_name, &pac_name,
 
708
                                         &authenticated, &complete,
 
709
                                         &pac_buffer, &pac_display_buffer,
 
710
                                         &more);
 
711
 
 
712
        if (gss_maj != 0) {
 
713
                DEBUG(0, ("obtaining PAC via GSSAPI gss_get_name_attribute "
 
714
                          "failed: %s\n",
 
715
                          gse_errstr(mem_ctx, gss_maj, gss_min)));
 
716
                return NT_STATUS_ACCESS_DENIED;
 
717
        }
 
718
 
 
719
        if (authenticated && complete) {
 
720
                /* The PAC blob is returned directly */
 
721
                *pac_blob = data_blob_talloc(mem_ctx,
 
722
                                             pac_buffer.value,
 
723
                                             pac_buffer.length);
 
724
                if (!pac_blob->data) {
 
725
                        status = NT_STATUS_NO_MEMORY;
 
726
                } else {
 
727
                        status = NT_STATUS_OK;
 
728
                }
 
729
 
 
730
                gss_maj = gss_release_buffer(&gss_min, &pac_buffer);
 
731
                gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer);
 
732
 
 
733
                return status;
 
734
        }
 
735
 
 
736
        DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, "
 
737
                  "complete: %s, more: %s\n",
 
738
                  authenticated ? "true" : "false",
 
739
                  complete ? "true" : "false",
 
740
                  more ? "true" : "false"));
 
741
 
 
742
        return NT_STATUS_ACCESS_DENIED;
 
743
}
 
744
 
 
745
size_t gse_get_signature_length(struct gse_context *gse_ctx,
 
746
                                int seal, size_t payload_size)
 
747
{
 
748
        OM_uint32 gss_min, gss_maj;
 
749
        gss_iov_buffer_desc iov[2];
 
750
        uint8_t fakebuf[payload_size];
 
751
        int sealed;
 
752
 
 
753
        iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
 
754
        iov[0].buffer.value = NULL;
 
755
        iov[0].buffer.length = 0;
 
756
        iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
 
757
        iov[1].buffer.value = fakebuf;
 
758
        iov[1].buffer.length = payload_size;
 
759
 
 
760
        gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gss_ctx,
 
761
                                        seal, GSS_C_QOP_DEFAULT,
 
762
                                        &sealed, iov, 2);
 
763
        if (gss_maj) {
 
764
                DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
 
765
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
766
                return 0;
 
767
        }
 
768
 
 
769
        return iov[0].buffer.length;
 
770
}
 
771
 
 
772
NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
773
                  DATA_BLOB *data, DATA_BLOB *signature)
 
774
{
 
775
        OM_uint32 gss_min, gss_maj;
 
776
        gss_iov_buffer_desc iov[2];
 
777
        int req_seal = 1; /* setting to 1 means we request sign+seal */
 
778
        int sealed;
 
779
        NTSTATUS status;
 
780
 
 
781
        /* allocate the memory ourselves so we do not need to talloc_memdup */
 
782
        signature->length = gse_get_signature_length(gse_ctx, 1, data->length);
 
783
        if (!signature->length) {
 
784
                return NT_STATUS_INTERNAL_ERROR;
 
785
        }
 
786
        signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
 
787
        if (!signature->data) {
 
788
                return NT_STATUS_NO_MEMORY;
 
789
        }
 
790
        iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
 
791
        iov[0].buffer.value = signature->data;
 
792
        iov[0].buffer.length = signature->length;
 
793
 
 
794
        /* data is encrypted in place, which is ok */
 
795
        iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
 
796
        iov[1].buffer.value = data->data;
 
797
        iov[1].buffer.length = data->length;
 
798
 
 
799
        gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gss_ctx,
 
800
                                req_seal, GSS_C_QOP_DEFAULT,
 
801
                                &sealed, iov, 2);
 
802
        if (gss_maj) {
 
803
                DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
 
804
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
805
                status = NT_STATUS_ACCESS_DENIED;
 
806
                goto done;
 
807
        }
 
808
 
 
809
        if (!sealed) {
 
810
                DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
 
811
                status = NT_STATUS_ACCESS_DENIED;
 
812
                goto done;
 
813
        }
 
814
 
 
815
        status = NT_STATUS_OK;
 
816
 
 
817
        DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
 
818
                   (int)iov[1].buffer.length, (int)iov[0].buffer.length));
 
819
 
 
820
done:
 
821
        return status;
 
822
}
 
823
 
 
824
NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
825
                    DATA_BLOB *data, DATA_BLOB *signature)
 
826
{
 
827
        OM_uint32 gss_min, gss_maj;
 
828
        gss_iov_buffer_desc iov[2];
 
829
        int sealed;
 
830
        NTSTATUS status;
 
831
 
 
832
        iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
 
833
        iov[0].buffer.value = signature->data;
 
834
        iov[0].buffer.length = signature->length;
 
835
 
 
836
        /* data is decrypted in place, which is ok */
 
837
        iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
 
838
        iov[1].buffer.value = data->data;
 
839
        iov[1].buffer.length = data->length;
 
840
 
 
841
        gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gss_ctx,
 
842
                                 &sealed, NULL, iov, 2);
 
843
        if (gss_maj) {
 
844
                DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
 
845
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
846
                status = NT_STATUS_ACCESS_DENIED;
 
847
                goto done;
 
848
        }
 
849
 
 
850
        if (!sealed) {
 
851
                DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
 
852
                status = NT_STATUS_ACCESS_DENIED;
 
853
                goto done;
 
854
        }
 
855
 
 
856
        status = NT_STATUS_OK;
 
857
 
 
858
        DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
 
859
                   (int)iov[1].buffer.length, (int)iov[0].buffer.length));
 
860
 
 
861
done:
 
862
        return status;
 
863
}
 
864
 
 
865
NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
866
                  DATA_BLOB *data, DATA_BLOB *signature)
 
867
{
 
868
        OM_uint32 gss_min, gss_maj;
 
869
        gss_buffer_desc in_data = { 0, NULL };
 
870
        gss_buffer_desc out_data = { 0, NULL};
 
871
        NTSTATUS status;
 
872
 
 
873
        in_data.value = data->data;
 
874
        in_data.length = data->length;
 
875
 
 
876
        gss_maj = gss_get_mic(&gss_min, gse_ctx->gss_ctx,
 
877
                              GSS_C_QOP_DEFAULT,
 
878
                              &in_data, &out_data);
 
879
        if (gss_maj) {
 
880
                DEBUG(0, ("gss_get_mic failed with [%s]\n",
 
881
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
882
                status = NT_STATUS_ACCESS_DENIED;
 
883
                goto done;
 
884
        }
 
885
 
 
886
        *signature = data_blob_talloc(mem_ctx,
 
887
                                        out_data.value, out_data.length);
 
888
        if (!signature->data) {
 
889
                status = NT_STATUS_NO_MEMORY;
 
890
                goto done;
 
891
        }
 
892
 
 
893
        status = NT_STATUS_OK;
 
894
 
 
895
done:
 
896
        if (out_data.value) {
 
897
                gss_maj = gss_release_buffer(&gss_min, &out_data);
 
898
        }
 
899
        return status;
 
900
}
 
901
 
 
902
NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
903
                      DATA_BLOB *data, DATA_BLOB *signature)
 
904
{
 
905
        OM_uint32 gss_min, gss_maj;
 
906
        gss_buffer_desc in_data = { 0, NULL };
 
907
        gss_buffer_desc in_token = { 0, NULL};
 
908
        NTSTATUS status;
 
909
 
 
910
        in_data.value = data->data;
 
911
        in_data.length = data->length;
 
912
        in_token.value = signature->data;
 
913
        in_token.length = signature->length;
 
914
 
 
915
        gss_maj = gss_verify_mic(&gss_min, gse_ctx->gss_ctx,
 
916
                                 &in_data, &in_token, NULL);
 
917
        if (gss_maj) {
 
918
                DEBUG(0, ("gss_verify_mic failed with [%s]\n",
 
919
                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
 
920
                status = NT_STATUS_ACCESS_DENIED;
 
921
                goto done;
 
922
        }
 
923
 
 
924
        status = NT_STATUS_OK;
 
925
 
 
926
done:
 
927
        return status;
 
928
}
 
929
 
 
930
#else
 
931
 
 
932
NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
 
933
                          bool do_sign, bool do_seal,
 
934
                          const char *ccache_name,
 
935
                          const char *server,
 
936
                          const char *service,
 
937
                          const char *username,
 
938
                          const char *password,
 
939
                          uint32_t add_gss_c_flags,
 
940
                          struct gse_context **_gse_ctx)
 
941
{
 
942
        return NT_STATUS_NOT_IMPLEMENTED;
 
943
}
 
944
 
 
945
NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
 
946
                                   struct gse_context *gse_ctx,
 
947
                                   DATA_BLOB *token_in,
 
948
                                   DATA_BLOB *token_out)
 
949
{
 
950
        return NT_STATUS_NOT_IMPLEMENTED;
 
951
}
 
952
 
 
953
NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
 
954
                         bool do_sign, bool do_seal,
 
955
                         uint32_t add_gss_c_flags,
 
956
                         const char *keytab,
 
957
                         struct gse_context **_gse_ctx)
 
958
{
 
959
        return NT_STATUS_NOT_IMPLEMENTED;
 
960
}
 
961
 
 
962
NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
 
963
                                   struct gse_context *gse_ctx,
 
964
                                   DATA_BLOB *token_in,
 
965
                                   DATA_BLOB *token_out)
 
966
{
 
967
        return NT_STATUS_NOT_IMPLEMENTED;
 
968
}
 
969
 
 
970
NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
 
971
{
 
972
        return NT_STATUS_NOT_IMPLEMENTED;
 
973
}
 
974
 
 
975
bool gse_require_more_processing(struct gse_context *gse_ctx)
 
976
{
 
977
        return false;
 
978
}
 
979
 
 
980
DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
 
981
                              struct gse_context *gse_ctx)
 
982
{
 
983
        return data_blob_null;
 
984
}
 
985
 
 
986
NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
 
987
                             TALLOC_CTX *mem_ctx, char **cli_name)
 
988
{
 
989
        return NT_STATUS_NOT_IMPLEMENTED;
 
990
}
 
991
 
 
992
NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
 
993
                            TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
 
994
{
 
995
        return NT_STATUS_NOT_IMPLEMENTED;
 
996
}
 
997
 
 
998
NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
 
999
                          TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
 
1000
{
 
1001
        return NT_STATUS_NOT_IMPLEMENTED;
 
1002
}
 
1003
 
 
1004
size_t gse_get_signature_length(struct gse_context *gse_ctx,
 
1005
                                int seal, size_t payload_size)
 
1006
{
 
1007
        return 0;
 
1008
}
 
1009
 
 
1010
NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
1011
                  DATA_BLOB *data, DATA_BLOB *signature)
 
1012
{
 
1013
        return NT_STATUS_NOT_IMPLEMENTED;
 
1014
}
 
1015
 
 
1016
NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
1017
                    DATA_BLOB *data, DATA_BLOB *signature)
 
1018
{
 
1019
        return NT_STATUS_NOT_IMPLEMENTED;
 
1020
}
 
1021
 
 
1022
NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
1023
                  DATA_BLOB *data, DATA_BLOB *signature)
 
1024
{
 
1025
        return NT_STATUS_NOT_IMPLEMENTED;
 
1026
}
 
1027
 
 
1028
NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
 
1029
                      DATA_BLOB *data, DATA_BLOB *signature)
 
1030
{
 
1031
        return NT_STATUS_NOT_IMPLEMENTED;
 
1032
}
 
1033
 
 
1034
#endif /* HAVE_KRB5 && HAVE_GSSAPI_EXT_H && HAVE_GSS_WRAP_IOV */