Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

Location:
vendor/current/source3/librpc/crypto
Files:
2 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/librpc/crypto/gse.c

    r746 r988  
    33 *  RPC Pipe client and server routines
    44 *  Copyright (C) Simo Sorce 2010.
     5 *  Copyright (C) Andrew Bartlett 2004-2011.
     6 *  Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
    57 *
    68 *  This program is free software; you can redistribute it and/or modify
     
    2224#include "includes.h"
    2325#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"
     26#include "libads/kerberos_proto.h"
     27#include "auth/common_auth.h"
     28#include "auth/gensec/gensec.h"
     29#include "auth/gensec/gensec_internal.h"
     30#include "auth/credentials/credentials.h"
     31#include "../librpc/gen_ndr/dcerpc.h"
     32
     33#if defined(HAVE_KRB5)
     34
     35#include "auth/kerberos/pac_utils.h"
     36#include "auth/kerberos/gssapi_helper.h"
    3137#include "gse_krb5.h"
    3238
    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 
    7639static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
     40static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
     41                                  size_t data_size);
    7742
    7843struct gse_context {
     44        gss_ctx_id_t gssapi_context;
     45        gss_name_t server_name;
     46        gss_name_t client_name;
     47        OM_uint32 gss_want_flags, gss_got_flags;
     48        size_t max_wrap_buf_size;
     49        size_t sig_size;
     50
     51        gss_cred_id_t delegated_cred_handle;
     52
     53        NTTIME expire_time;
     54
     55        /* gensec_gse only */
    7956        krb5_context k5ctx;
    8057        krb5_ccache ccache;
    8158        krb5_keytab keytab;
    8259
    83         gss_ctx_id_t gss_ctx;
    84 
    8560        gss_OID_desc gss_mech;
    86         OM_uint32 gss_c_flags;
    8761        gss_cred_id_t creds;
    88         gss_name_t server_name;
    8962
    9063        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;
    9764};
    9865
     
    10168{
    10269        struct gse_context *gse_ctx;
    103         OM_uint32 gss_min, gss_maj;
     70        OM_uint32 gss_min;
    10471
    10572        gse_ctx = talloc_get_type_abort(ptr, struct gse_context);
     
    11683                gse_ctx->k5ctx = NULL;
    11784        }
    118         if (gse_ctx->gss_ctx != GSS_C_NO_CONTEXT) {
    119                 gss_maj = gss_delete_sec_context(&gss_min,
    120                                                  &gse_ctx->gss_ctx,
     85        if (gse_ctx->gssapi_context != GSS_C_NO_CONTEXT) {
     86                (void)gss_delete_sec_context(&gss_min,
     87                                                 &gse_ctx->gssapi_context,
    12188                                                 GSS_C_NO_BUFFER);
    12289        }
    12390        if (gse_ctx->server_name) {
    124                 gss_maj = gss_release_name(&gss_min,
     91                (void)gss_release_name(&gss_min,
    12592                                           &gse_ctx->server_name);
    12693        }
    12794        if (gse_ctx->client_name) {
    128                 gss_maj = gss_release_name(&gss_min,
     95                (void)gss_release_name(&gss_min,
    12996                                           &gse_ctx->client_name);
    13097        }
    13198        if (gse_ctx->creds) {
    132                 gss_maj = gss_release_cred(&gss_min,
     99                (void)gss_release_cred(&gss_min,
    133100                                           &gse_ctx->creds);
    134101        }
    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         }
     102        if (gse_ctx->delegated_cred_handle) {
     103                (void)gss_release_cred(&gss_min,
     104                                           &gse_ctx->delegated_cred_handle);
     105        }
     106
     107        /* MIT and Heimdal differ as to if you can call
     108         * gss_release_oid() on this OID, generated by
     109         * gss_{accept,init}_sec_context().  However, as long as the
     110         * oid is gss_mech_krb5 (which it always is at the moment),
     111         * then this is a moot point, as both declare this particular
     112         * OID static, and so no memory is lost.  This assert is in
     113         * place to ensure that the programmer who wishes to extend
     114         * this code to EAP or other GSS mechanisms determines an
     115         * implementation-dependent way of releasing any dynamically
     116         * allocated OID */
     117        SMB_ASSERT(smb_gss_oid_equal(&gse_ctx->gss_mech, GSS_C_NO_OID) ||
     118                   smb_gss_oid_equal(&gse_ctx->gss_mech, gss_mech_krb5));
     119
    143120        return 0;
    144121}
     
    160137        talloc_set_destructor((TALLOC_CTX *)gse_ctx, gse_context_destructor);
    161138
     139        gse_ctx->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
     140        gse_ctx->max_wrap_buf_size = UINT16_MAX;
     141
    162142        memcpy(&gse_ctx->gss_mech, gss_mech_krb5, sizeof(gss_OID_desc));
    163143
    164         gse_ctx->gss_c_flags = GSS_C_MUTUAL_FLAG |
     144        gse_ctx->gss_want_flags = GSS_C_MUTUAL_FLAG |
    165145                                GSS_C_DELEG_FLAG |
    166146                                GSS_C_DELEG_POLICY_FLAG |
     
    168148                                GSS_C_SEQUENCE_FLAG;
    169149        if (do_sign) {
    170                 gse_ctx->gss_c_flags |= GSS_C_INTEG_FLAG;
     150                gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
    171151        }
    172152        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;
     153                gse_ctx->gss_want_flags |= GSS_C_INTEG_FLAG;
     154                gse_ctx->gss_want_flags |= GSS_C_CONF_FLAG;
     155        }
     156
     157        gse_ctx->gss_want_flags |= add_gss_c_flags;
    177158
    178159        /* Initialize Kerberos Context */
     
    211192}
    212193
    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)
     194static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
     195                                bool do_sign, bool do_seal,
     196                                const char *ccache_name,
     197                                const char *server,
     198                                const char *service,
     199                                const char *username,
     200                                const char *password,
     201                                uint32_t add_gss_c_flags,
     202                                struct gse_context **_gse_ctx)
    222203{
    223204        struct gse_context *gse_ctx;
    224205        OM_uint32 gss_maj, gss_min;
    225         gss_buffer_desc name_buffer = {0, NULL};
     206        gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER;
    226207        gss_OID_set_desc mech_set;
     208#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
     209        gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
     210#endif
    227211        NTSTATUS status;
    228212
     
    238222        }
    239223
    240         name_buffer.value = talloc_asprintf(gse_ctx,
    241                                             "%s@%s", service, server);
     224        /* Guess the realm based on the supplied service, and avoid the GSS libs
     225           doing DNS lookups which may fail.
     226
     227           TODO: Loop with the KDC on some more combinations (local
     228           realm in particular), possibly falling back to
     229           GSS_C_NT_HOSTBASED_SERVICE
     230        */
     231        name_buffer.value = kerberos_get_principal_from_service_hostname(
     232                                        gse_ctx, service, server, lp_realm());
    242233        if (!name_buffer.value) {
    243234                status = NT_STATUS_NO_MEMORY;
     
    246237        name_buffer.length = strlen((char *)name_buffer.value);
    247238        gss_maj = gss_import_name(&gss_min, &name_buffer,
    248                                   GSS_C_NT_HOSTBASED_SERVICE,
     239                                  GSS_C_NT_USER_NAME,
    249240                                  &gse_ctx->server_name);
    250241        if (gss_maj) {
    251                 DEBUG(0, ("gss_import_name failed for %s, with [%s]\n",
     242                DEBUG(5, ("gss_import_name failed for %s, with [%s]\n",
    252243                          (char *)name_buffer.value,
    253244                          gse_errstr(gse_ctx, gss_maj, gss_min)));
     
    270261                                   NULL, NULL);
    271262        if (gss_maj) {
    272                 DEBUG(0, ("gss_acquire_creds failed for %s, with [%s]\n",
    273                           (char *)name_buffer.value,
     263                DEBUG(5, ("gss_acquire_creds failed for GSS_C_NO_NAME with [%s] -"
     264                          "the caller may retry after a kinit.\n",
    274265                          gse_errstr(gse_ctx, gss_maj, gss_min)));
    275266                status = NT_STATUS_INTERNAL_ERROR;
    276267                goto err_out;
    277268        }
     269
     270#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
     271        /*
     272         * Don't force GSS_C_CONF_FLAG and GSS_C_INTEG_FLAG.
     273         *
     274         * This allows us to disable SIGN and SEAL for
     275         * AUTH_LEVEL_CONNECT and AUTH_LEVEL_INTEGRITY.
     276         *
     277         * https://groups.yahoo.com/neo/groups/cat-ietf/conversations/topics/575
     278         * http://krbdev.mit.edu/rt/Ticket/Display.html?id=6938
     279         */
     280        gss_maj = gss_set_cred_option(&gss_min, &gse_ctx->creds,
     281                                      GSS_KRB5_CRED_NO_CI_FLAGS_X,
     282                                      &empty_buffer);
     283        if (gss_maj) {
     284                DEBUG(0, ("gss_set_cred_option(GSS_KRB5_CRED_NO_CI_FLAGS_X), "
     285                          "failed with [%s]\n",
     286                          gse_errstr(gse_ctx, gss_maj, gss_min)));
     287                status = NT_STATUS_INTERNAL_ERROR;
     288                goto err_out;
     289        }
     290#endif
    278291
    279292        *_gse_ctx = gse_ctx;
     
    287300}
    288301
    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)
     302static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
     303                                          struct gse_context *gse_ctx,
     304                                          const DATA_BLOB *token_in,
     305                                          DATA_BLOB *token_out)
    293306{
    294307        OM_uint32 gss_maj, gss_min;
     
    297310        DATA_BLOB blob = data_blob_null;
    298311        NTSTATUS status;
     312        OM_uint32 time_rec = 0;
     313        struct timeval tv;
    299314
    300315        in_data.value = token_in->data;
     
    303318        gss_maj = gss_init_sec_context(&gss_min,
    304319                                        gse_ctx->creds,
    305                                         &gse_ctx->gss_ctx,
     320                                        &gse_ctx->gssapi_context,
    306321                                        gse_ctx->server_name,
    307322                                        &gse_ctx->gss_mech,
    308                                         gse_ctx->gss_c_flags,
     323                                        gse_ctx->gss_want_flags,
    309324                                        0, GSS_C_NO_CHANNEL_BINDINGS,
    310325                                        &in_data, NULL, &out_data,
    311                                         NULL, NULL);
     326                                        &gse_ctx->gss_got_flags, &time_rec);
    312327        switch (gss_maj) {
    313328        case GSS_S_COMPLETE:
    314329                /* we are done with it */
    315                 gse_ctx->more_processing = false;
     330                tv = timeval_current_ofs(time_rec, 0);
     331                gse_ctx->expire_time = timeval_to_nttime(&tv);
     332
    316333                status = NT_STATUS_OK;
    317334                break;
    318335        case GSS_S_CONTINUE_NEEDED:
    319336                /* we will need a third leg */
    320                 gse_ctx->more_processing = true;
    321                 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
    322                 status = NT_STATUS_OK;
     337                status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    323338                break;
    324339        default:
     
    329344        }
    330345
    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);
     346        /* we may be told to return nothing */
     347        if (out_data.length) {
     348                blob = data_blob_talloc(mem_ctx, out_data.value, out_data.length);
     349                if (!blob.data) {
     350                        status = NT_STATUS_NO_MEMORY;
     351                }
     352
     353                gss_maj = gss_release_buffer(&gss_min, &out_data);
     354        }
    337355
    338356done:
     
    341359}
    342360
    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)
     361static NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
     362                                bool do_sign, bool do_seal,
     363                                uint32_t add_gss_c_flags,
     364                                struct gse_context **_gse_ctx)
    348365{
    349366        struct gse_context *gse_ctx;
    350367        OM_uint32 gss_maj, gss_min;
    351         gss_OID_set_desc mech_set;
    352368        krb5_error_code ret;
    353         const char *ktname;
    354369        NTSTATUS status;
    355370
     
    360375        }
    361376
    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 
     377        ret = gse_krb5_get_server_keytab(gse_ctx->k5ctx,
     378                                         &gse_ctx->keytab);
     379        if (ret) {
     380                status = NT_STATUS_INTERNAL_ERROR;
     381                goto done;
     382        }
     383
     384#ifdef HAVE_GSS_KRB5_IMPORT_CRED
     385
     386        /* This creates a GSSAPI cred_id_t with the keytab set */
     387        gss_maj = gss_krb5_import_cred(&gss_min, NULL, NULL, gse_ctx->keytab,
     388                                       &gse_ctx->creds);
     389
     390        if (gss_maj != 0
     391            && gss_maj != (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME)) {
     392                DEBUG(0, ("gss_krb5_import_cred failed with [%s]\n",
     393                          gse_errstr(gse_ctx, gss_maj, gss_min)));
     394                status = NT_STATUS_INTERNAL_ERROR;
     395                goto done;
     396
     397                /* This is the error the MIT krb5 1.9 gives when it
     398                 * implements the function, but we do not specify the
     399                 * principal.  However, when we specify the principal
     400                 * as host$@REALM the GSS acceptor fails with 'wrong
     401                 * principal in request'.  Work around the issue by
     402                 * falling back to the alternate approach below. */
     403        } else if (gss_maj == (GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME))
     404#endif
    379405        /* FIXME!!!
    380406         * This call sets the default keytab for the whole server, not
    381407         * just for this context. Need to find a way that does not alter
    382408         * 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,
     409        {
     410                const char *ktname;
     411                gss_OID_set_desc mech_set;
     412
     413                ret = smb_krb5_keytab_name(gse_ctx, gse_ctx->k5ctx,
     414                                   gse_ctx->keytab, &ktname);
     415                if (ret) {
     416                        status = NT_STATUS_INTERNAL_ERROR;
     417                        goto done;
     418                }
     419
     420                ret = gsskrb5_register_acceptor_identity(ktname);
     421                if (ret) {
     422                        status = NT_STATUS_INTERNAL_ERROR;
     423                        goto done;
     424                }
     425
     426                mech_set.count = 1;
     427                mech_set.elements = &gse_ctx->gss_mech;
     428
     429                gss_maj = gss_acquire_cred(&gss_min,
    393430                                   GSS_C_NO_NAME,
    394431                                   GSS_C_INDEFINITE,
     
    397434                                   &gse_ctx->creds,
    398435                                   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;
     436
     437                if (gss_maj) {
     438                        DEBUG(0, ("gss_acquire_creds failed with [%s]\n",
     439                                  gse_errstr(gse_ctx, gss_maj, gss_min)));
     440                        status = NT_STATUS_INTERNAL_ERROR;
     441                        goto done;
     442                }
    404443        }
    405444
     
    415454}
    416455
    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)
     456static NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
     457                                          struct gse_context *gse_ctx,
     458                                          const DATA_BLOB *token_in,
     459                                          DATA_BLOB *token_out)
    421460{
    422461        OM_uint32 gss_maj, gss_min;
     
    425464        DATA_BLOB blob = data_blob_null;
    426465        NTSTATUS status;
     466        OM_uint32 time_rec = 0;
     467        struct timeval tv;
    427468
    428469        in_data.value = token_in->data;
     
    430471
    431472        gss_maj = gss_accept_sec_context(&gss_min,
    432                                          &gse_ctx->gss_ctx,
     473                                         &gse_ctx->gssapi_context,
    433474                                         gse_ctx->creds,
    434475                                         &in_data,
     
    437478                                         &gse_ctx->ret_mech,
    438479                                         &out_data,
    439                                          &gse_ctx->ret_flags, NULL,
    440                                          &gse_ctx->delegated_creds);
     480                                         &gse_ctx->gss_got_flags,
     481                                         &time_rec,
     482                                         &gse_ctx->delegated_cred_handle);
    441483        switch (gss_maj) {
    442484        case GSS_S_COMPLETE:
    443485                /* we are done with it */
    444                 gse_ctx->more_processing = false;
    445                 gse_ctx->authenticated = true;
     486                tv = timeval_current_ofs(time_rec, 0);
     487                gse_ctx->expire_time = timeval_to_nttime(&tv);
     488
    446489                status = NT_STATUS_OK;
    447490                break;
    448491        case GSS_S_CONTINUE_NEEDED:
    449492                /* we will need a third leg */
    450                 gse_ctx->more_processing = true;
    451                 /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
    452                 status = NT_STATUS_OK;
     493                status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    453494                break;
    454495        default:
    455                 DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
     496                DEBUG(1, ("gss_accept_sec_context failed with [%s]\n",
    456497                          gse_errstr(talloc_tos(), gss_maj, gss_min)));
    457498
    458                 if (gse_ctx->gss_ctx) {
     499                if (gse_ctx->gssapi_context) {
    459500                        gss_delete_sec_context(&gss_min,
    460                                                 &gse_ctx->gss_ctx,
     501                                                &gse_ctx->gssapi_context,
    461502                                                GSS_C_NO_BUFFER);
    462503                }
    463504
    464                 status = NT_STATUS_INTERNAL_ERROR;
    465                 goto done;
     505                /*
     506                 * If we got an output token, make Windows aware of it
     507                 * by telling it that more processing is needed
     508                 */
     509                if (out_data.length > 0) {
     510                        status = NT_STATUS_MORE_PROCESSING_REQUIRED;
     511                        /* Fall through to handle the out token */
     512                } else {
     513                        status = NT_STATUS_LOGON_FAILURE;
     514                        goto done;
     515                }
    466516        }
    467517
     
    481531}
    482532
    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 
    523533static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min)
    524534{
     
    536546                                     GSS_C_NO_OID, &msg_ctx, &msg_maj);
    537547        if (gss_maj) {
     548                goto done;
     549        }
     550        errstr = talloc_strndup(mem_ctx,
     551                                (char *)msg_maj.value,
     552                                        msg_maj.length);
     553        if (!errstr) {
    538554                goto done;
    539555        }
     
    545561        }
    546562
    547         errstr = talloc_strndup(mem_ctx,
    548                                 (char *)msg_maj.value,
    549                                         msg_maj.length);
    550         if (!errstr) {
    551                 goto done;
    552         }
    553563        errstr = talloc_strdup_append_buffer(errstr, ": ");
    554564        if (!errstr) {
     
    572582}
    573583
    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) {
     584static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
     585{
     586        struct gse_context *gse_ctx;
     587        struct cli_credentials *creds = gensec_get_credentials(gensec_security);
     588        NTSTATUS nt_status;
     589        OM_uint32 want_flags = 0;
     590        bool do_sign = false, do_seal = false;
     591        const char *hostname = gensec_get_target_hostname(gensec_security);
     592        const char *service = gensec_get_target_service(gensec_security);
     593        const char *username = cli_credentials_get_username(creds);
     594        const char *password = cli_credentials_get_password(creds);
     595
     596        if (!hostname) {
     597                DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
     598                return NT_STATUS_INVALID_PARAMETER;
     599        }
     600        if (is_ipaddress(hostname)) {
     601                DEBUG(2, ("Cannot do GSE to an IP address\n"));
     602                return NT_STATUS_INVALID_PARAMETER;
     603        }
     604        if (strcmp(hostname, "localhost") == 0) {
     605                DEBUG(2, ("GSE to 'localhost' does not make sense\n"));
     606                return NT_STATUS_INVALID_PARAMETER;
     607        }
     608
     609        if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
     610                do_sign = true;
     611        }
     612        if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
     613                do_sign = true;
     614        }
     615        if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
     616                do_seal = true;
     617        }
     618        if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
     619                want_flags |= GSS_C_DCE_STYLE;
     620        }
     621
     622        nt_status = gse_init_client(gensec_security, do_sign, do_seal, NULL,
     623                                    hostname, service,
     624                                    username, password, want_flags,
     625                                    &gse_ctx);
     626        if (!NT_STATUS_IS_OK(nt_status)) {
     627                return nt_status;
     628        }
     629        gensec_security->private_data = gse_ctx;
     630        return NT_STATUS_OK;
     631}
     632
     633static NTSTATUS gensec_gse_server_start(struct gensec_security *gensec_security)
     634{
     635        struct gse_context *gse_ctx;
     636        NTSTATUS nt_status;
     637        OM_uint32 want_flags = 0;
     638        bool do_sign = false, do_seal = false;
     639
     640        if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
     641                do_sign = true;
     642        }
     643        if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
     644                do_seal = true;
     645        }
     646        if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
     647                want_flags |= GSS_C_DCE_STYLE;
     648        }
     649
     650        nt_status = gse_init_server(gensec_security, do_sign, do_seal, want_flags,
     651                                    &gse_ctx);
     652        if (!NT_STATUS_IS_OK(nt_status)) {
     653                return nt_status;
     654        }
     655        gensec_security->private_data = gse_ctx;
     656        return NT_STATUS_OK;
     657}
     658
     659/**
     660 * Next state function for the GSE GENSEC mechanism
     661 *
     662 * @param gensec_gse_state GSE State
     663 * @param mem_ctx The TALLOC_CTX for *out to be allocated on
     664 * @param in The request, as a DATA_BLOB
     665 * @param out The reply, as an talloc()ed DATA_BLOB, on *mem_ctx
     666 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
     667 *                or NT_STATUS_OK if the user is authenticated.
     668 */
     669
     670static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security,
     671                                  TALLOC_CTX *mem_ctx,
     672                                  struct tevent_context *ev,
     673                                  const DATA_BLOB in, DATA_BLOB *out)
     674{
     675        NTSTATUS status;
     676        struct gse_context *gse_ctx =
     677                talloc_get_type_abort(gensec_security->private_data,
     678                struct gse_context);
     679
     680        switch (gensec_security->gensec_role) {
     681        case GENSEC_CLIENT:
     682                status = gse_get_client_auth_token(mem_ctx, gse_ctx,
     683                                                   &in, out);
     684                break;
     685        case GENSEC_SERVER:
     686                status = gse_get_server_auth_token(mem_ctx, gse_ctx,
     687                                                   &in, out);
     688                break;
     689        }
     690        if (!NT_STATUS_IS_OK(status)) {
     691                return status;
     692        }
     693
     694        return NT_STATUS_OK;
     695}
     696
     697static NTSTATUS gensec_gse_wrap(struct gensec_security *gensec_security,
     698                                TALLOC_CTX *mem_ctx,
     699                                const DATA_BLOB *in,
     700                                DATA_BLOB *out)
     701{
     702        struct gse_context *gse_ctx =
     703                talloc_get_type_abort(gensec_security->private_data,
     704                struct gse_context);
     705        OM_uint32 maj_stat, min_stat;
     706        gss_buffer_desc input_token, output_token;
     707        int conf_state;
     708        input_token.length = in->length;
     709        input_token.value = in->data;
     710
     711        maj_stat = gss_wrap(&min_stat,
     712                            gse_ctx->gssapi_context,
     713                            gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
     714                            GSS_C_QOP_DEFAULT,
     715                            &input_token,
     716                            &conf_state,
     717                            &output_token);
     718        if (GSS_ERROR(maj_stat)) {
     719                DEBUG(0, ("gensec_gse_wrap: GSS Wrap failed: %s\n",
     720                          gse_errstr(talloc_tos(), maj_stat, min_stat)));
    621721                return NT_STATUS_ACCESS_DENIED;
    622722        }
    623723
    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) {
     724        *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
     725        gss_release_buffer(&min_stat, &output_token);
     726
     727        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
     728            && !conf_state) {
     729                return NT_STATUS_ACCESS_DENIED;
     730        }
     731        return NT_STATUS_OK;
     732}
     733
     734static NTSTATUS gensec_gse_unwrap(struct gensec_security *gensec_security,
     735                                     TALLOC_CTX *mem_ctx,
     736                                     const DATA_BLOB *in,
     737                                     DATA_BLOB *out)
     738{
     739        struct gse_context *gse_ctx =
     740                talloc_get_type_abort(gensec_security->private_data,
     741                struct gse_context);
     742        OM_uint32 maj_stat, min_stat;
     743        gss_buffer_desc input_token, output_token;
     744        int conf_state;
     745        gss_qop_t qop_state;
     746        input_token.length = in->length;
     747        input_token.value = in->data;
     748
     749        maj_stat = gss_unwrap(&min_stat,
     750                              gse_ctx->gssapi_context,
     751                              &input_token,
     752                              &output_token,
     753                              &conf_state,
     754                              &qop_state);
     755        if (GSS_ERROR(maj_stat)) {
     756                DEBUG(0, ("gensec_gse_unwrap: GSS UnWrap failed: %s\n",
     757                          gse_errstr(talloc_tos(), maj_stat, min_stat)));
     758                return NT_STATUS_ACCESS_DENIED;
     759        }
     760
     761        *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
     762        gss_release_buffer(&min_stat, &output_token);
     763
     764        if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
     765            && !conf_state) {
     766                return NT_STATUS_ACCESS_DENIED;
     767        }
     768        return NT_STATUS_OK;
     769}
     770
     771static NTSTATUS gensec_gse_seal_packet(struct gensec_security *gensec_security,
     772                                       TALLOC_CTX *mem_ctx,
     773                                       uint8_t *data, size_t length,
     774                                       const uint8_t *whole_pdu, size_t pdu_length,
     775                                       DATA_BLOB *sig)
     776{
     777        struct gse_context *gse_ctx =
     778                talloc_get_type_abort(gensec_security->private_data,
     779                struct gse_context);
     780        bool hdr_signing = false;
     781        size_t sig_size = 0;
     782        NTSTATUS status;
     783
     784        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     785                hdr_signing = true;
     786        }
     787
     788        sig_size = gensec_gse_sig_size(gensec_security, length);
     789
     790        status = gssapi_seal_packet(gse_ctx->gssapi_context,
     791                                    &gse_ctx->gss_mech,
     792                                    hdr_signing, sig_size,
     793                                    data, length,
     794                                    whole_pdu, pdu_length,
     795                                    mem_ctx, sig);
     796        if (!NT_STATUS_IS_OK(status)) {
     797                DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu,"
     798                          "data=%zu,pdu=%zu) failed: %s\n",
     799                          hdr_signing, sig_size, length, pdu_length,
     800                          nt_errstr(status)));
     801                return status;
     802        }
     803
     804        return NT_STATUS_OK;
     805}
     806
     807static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security,
     808                                         uint8_t *data, size_t length,
     809                                         const uint8_t *whole_pdu, size_t pdu_length,
     810                                         const DATA_BLOB *sig)
     811{
     812        struct gse_context *gse_ctx =
     813                talloc_get_type_abort(gensec_security->private_data,
     814                struct gse_context);
     815        bool hdr_signing = false;
     816        NTSTATUS status;
     817
     818        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     819                hdr_signing = true;
     820        }
     821
     822        status = gssapi_unseal_packet(gse_ctx->gssapi_context,
     823                                      &gse_ctx->gss_mech,
     824                                      hdr_signing,
     825                                      data, length,
     826                                      whole_pdu, pdu_length,
     827                                      sig);
     828        if (!NT_STATUS_IS_OK(status)) {
     829                DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu,"
     830                          "data=%zu,pdu=%zu) failed: %s\n",
     831                          hdr_signing, sig->length, length, pdu_length,
     832                          nt_errstr(status)));
     833                return status;
     834        }
     835
     836        return NT_STATUS_OK;
     837}
     838
     839static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security,
     840                                       TALLOC_CTX *mem_ctx,
     841                                       const uint8_t *data, size_t length,
     842                                       const uint8_t *whole_pdu, size_t pdu_length,
     843                                       DATA_BLOB *sig)
     844{
     845        struct gse_context *gse_ctx =
     846                talloc_get_type_abort(gensec_security->private_data,
     847                struct gse_context);
     848        bool hdr_signing = false;
     849        NTSTATUS status;
     850
     851        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     852                hdr_signing = true;
     853        }
     854
     855        status = gssapi_sign_packet(gse_ctx->gssapi_context,
     856                                    &gse_ctx->gss_mech,
     857                                    hdr_signing,
     858                                    data, length,
     859                                    whole_pdu, pdu_length,
     860                                    mem_ctx, sig);
     861        if (!NT_STATUS_IS_OK(status)) {
     862                DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
     863                          "data=%zu,pdu=%zu) failed: %s\n",
     864                          hdr_signing, length, pdu_length,
     865                          nt_errstr(status)));
     866                return status;
     867        }
     868
     869        return NT_STATUS_OK;
     870}
     871
     872static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security,
     873                                        const uint8_t *data, size_t length,
     874                                        const uint8_t *whole_pdu, size_t pdu_length,
     875                                        const DATA_BLOB *sig)
     876{
     877        struct gse_context *gse_ctx =
     878                talloc_get_type_abort(gensec_security->private_data,
     879                struct gse_context);
     880        bool hdr_signing = false;
     881        NTSTATUS status;
     882
     883        if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     884                hdr_signing = true;
     885        }
     886
     887        status = gssapi_check_packet(gse_ctx->gssapi_context,
     888                                     &gse_ctx->gss_mech,
     889                                     hdr_signing,
     890                                     data, length,
     891                                     whole_pdu, pdu_length,
     892                                     sig);
     893        if (!NT_STATUS_IS_OK(status)) {
     894                DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu"
     895                          "data=%zu,pdu=%zu) failed: %s\n",
     896                          hdr_signing, sig->length, length, pdu_length,
     897                          nt_errstr(status)));
     898                return status;
     899        }
     900
     901        return NT_STATUS_OK;
     902}
     903
     904/* Try to figure out what features we actually got on the connection */
     905static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
     906                                    uint32_t feature)
     907{
     908        struct gse_context *gse_ctx =
     909                talloc_get_type_abort(gensec_security->private_data,
     910                struct gse_context);
     911
     912        if (feature & GENSEC_FEATURE_SESSION_KEY) {
     913                return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
     914        }
     915        if (feature & GENSEC_FEATURE_SIGN) {
     916                return gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG;
     917        }
     918        if (feature & GENSEC_FEATURE_SEAL) {
     919                return gse_ctx->gss_got_flags & GSS_C_CONF_FLAG;
     920        }
     921        if (feature & GENSEC_FEATURE_DCE_STYLE) {
     922                return gse_ctx->gss_got_flags & GSS_C_DCE_STYLE;
     923        }
     924        if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
     925                NTSTATUS status;
     926                uint32_t keytype;
     927
     928                if (!(gse_ctx->gss_got_flags & GSS_C_INTEG_FLAG)) {
     929                        return false;
     930                }
     931
     932                status = gssapi_get_session_key(talloc_tos(),
     933                                                gse_ctx->gssapi_context, NULL, &keytype);
     934                /*
     935                 * We should do a proper sig on the mechListMic unless
     936                 * we know we have to be backwards compatible with
     937                 * earlier windows versions. 
     938                 *
     939                 * Negotiating a non-krb5
     940                 * mech for example should be regarded as having
     941                 * NEW_SPNEGO
     942                 */
     943                if (NT_STATUS_IS_OK(status)) {
     944                        switch (keytype) {
     945                        case ENCTYPE_DES_CBC_CRC:
     946                        case ENCTYPE_DES_CBC_MD5:
     947                        case ENCTYPE_ARCFOUR_HMAC:
     948                        case ENCTYPE_DES3_CBC_SHA1:
     949                                return false;
     950                        }
     951                }
     952                return true;
     953        }
     954        /* We can always do async (rather than strict request/reply) packets.  */
     955        if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
     956                return true;
     957        }
     958        if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
     959                if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
     960                        return true;
     961                }
     962
     963                if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
     964                        return true;
     965                }
     966
     967                return false;
     968        }
     969        return false;
     970}
     971
     972static NTTIME gensec_gse_expire_time(struct gensec_security *gensec_security)
     973{
     974        struct gse_context *gse_ctx =
     975                talloc_get_type_abort(gensec_security->private_data,
     976                struct gse_context);
     977
     978        return gse_ctx->expire_time;
     979}
     980
     981/*
     982 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
     983 * (for encrypting some passwords).
     984 *
     985 * This breaks all the abstractions, but what do you expect...
     986 */
     987static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security,
     988                                       TALLOC_CTX *mem_ctx,
     989                                       DATA_BLOB *session_key)
     990{
     991        struct gse_context *gse_ctx =
     992                talloc_get_type_abort(gensec_security->private_data,
     993                struct gse_context);
     994
     995        return gssapi_get_session_key(mem_ctx, gse_ctx->gssapi_context, session_key, NULL);
     996}
     997
     998/* Get some basic (and authorization) information about the user on
     999 * this session.  This uses either the PAC (if present) or a local
     1000 * database lookup */
     1001static NTSTATUS gensec_gse_session_info(struct gensec_security *gensec_security,
     1002                                        TALLOC_CTX *mem_ctx,
     1003                                        struct auth_session_info **_session_info)
     1004{
     1005        struct gse_context *gse_ctx =
     1006                talloc_get_type_abort(gensec_security->private_data,
     1007                struct gse_context);
     1008        NTSTATUS nt_status;
     1009        TALLOC_CTX *tmp_ctx;
     1010        struct auth_session_info *session_info = NULL;
     1011        OM_uint32 maj_stat, min_stat;
     1012        DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
     1013
     1014        gss_buffer_desc name_token;
     1015        char *principal_string;
     1016
     1017        tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gse_session_info context");
     1018        NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
     1019
     1020        maj_stat = gss_display_name(&min_stat,
     1021                                    gse_ctx->client_name,
     1022                                    &name_token,
     1023                                    NULL);
     1024        if (GSS_ERROR(maj_stat)) {
     1025                DEBUG(1, ("GSS display_name failed: %s\n",
     1026                          gse_errstr(talloc_tos(), maj_stat, min_stat)));
     1027                talloc_free(tmp_ctx);
     1028                return NT_STATUS_FOOBAR;
     1029        }
     1030
     1031        principal_string = talloc_strndup(tmp_ctx,
     1032                                          (const char *)name_token.value,
     1033                                          name_token.length);
     1034
     1035        gss_release_buffer(&min_stat, &name_token);
     1036
     1037        if (!principal_string) {
     1038                talloc_free(tmp_ctx);
    6461039                return NT_STATUS_NO_MEMORY;
    6471040        }
    6481041
     1042        nt_status = gssapi_obtain_pac_blob(tmp_ctx,  gse_ctx->gssapi_context,
     1043                                           gse_ctx->client_name,
     1044                                           &pac_blob);
     1045
     1046        /* IF we have the PAC - otherwise we need to get this
     1047         * data from elsewere
     1048         */
     1049        if (NT_STATUS_IS_OK(nt_status)) {
     1050                pac_blob_ptr = &pac_blob;
     1051        }
     1052        nt_status = gensec_generate_session_info_pac(tmp_ctx,
     1053                                                     gensec_security,
     1054                                                     NULL,
     1055                                                     pac_blob_ptr, principal_string,
     1056                                                     gensec_get_remote_address(gensec_security),
     1057                                                     &session_info);
     1058        if (!NT_STATUS_IS_OK(nt_status)) {
     1059                talloc_free(tmp_ctx);
     1060                return nt_status;
     1061        }
     1062
     1063        nt_status = gensec_gse_session_key(gensec_security, session_info,
     1064                                           &session_info->session_key);
     1065        if (!NT_STATUS_IS_OK(nt_status)) {
     1066                talloc_free(tmp_ctx);
     1067                return nt_status;
     1068        }
     1069
     1070        *_session_info = talloc_move(mem_ctx, &session_info);
     1071        talloc_free(tmp_ctx);
     1072
    6491073        return NT_STATUS_OK;
    6501074}
    6511075
    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 /*
    692  * gss_get_name_attribute() in MIT krb5 1.10.0 can return unintialized pac_display_buffer
    693  * and later gss_release_buffer() will crash on attempting to release it.
    694  *
    695  * So always initialize the buffer descriptors.
    696  *
    697  * See following links for more details:
    698  * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=658514
    699  * http://krbdev.mit.edu/rt/Ticket/Display.html?user=guest&pass=guest&id=7087
    700  */
    701         gss_buffer_desc pac_buffer = {
    702                 .value = NULL,
    703                 .length = 0
    704         };
    705         gss_buffer_desc pac_display_buffer = {
    706                 .value = NULL,
    707                 .length = 0
    708         };
    709         gss_buffer_desc pac_name = {
    710                 .value = discard_const_p(char, "urn:mspac:"),
    711                 .length = sizeof("urn:mspac:") - 1
    712         };
    713         int more = -1;
    714         int authenticated = false;
    715         int complete = false;
    716         NTSTATUS status;
    717 
    718         if (!gse_ctx->authenticated) {
    719                 return NT_STATUS_ACCESS_DENIED;
    720         }
    721 
    722         gss_maj = gss_get_name_attribute(&gss_min,
    723                                          gse_ctx->client_name, &pac_name,
    724                                          &authenticated, &complete,
    725                                          &pac_buffer, &pac_display_buffer,
    726                                          &more);
    727 
    728         if (gss_maj != 0) {
    729                 DEBUG(0, ("obtaining PAC via GSSAPI gss_get_name_attribute "
    730                           "failed: %s\n",
    731                           gse_errstr(mem_ctx, gss_maj, gss_min)));
    732                 return NT_STATUS_ACCESS_DENIED;
    733         }
    734 
    735         if (authenticated && complete) {
    736                 /* The PAC blob is returned directly */
    737                 *pac_blob = data_blob_talloc(mem_ctx,
    738                                              pac_buffer.value,
    739                                              pac_buffer.length);
    740                 if (!pac_blob->data) {
    741                         status = NT_STATUS_NO_MEMORY;
    742                 } else {
    743                         status = NT_STATUS_OK;
    744                 }
    745 
    746                 gss_maj = gss_release_buffer(&gss_min, &pac_buffer);
    747                 gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer);
    748 
    749                 return status;
    750         }
    751 
    752         DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, "
    753                   "complete: %s, more: %s\n",
    754                   authenticated ? "true" : "false",
    755                   complete ? "true" : "false",
    756                   more ? "true" : "false"));
    757 
    758         return NT_STATUS_ACCESS_DENIED;
    759 }
    760 
    761 size_t gse_get_signature_length(struct gse_context *gse_ctx,
    762                                 int seal, size_t payload_size)
    763 {
    764         OM_uint32 gss_min, gss_maj;
    765         gss_iov_buffer_desc iov[2];
    766         uint8_t fakebuf[payload_size];
    767         int sealed;
    768 
    769         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
    770         iov[0].buffer.value = NULL;
    771         iov[0].buffer.length = 0;
    772         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
    773         iov[1].buffer.value = fakebuf;
    774         iov[1].buffer.length = payload_size;
    775 
    776         gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gss_ctx,
    777                                         seal, GSS_C_QOP_DEFAULT,
    778                                         &sealed, iov, 2);
    779         if (gss_maj) {
    780                 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
    781                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
     1076static size_t gensec_gse_max_input_size(struct gensec_security *gensec_security)
     1077{
     1078        struct gse_context *gse_ctx =
     1079                talloc_get_type_abort(gensec_security->private_data,
     1080                struct gse_context);
     1081        OM_uint32 maj_stat, min_stat;
     1082        OM_uint32 max_input_size;
     1083
     1084        maj_stat = gss_wrap_size_limit(&min_stat,
     1085                                       gse_ctx->gssapi_context,
     1086                                       gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
     1087                                       GSS_C_QOP_DEFAULT,
     1088                                       gse_ctx->max_wrap_buf_size,
     1089                                       &max_input_size);
     1090        if (GSS_ERROR(maj_stat)) {
     1091                TALLOC_CTX *mem_ctx = talloc_new(NULL);
     1092                DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
     1093                          gse_errstr(mem_ctx, maj_stat, min_stat)));
     1094                talloc_free(mem_ctx);
    7821095                return 0;
    7831096        }
    7841097
    785         return iov[0].buffer.length;
    786 }
    787 
    788 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    789                   DATA_BLOB *data, DATA_BLOB *signature)
    790 {
    791         OM_uint32 gss_min, gss_maj;
    792         gss_iov_buffer_desc iov[2];
    793         int req_seal = 1; /* setting to 1 means we request sign+seal */
    794         int sealed;
    795         NTSTATUS status;
    796 
    797         /* allocate the memory ourselves so we do not need to talloc_memdup */
    798         signature->length = gse_get_signature_length(gse_ctx, 1, data->length);
    799         if (!signature->length) {
    800                 return NT_STATUS_INTERNAL_ERROR;
    801         }
    802         signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
    803         if (!signature->data) {
    804                 return NT_STATUS_NO_MEMORY;
    805         }
    806         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
    807         iov[0].buffer.value = signature->data;
    808         iov[0].buffer.length = signature->length;
    809 
    810         /* data is encrypted in place, which is ok */
    811         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
    812         iov[1].buffer.value = data->data;
    813         iov[1].buffer.length = data->length;
    814 
    815         gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gss_ctx,
    816                                 req_seal, GSS_C_QOP_DEFAULT,
    817                                 &sealed, iov, 2);
    818         if (gss_maj) {
    819                 DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
    820                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
    821                 status = NT_STATUS_ACCESS_DENIED;
    822                 goto done;
    823         }
    824 
    825         if (!sealed) {
    826                 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
    827                 status = NT_STATUS_ACCESS_DENIED;
    828                 goto done;
    829         }
    830 
    831         status = NT_STATUS_OK;
    832 
    833         DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
    834                    (int)iov[1].buffer.length, (int)iov[0].buffer.length));
    835 
    836 done:
    837         return status;
    838 }
    839 
    840 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    841                     DATA_BLOB *data, DATA_BLOB *signature)
    842 {
    843         OM_uint32 gss_min, gss_maj;
    844         gss_iov_buffer_desc iov[2];
    845         int sealed;
    846         NTSTATUS status;
    847 
    848         iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
    849         iov[0].buffer.value = signature->data;
    850         iov[0].buffer.length = signature->length;
    851 
    852         /* data is decrypted in place, which is ok */
    853         iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
    854         iov[1].buffer.value = data->data;
    855         iov[1].buffer.length = data->length;
    856 
    857         gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gss_ctx,
    858                                  &sealed, NULL, iov, 2);
    859         if (gss_maj) {
    860                 DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
    861                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
    862                 status = NT_STATUS_ACCESS_DENIED;
    863                 goto done;
    864         }
    865 
    866         if (!sealed) {
    867                 DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
    868                 status = NT_STATUS_ACCESS_DENIED;
    869                 goto done;
    870         }
    871 
    872         status = NT_STATUS_OK;
    873 
    874         DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
    875                    (int)iov[1].buffer.length, (int)iov[0].buffer.length));
    876 
    877 done:
    878         return status;
    879 }
    880 
    881 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    882                   DATA_BLOB *data, DATA_BLOB *signature)
    883 {
    884         OM_uint32 gss_min, gss_maj;
    885         gss_buffer_desc in_data = { 0, NULL };
    886         gss_buffer_desc out_data = { 0, NULL};
    887         NTSTATUS status;
    888 
    889         in_data.value = data->data;
    890         in_data.length = data->length;
    891 
    892         gss_maj = gss_get_mic(&gss_min, gse_ctx->gss_ctx,
    893                               GSS_C_QOP_DEFAULT,
    894                               &in_data, &out_data);
    895         if (gss_maj) {
    896                 DEBUG(0, ("gss_get_mic failed with [%s]\n",
    897                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
    898                 status = NT_STATUS_ACCESS_DENIED;
    899                 goto done;
    900         }
    901 
    902         *signature = data_blob_talloc(mem_ctx,
    903                                         out_data.value, out_data.length);
    904         if (!signature->data) {
    905                 status = NT_STATUS_NO_MEMORY;
    906                 goto done;
    907         }
    908 
    909         status = NT_STATUS_OK;
    910 
    911 done:
    912         if (out_data.value) {
    913                 gss_maj = gss_release_buffer(&gss_min, &out_data);
    914         }
    915         return status;
    916 }
    917 
    918 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    919                       DATA_BLOB *data, DATA_BLOB *signature)
    920 {
    921         OM_uint32 gss_min, gss_maj;
    922         gss_buffer_desc in_data = { 0, NULL };
    923         gss_buffer_desc in_token = { 0, NULL};
    924         NTSTATUS status;
    925 
    926         in_data.value = data->data;
    927         in_data.length = data->length;
    928         in_token.value = signature->data;
    929         in_token.length = signature->length;
    930 
    931         gss_maj = gss_verify_mic(&gss_min, gse_ctx->gss_ctx,
    932                                  &in_data, &in_token, NULL);
    933         if (gss_maj) {
    934                 DEBUG(0, ("gss_verify_mic failed with [%s]\n",
    935                           gse_errstr(talloc_tos(), gss_maj, gss_min)));
    936                 status = NT_STATUS_ACCESS_DENIED;
    937                 goto done;
    938         }
    939 
    940         status = NT_STATUS_OK;
    941 
    942 done:
    943         return status;
    944 }
    945 
    946 #else
    947 
    948 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
    949                           bool do_sign, bool do_seal,
    950                           const char *ccache_name,
    951                           const char *server,
    952                           const char *service,
    953                           const char *username,
    954                           const char *password,
    955                           uint32_t add_gss_c_flags,
    956                           struct gse_context **_gse_ctx)
    957 {
    958         return NT_STATUS_NOT_IMPLEMENTED;
    959 }
    960 
    961 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
    962                                    struct gse_context *gse_ctx,
    963                                    DATA_BLOB *token_in,
    964                                    DATA_BLOB *token_out)
    965 {
    966         return NT_STATUS_NOT_IMPLEMENTED;
    967 }
    968 
    969 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
    970                          bool do_sign, bool do_seal,
    971                          uint32_t add_gss_c_flags,
    972                          const char *keytab,
    973                          struct gse_context **_gse_ctx)
    974 {
    975         return NT_STATUS_NOT_IMPLEMENTED;
    976 }
    977 
    978 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
    979                                    struct gse_context *gse_ctx,
    980                                    DATA_BLOB *token_in,
    981                                    DATA_BLOB *token_out)
    982 {
    983         return NT_STATUS_NOT_IMPLEMENTED;
    984 }
    985 
    986 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx)
    987 {
    988         return NT_STATUS_NOT_IMPLEMENTED;
    989 }
    990 
    991 bool gse_require_more_processing(struct gse_context *gse_ctx)
    992 {
    993         return false;
    994 }
    995 
    996 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
    997                               struct gse_context *gse_ctx)
    998 {
    999         return data_blob_null;
    1000 }
    1001 
    1002 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
    1003                              TALLOC_CTX *mem_ctx, char **cli_name)
    1004 {
    1005         return NT_STATUS_NOT_IMPLEMENTED;
    1006 }
    1007 
    1008 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
    1009                             TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
    1010 {
    1011         return NT_STATUS_NOT_IMPLEMENTED;
    1012 }
    1013 
    1014 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
    1015                           TALLOC_CTX *mem_ctx, DATA_BLOB *pac)
    1016 {
    1017         return NT_STATUS_NOT_IMPLEMENTED;
    1018 }
    1019 
    1020 size_t gse_get_signature_length(struct gse_context *gse_ctx,
    1021                                 int seal, size_t payload_size)
    1022 {
    1023         return 0;
    1024 }
    1025 
    1026 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    1027                   DATA_BLOB *data, DATA_BLOB *signature)
    1028 {
    1029         return NT_STATUS_NOT_IMPLEMENTED;
    1030 }
    1031 
    1032 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    1033                     DATA_BLOB *data, DATA_BLOB *signature)
    1034 {
    1035         return NT_STATUS_NOT_IMPLEMENTED;
    1036 }
    1037 
    1038 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    1039                   DATA_BLOB *data, DATA_BLOB *signature)
    1040 {
    1041         return NT_STATUS_NOT_IMPLEMENTED;
    1042 }
    1043 
    1044 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    1045                       DATA_BLOB *data, DATA_BLOB *signature)
    1046 {
    1047         return NT_STATUS_NOT_IMPLEMENTED;
    1048 }
    1049 
    1050 #endif /* HAVE_KRB5 && HAVE_GSSAPI_EXT_H && HAVE_GSS_WRAP_IOV */
     1098        return max_input_size;
     1099}
     1100
     1101/* Find out the maximum output size negotiated on this connection */
     1102static size_t gensec_gse_max_wrapped_size(struct gensec_security *gensec_security)
     1103{
     1104        struct gse_context *gse_ctx =
     1105                talloc_get_type_abort(gensec_security->private_data,
     1106                struct gse_context);
     1107        return gse_ctx->max_wrap_buf_size;
     1108}
     1109
     1110static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
     1111                                  size_t data_size)
     1112{
     1113        struct gse_context *gse_ctx =
     1114                talloc_get_type_abort(gensec_security->private_data,
     1115                struct gse_context);
     1116
     1117        if (gse_ctx->sig_size > 0) {
     1118                return gse_ctx->sig_size;
     1119        }
     1120
     1121        gse_ctx->sig_size = gssapi_get_sig_size(gse_ctx->gssapi_context,
     1122                                                &gse_ctx->gss_mech,
     1123                                                gse_ctx->gss_want_flags,
     1124                                                data_size);
     1125        return gse_ctx->sig_size;
     1126}
     1127
     1128static const char *gensec_gse_krb5_oids[] = {
     1129        GENSEC_OID_KERBEROS5_OLD,
     1130        GENSEC_OID_KERBEROS5,
     1131        NULL
     1132};
     1133
     1134const struct gensec_security_ops gensec_gse_krb5_security_ops = {
     1135        .name           = "gse_krb5",
     1136        .auth_type      = DCERPC_AUTH_TYPE_KRB5,
     1137        .oid            = gensec_gse_krb5_oids,
     1138        .client_start   = gensec_gse_client_start,
     1139        .server_start   = gensec_gse_server_start,
     1140        .magic          = gensec_magic_check_krb5_oid,
     1141        .update         = gensec_gse_update,
     1142        .session_key    = gensec_gse_session_key,
     1143        .session_info   = gensec_gse_session_info,
     1144        .sig_size       = gensec_gse_sig_size,
     1145        .sign_packet    = gensec_gse_sign_packet,
     1146        .check_packet   = gensec_gse_check_packet,
     1147        .seal_packet    = gensec_gse_seal_packet,
     1148        .unseal_packet  = gensec_gse_unseal_packet,
     1149        .max_input_size   = gensec_gse_max_input_size,
     1150        .max_wrapped_size = gensec_gse_max_wrapped_size,
     1151        .wrap           = gensec_gse_wrap,
     1152        .unwrap         = gensec_gse_unwrap,
     1153        .have_feature   = gensec_gse_have_feature,
     1154        .expire_time    = gensec_gse_expire_time,
     1155        .enabled        = true,
     1156        .kerberos       = true,
     1157        .priority       = GENSEC_GSSAPI
     1158};
     1159
     1160#endif /* HAVE_KRB5 */
  • vendor/current/source3/librpc/crypto/gse.h

    r740 r988  
    2222struct gse_context;
    2323
    24 #ifndef GSS_C_DCE_STYLE
    25 #define GSS_C_DCE_STYLE 0x1000
    26 #endif
    27 
    28 NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
    29                           bool do_sign, bool do_seal,
    30                           const char *ccache_name,
    31                           const char *server,
    32                           const char *service,
    33                           const char *username,
    34                           const char *password,
    35                           uint32_t add_gss_c_flags,
    36                           struct gse_context **_gse_ctx);
    37 NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
    38                                    struct gse_context *gse_ctx,
    39                                    DATA_BLOB *token_in,
    40                                    DATA_BLOB *token_out);
    41 
    42 NTSTATUS gse_init_server(TALLOC_CTX *mem_ctx,
    43                          bool do_sign, bool do_seal,
    44                          uint32_t add_gss_c_flags,
    45                          const char *keytab,
    46                          struct gse_context **_gse_ctx);
    47 NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx,
    48                                    struct gse_context *gse_ctx,
    49                                    DATA_BLOB *token_in,
    50                                    DATA_BLOB *token_out);
    51 NTSTATUS gse_verify_server_auth_flags(struct gse_context *gse_ctx);
    52 
    53 bool gse_require_more_processing(struct gse_context *gse_ctx);
    54 DATA_BLOB gse_get_session_key(TALLOC_CTX *mem_ctx,
    55                                 struct gse_context *gse_ctx);
    56 NTSTATUS gse_get_client_name(struct gse_context *gse_ctx,
    57                              TALLOC_CTX *mem_ctx, char **client_name);
    58 NTSTATUS gse_get_authz_data(struct gse_context *gse_ctx,
    59                             TALLOC_CTX *mem_ctx, DATA_BLOB *pac);
    60 NTSTATUS gse_get_pac_blob(struct gse_context *gse_ctx,
    61                           TALLOC_CTX *mem_ctx, DATA_BLOB *pac);
    62 
    63 size_t gse_get_signature_length(struct gse_context *gse_ctx,
    64                                 int seal, size_t payload_size);
    65 NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    66                   DATA_BLOB *data, DATA_BLOB *signature);
    67 NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    68                     DATA_BLOB *data, DATA_BLOB *signature);
    69 NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    70                   DATA_BLOB *data, DATA_BLOB *signature);
    71 NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
    72                       DATA_BLOB *data, DATA_BLOB *signature);
     24extern const struct gensec_security_ops gensec_gse_krb5_security_ops;
    7325
    7426#endif /* _GSE_H_ */
  • vendor/current/source3/librpc/crypto/gse_krb5.c

    r740 r988  
    2222#include "secrets.h"
    2323#include "gse_krb5.h"
     24#include "lib/param/loadparm.h"
    2425
    2526#ifdef HAVE_KRB5
     
    9192        int err;
    9293
    93         err = asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
     94        err = asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
    9495        if (err == -1) {
    9596                return -1;
    9697        }
    9798
    98         strlower_m(host_princ_s);
     99        if (!strlower_m(host_princ_s)) {
     100                SAFE_FREE(host_princ_s);
     101                return -1;
     102        }
    99103        ret = smb_krb5_parse_name(krbctx, host_princ_s, host_princ);
    100104        if (ret) {
     
    170174#define CLEARTEXT_PRIV_ENCTYPE -99
    171175
    172 static krb5_error_code get_mem_keytab_from_secrets(krb5_context krbctx,
    173                                                    krb5_keytab *keytab)
     176static krb5_error_code fill_mem_keytab_from_secrets(krb5_context krbctx,
     177                                                    krb5_keytab *keytab)
    174178{
    175179        krb5_error_code ret;
     
    194198        }
    195199        pwd_len = strlen(pwd);
    196 
    197         if (*keytab == NULL) {
    198                 /* create memory keytab */
    199                 ret = krb5_kt_resolve(krbctx, SRV_MEM_KEYTAB_NAME, keytab);
    200                 if (ret) {
    201                         DEBUG(1, (__location__ ": Failed to get memory "
    202                                   "keytab!\n"));
    203                         return ret;
    204                 }
    205         }
    206200
    207201        ZERO_STRUCT(kt_entry);
     
    281275        }
    282276
    283         pwd_old = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
     277        pwd_old = secrets_fetch_prev_machine_password(lp_workgroup());
    284278        if (!pwd_old) {
    285279                DEBUG(10, (__location__ ": no prev machine password\n"));
     
    332326        }
    333327
    334         if (ret) {
    335                 if (*keytab) {
    336                         krb5_kt_close(krbctx, *keytab);
    337                         *keytab = NULL;
    338                 }
    339         }
    340 
    341328        return ret;
    342329}
    343330
    344 static krb5_error_code get_mem_keytab_from_system_keytab(krb5_context krbctx,
    345                                                          krb5_keytab *keytab,
    346                                                          bool verify)
     331static krb5_error_code fill_mem_keytab_from_system_keytab(krb5_context krbctx,
     332                                                          krb5_keytab *mkeytab)
    347333{
    348         return KRB5_KT_NOTFOUND;
     334        krb5_error_code ret = 0;
     335        krb5_keytab keytab = NULL;
     336        krb5_kt_cursor kt_cursor;
     337        krb5_keytab_entry kt_entry;
     338        char *valid_princ_formats[7] = { NULL, NULL, NULL,
     339                                         NULL, NULL, NULL, NULL };
     340        char *entry_princ_s = NULL;
     341        fstring my_name, my_fqdn;
     342        int i;
     343        int err;
     344
     345        /* Generate the list of principal names which we expect
     346         * clients might want to use for authenticating to the file
     347         * service.  We allow name$,{host,cifs}/{name,fqdn,name.REALM}. */
     348
     349        fstrcpy(my_name, lp_netbios_name());
     350
     351        my_fqdn[0] = '\0';
     352        name_to_fqdn(my_fqdn, lp_netbios_name());
     353
     354        err = asprintf(&valid_princ_formats[0],
     355                        "%s$@%s", my_name, lp_realm());
     356        if (err == -1) {
     357                ret = ENOMEM;
     358                goto out;
     359        }
     360        err = asprintf(&valid_princ_formats[1],
     361                        "host/%s@%s", my_name, lp_realm());
     362        if (err == -1) {
     363                ret = ENOMEM;
     364                goto out;
     365        }
     366        err = asprintf(&valid_princ_formats[2],
     367                        "host/%s@%s", my_fqdn, lp_realm());
     368        if (err == -1) {
     369                ret = ENOMEM;
     370                goto out;
     371        }
     372        err = asprintf(&valid_princ_formats[3],
     373                        "host/%s.%s@%s", my_name, lp_realm(), lp_realm());
     374        if (err == -1) {
     375                ret = ENOMEM;
     376                goto out;
     377        }
     378        err = asprintf(&valid_princ_formats[4],
     379                        "cifs/%s@%s", my_name, lp_realm());
     380        if (err == -1) {
     381                ret = ENOMEM;
     382                goto out;
     383        }
     384        err = asprintf(&valid_princ_formats[5],
     385                        "cifs/%s@%s", my_fqdn, lp_realm());
     386        if (err == -1) {
     387                ret = ENOMEM;
     388                goto out;
     389        }
     390        err = asprintf(&valid_princ_formats[6],
     391                        "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm());
     392        if (err == -1) {
     393                ret = ENOMEM;
     394                goto out;
     395        }
     396
     397        ZERO_STRUCT(kt_entry);
     398        ZERO_STRUCT(kt_cursor);
     399
     400        ret = smb_krb5_open_keytab(krbctx, NULL, false, &keytab);
     401        if (ret) {
     402                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     403                          error_message(ret)));
     404                goto out;
     405        }
     406
     407        /*
     408         * Iterate through the keytab.  For each key, if the principal
     409         * name case-insensitively matches one of the allowed formats,
     410         * copy it to the memory keytab.
     411         */
     412
     413        ret = krb5_kt_start_seq_get(krbctx, keytab, &kt_cursor);
     414        if (ret) {
     415                DEBUG(1, (__location__ ": krb5_kt_start_seq_get failed (%s)\n",
     416                          error_message(ret)));
     417                goto out;
     418        }
     419
     420        while ((krb5_kt_next_entry(krbctx, keytab,
     421                                   &kt_entry, &kt_cursor) == 0)) {
     422                ret = smb_krb5_unparse_name(talloc_tos(), krbctx,
     423                                            kt_entry.principal,
     424                                            &entry_princ_s);
     425                if (ret) {
     426                        DEBUG(1, (__location__ ": smb_krb5_unparse_name "
     427                                  "failed (%s)\n", error_message(ret)));
     428                        goto out;
     429                }
     430
     431                for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
     432
     433                        if (!strequal(entry_princ_s, valid_princ_formats[i])) {
     434                                continue;
     435                        }
     436
     437                        ret = krb5_kt_add_entry(krbctx, *mkeytab, &kt_entry);
     438                        if (ret) {
     439                                DEBUG(1, (__location__ ": smb_krb5_unparse_name "
     440                                          "failed (%s)\n", error_message(ret)));
     441                                goto out;
     442                        }
     443                }
     444
     445                /* Free the name we parsed. */
     446                TALLOC_FREE(entry_princ_s);
     447
     448                /* Free the entry we just read. */
     449                smb_krb5_kt_free_entry(krbctx, &kt_entry);
     450                ZERO_STRUCT(kt_entry);
     451        }
     452        krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor);
     453
     454        ZERO_STRUCT(kt_cursor);
     455
     456out:
     457
     458        for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
     459                SAFE_FREE(valid_princ_formats[i]);
     460        }
     461
     462        TALLOC_FREE(entry_princ_s);
     463
     464        {
     465                krb5_keytab_entry zero_kt_entry;
     466                ZERO_STRUCT(zero_kt_entry);
     467                if (memcmp(&zero_kt_entry, &kt_entry,
     468                           sizeof(krb5_keytab_entry))) {
     469                        smb_krb5_kt_free_entry(krbctx, &kt_entry);
     470                }
     471        }
     472
     473        {
     474                krb5_kt_cursor zero_csr;
     475                ZERO_STRUCT(zero_csr);
     476                if ((memcmp(&kt_cursor, &zero_csr,
     477                            sizeof(krb5_kt_cursor)) != 0) && keytab) {
     478                        krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor);
     479                }
     480        }
     481
     482        if (keytab) {
     483                krb5_kt_close(krbctx, keytab);
     484        }
     485
     486        return ret;
     487}
     488
     489static krb5_error_code fill_mem_keytab_from_dedicated_keytab(krb5_context krbctx,
     490                                                             krb5_keytab *mkeytab)
     491{
     492        krb5_error_code ret = 0;
     493        krb5_keytab keytab = NULL;
     494        krb5_kt_cursor kt_cursor;
     495        krb5_keytab_entry kt_entry;
     496
     497        ret = smb_krb5_open_keytab(krbctx, lp_dedicated_keytab_file(),
     498                                   false, &keytab);
     499        if (ret) {
     500                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     501                          error_message(ret)));
     502                return ret;
     503        }
     504
     505        /*
     506         * Iterate through the keytab.  For each key, if the principal
     507         * name case-insensitively matches one of the allowed formats,
     508         * copy it to the memory keytab.
     509         */
     510
     511        ret = krb5_kt_start_seq_get(krbctx, keytab, &kt_cursor);
     512        if (ret) {
     513                DEBUG(1, (__location__ ": krb5_kt_start_seq_get failed (%s)\n",
     514                          error_message(ret)));
     515                goto out;
     516        }
     517
     518        while ((krb5_kt_next_entry(krbctx, keytab,
     519                                   &kt_entry, &kt_cursor) == 0)) {
     520
     521                ret = krb5_kt_add_entry(krbctx, *mkeytab, &kt_entry);
     522
     523                /* Free the entry we just read. */
     524                smb_krb5_kt_free_entry(krbctx, &kt_entry);
     525
     526                if (ret) {
     527                        DEBUG(1, (__location__ ": smb_krb5_unparse_name "
     528                                  "failed (%s)\n", error_message(ret)));
     529                        break;
     530                }
     531        }
     532        krb5_kt_end_seq_get(krbctx, keytab, &kt_cursor);
     533
     534out:
     535       
     536        krb5_kt_close(krbctx, keytab);
     537
     538        return ret;
    349539}
    350540
     
    352542                                           krb5_keytab *keytab)
    353543{
    354         krb5_error_code ret;
     544        krb5_error_code ret = 0;
     545        krb5_error_code ret1 = 0;
     546        krb5_error_code ret2 = 0;
    355547
    356548        *keytab = NULL;
     549
     550        /* create memory keytab */
     551        ret = krb5_kt_resolve(krbctx, SRV_MEM_KEYTAB_NAME, keytab);
     552        if (ret) {
     553                DEBUG(1, (__location__ ": Failed to get memory "
     554                          "keytab!\n"));
     555                return ret;
     556        }
    357557
    358558        switch (lp_kerberos_method()) {
    359559        default:
    360560        case KERBEROS_VERIFY_SECRETS:
    361                 ret = get_mem_keytab_from_secrets(krbctx, keytab);
     561                ret = fill_mem_keytab_from_secrets(krbctx, keytab);
    362562                break;
    363563        case KERBEROS_VERIFY_SYSTEM_KEYTAB:
    364                 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, true);
     564                ret = fill_mem_keytab_from_system_keytab(krbctx, keytab);
    365565                break;
    366566        case KERBEROS_VERIFY_DEDICATED_KEYTAB:
    367567                /* just use whatever keytab is configured */
    368                 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, false);
     568                ret = fill_mem_keytab_from_dedicated_keytab(krbctx, keytab);
    369569                break;
    370570        case KERBEROS_VERIFY_SECRETS_AND_KEYTAB:
    371                 ret = get_mem_keytab_from_secrets(krbctx, keytab);
    372                 if (ret) {
     571                ret1 = fill_mem_keytab_from_secrets(krbctx, keytab);
     572                if (ret1) {
    373573                        DEBUG(3, (__location__ ": Warning! Unable to set mem "
    374574                                  "keytab from secrets!\n"));
    375575                }
    376576                /* Now append system keytab keys too */
    377                 ret = get_mem_keytab_from_system_keytab(krbctx, keytab, true);
    378                 if (ret) {
     577                ret2 = fill_mem_keytab_from_system_keytab(krbctx, keytab);
     578                if (ret2) {
    379579                        DEBUG(3, (__location__ ": Warning! Unable to set mem "
    380                                   "keytab from secrets!\n"));
     580                                  "keytab from system keytab!\n"));
     581                }
     582                if (ret1 == 0 || ret2 == 0) {
     583                        ret = 0;
     584                } else {
     585                        ret = ret1;
    381586                }
    382587                break;
     588        }
     589
     590        if (ret) {
     591                krb5_kt_close(krbctx, *keytab);
     592                *keytab = NULL;
     593                DEBUG(1,("%s: Error! Unable to set mem keytab - %d\n",
     594                         __location__, ret));
    383595        }
    384596
Note: See TracChangeset for help on using the changeset viewer.