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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libads/sasl.c

    r919 r988  
    2020#include "includes.h"
    2121#include "../libcli/auth/spnego.h"
    22 #include "../libcli/auth/ntlmssp.h"
     22#include "auth/credentials/credentials.h"
     23#include "auth/gensec/gensec.h"
     24#include "auth_generic.h"
    2325#include "ads.h"
    2426#include "smb_krb5.h"
     27#include "system/gssapi.h"
     28#include "lib/param/loadparm.h"
    2529
    2630#ifdef HAVE_LDAP
    2731
    28 static ADS_STATUS ads_sasl_ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
    29 {
    30         struct ntlmssp_state *ntlmssp_state =
    31                 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
    32         ADS_STATUS status;
     32static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
     33{
     34        struct gensec_security *gensec_security =
     35                talloc_get_type_abort(ads->ldap.wrap_private_data,
     36                struct gensec_security);
    3337        NTSTATUS nt_status;
    34         DATA_BLOB sig;
    35         TALLOC_CTX *frame;
    36         uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE);
    37 
    38         frame = talloc_stackframe();
    39         /* copy the data to the right location */
    40         memcpy(dptr, buf, len);
    41 
    42         /* create the signature and may encrypt the data */
    43         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
    44                 nt_status = ntlmssp_seal_packet(ntlmssp_state,
    45                                                 frame,
    46                                                 dptr, len,
    47                                                 dptr, len,
    48                                                 &sig);
    49         } else {
    50                 nt_status = ntlmssp_sign_packet(ntlmssp_state,
    51                                                 frame,
    52                                                 dptr, len,
    53                                                 dptr, len,
    54                                                 &sig);
    55         }
    56         status = ADS_ERROR_NT(nt_status);
    57         if (!ADS_ERR_OK(status)) return status;
    58 
    59         /* copy the signature to the right location */
    60         memcpy(ads->ldap.out.buf + 4,
    61                sig.data, NTLMSSP_SIG_SIZE);
     38        DATA_BLOB unwrapped, wrapped;
     39        TALLOC_CTX *frame = talloc_stackframe();
     40
     41        unwrapped = data_blob_const(buf, len);
     42
     43        nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped);
     44        if (!NT_STATUS_IS_OK(nt_status)) {
     45                TALLOC_FREE(frame);
     46                return ADS_ERROR_NT(nt_status);
     47        }
     48
     49        if ((ads->ldap.out.size - 4) < wrapped.length) {
     50                TALLOC_FREE(frame);
     51                return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     52        }
     53
     54        /* copy the wrapped blob to the right location */
     55        memcpy(ads->ldap.out.buf + 4, wrapped.data, wrapped.length);
     56
     57        /* set how many bytes must be written to the underlying socket */
     58        ads->ldap.out.left = 4 + wrapped.length;
    6259
    6360        TALLOC_FREE(frame);
    6461
     62        return ADS_SUCCESS;
     63}
     64
     65static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads)
     66{
     67        struct gensec_security *gensec_security =
     68                talloc_get_type_abort(ads->ldap.wrap_private_data,
     69                struct gensec_security);
     70        NTSTATUS nt_status;
     71        DATA_BLOB unwrapped, wrapped;
     72        TALLOC_CTX *frame = talloc_stackframe();
     73
     74        wrapped = data_blob_const(ads->ldap.in.buf + 4, ads->ldap.in.ofs - 4);
     75
     76        nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped);
     77        if (!NT_STATUS_IS_OK(nt_status)) {
     78                TALLOC_FREE(frame);
     79                return ADS_ERROR_NT(nt_status);
     80        }
     81
     82        if (wrapped.length < unwrapped.length) {
     83                TALLOC_FREE(frame);
     84                return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     85        }
     86
     87        /* copy the wrapped blob to the right location */
     88        memcpy(ads->ldap.in.buf + 4, unwrapped.data, unwrapped.length);
     89
    6590        /* set how many bytes must be written to the underlying socket */
    66         ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len;
     91        ads->ldap.in.left       = unwrapped.length;
     92        ads->ldap.in.ofs        = 4;
     93
     94        TALLOC_FREE(frame);
    6795
    6896        return ADS_SUCCESS;
    6997}
    7098
    71 static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads)
    72 {
    73         struct ntlmssp_state *ntlmssp_state =
    74                 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
    75         ADS_STATUS status;
    76         NTSTATUS nt_status;
    77         DATA_BLOB sig;
    78         uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE);
    79         uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE);
    80 
    81         /* wrap the signature into a DATA_BLOB */
    82         sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE);
    83 
    84         /* verify the signature and maybe decrypt the data */
    85         if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
    86                 nt_status = ntlmssp_unseal_packet(ntlmssp_state,
    87                                                   dptr, dlen,
    88                                                   dptr, dlen,
    89                                                   &sig);
    90         } else {
    91                 nt_status = ntlmssp_check_packet(ntlmssp_state,
    92                                                  dptr, dlen,
    93                                                  dptr, dlen,
    94                                                  &sig);
    95         }
    96         status = ADS_ERROR_NT(nt_status);
    97         if (!ADS_ERR_OK(status)) return status;
    98 
    99         /* set the amount of bytes for the upper layer and set the ofs to the data */
    100         ads->ldap.in.left       = dlen;
    101         ads->ldap.in.ofs        = 4 + NTLMSSP_SIG_SIZE;
    102 
    103         return ADS_SUCCESS;
    104 }
    105 
    106 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads)
    107 {
    108         struct ntlmssp_state *ntlmssp_state =
    109                 (struct ntlmssp_state *)ads->ldap.wrap_private_data;
    110 
    111         TALLOC_FREE(ntlmssp_state);
     99static void ads_sasl_gensec_disconnect(ADS_STRUCT *ads)
     100{
     101        struct gensec_security *gensec_security =
     102                talloc_get_type_abort(ads->ldap.wrap_private_data,
     103                struct gensec_security);
     104
     105        TALLOC_FREE(gensec_security);
    112106
    113107        ads->ldap.wrap_ops = NULL;
     
    115109}
    116110
    117 static const struct ads_saslwrap_ops ads_sasl_ntlmssp_ops = {
    118         .name           = "ntlmssp",
    119         .wrap           = ads_sasl_ntlmssp_wrap,
    120         .unwrap         = ads_sasl_ntlmssp_unwrap,
    121         .disconnect     = ads_sasl_ntlmssp_disconnect
     111static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
     112        .name           = "gensec",
     113        .wrap           = ads_sasl_gensec_wrap,
     114        .unwrap         = ads_sasl_gensec_unwrap,
     115        .disconnect     = ads_sasl_gensec_disconnect
    122116};
    123117
    124118/*
    125    perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
     119   perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
    126120   we fit on one socket??)
    127121*/
    128 static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
    129 {
    130         DATA_BLOB msg1 = data_blob_null;
    131         DATA_BLOB blob = data_blob_null;
     122static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
     123                                const char *sasl,
     124                                enum credentials_use_kerberos krb5_state,
     125                                const char *target_service,
     126                                const char *target_hostname,
     127                                const DATA_BLOB server_blob)
     128{
    132129        DATA_BLOB blob_in = data_blob_null;
    133130        DATA_BLOB blob_out = data_blob_null;
    134         struct berval cred, *scred = NULL;
    135131        int rc;
    136132        NTSTATUS nt_status;
    137133        ADS_STATUS status;
    138         int turn = 1;
    139         uint32 features = 0;
    140 
    141         struct ntlmssp_state *ntlmssp_state;
    142 
    143         nt_status = ntlmssp_client_start(NULL,
    144                                          global_myname(),
    145                                          lp_workgroup(),
    146                                          lp_client_ntlmv2_auth(),
    147                                          &ntlmssp_state);
     134        struct auth_generic_state *auth_generic_state;
     135        bool use_spnego_principal = lp_client_use_spnego_principal();
     136        const char *sasl_list[] = { sasl, NULL };
     137        NTTIME end_nt_time;
     138
     139        nt_status = auth_generic_client_prepare(NULL, &auth_generic_state);
    148140        if (!NT_STATUS_IS_OK(nt_status)) {
    149141                return ADS_ERROR_NT(nt_status);
    150142        }
    151         ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;
    152 
    153         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
     143
     144        if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
    154145                return ADS_ERROR_NT(nt_status);
    155146        }
    156         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
     147        if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
    157148                return ADS_ERROR_NT(nt_status);
    158149        }
    159         if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
     150        if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
    160151                return ADS_ERROR_NT(nt_status);
     152        }
     153
     154        if (server_blob.length == 0) {
     155                use_spnego_principal = false;
     156        }
     157
     158        if (krb5_state == CRED_DONT_USE_KERBEROS) {
     159                use_spnego_principal = false;
     160        }
     161
     162        cli_credentials_set_kerberos_state(auth_generic_state->credentials,
     163                                           krb5_state);
     164
     165        if (target_service != NULL) {
     166                nt_status = gensec_set_target_service(
     167                                        auth_generic_state->gensec_security,
     168                                        target_service);
     169                if (!NT_STATUS_IS_OK(nt_status)) {
     170                        return ADS_ERROR_NT(nt_status);
     171                }
     172        }
     173
     174        if (target_hostname != NULL) {
     175                nt_status = gensec_set_target_hostname(
     176                                        auth_generic_state->gensec_security,
     177                                        target_hostname);
     178                if (!NT_STATUS_IS_OK(nt_status)) {
     179                        return ADS_ERROR_NT(nt_status);
     180                }
     181        }
     182
     183        if (target_service != NULL && target_hostname != NULL) {
     184                use_spnego_principal = false;
    161185        }
    162186
    163187        switch (ads->ldap.wrap_type) {
    164188        case ADS_SASLWRAP_TYPE_SEAL:
    165                 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
     189                gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
     190                gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL);
    166191                break;
    167192        case ADS_SASLWRAP_TYPE_SIGN:
    168193                if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
    169                         features = NTLMSSP_FEATURE_SIGN;
     194                        gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
    170195                } else {
    171196                        /*
    172197                         * windows servers are broken with sign only,
    173                          * so we need to use seal here too
     198                         * so we let the NTLMSSP backend to seal here,
     199                         * via GENSEC_FEATURE_LDAP_STYLE.
    174200                         */
    175                         features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
    176                         ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
     201                        gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN);
     202                        gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE);
    177203                }
    178204                break;
     
    181207        }
    182208
    183         ntlmssp_want_feature(ntlmssp_state, features);
    184 
    185         blob_in = data_blob_null;
    186 
    187         do {
    188                 nt_status = ntlmssp_update(ntlmssp_state,
    189                                            blob_in, &blob_out);
     209        nt_status = auth_generic_client_start_by_sasl(auth_generic_state,
     210                                                      sasl_list);
     211        if (!NT_STATUS_IS_OK(nt_status)) {
     212                return ADS_ERROR_NT(nt_status);
     213        }
     214
     215        rc = LDAP_SASL_BIND_IN_PROGRESS;
     216        nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
     217        if (use_spnego_principal) {
     218                blob_in = data_blob_dup_talloc(talloc_tos(), server_blob);
     219                if (blob_in.length == 0) {
     220                        TALLOC_FREE(auth_generic_state);
     221                        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     222                }
     223        } else {
     224                blob_in = data_blob_null;
     225        }
     226        blob_out = data_blob_null;
     227
     228        while (true) {
     229                struct berval cred, *scred = NULL;
     230
     231                nt_status = gensec_update(auth_generic_state->gensec_security,
     232                                          talloc_tos(), blob_in, &blob_out);
    190233                data_blob_free(&blob_in);
    191                 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
    192                      || NT_STATUS_IS_OK(nt_status))
    193                     && blob_out.length) {
    194                         if (turn == 1) {
    195                                 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
    196                                 /* and wrap it in a SPNEGO wrapper */
    197                                 msg1 = spnego_gen_negTokenInit(talloc_tos(),
    198                                                 OIDs_ntlm, &blob_out, NULL);
    199                         } else {
    200                                 /* wrap it in SPNEGO */
    201                                 msg1 = spnego_gen_auth(talloc_tos(), blob_out);
    202                         }
    203 
    204                         data_blob_free(&blob_out);
    205 
    206                         cred.bv_val = (char *)msg1.data;
    207                         cred.bv_len = msg1.length;
    208                         scred = NULL;
    209                         rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
    210                         data_blob_free(&msg1);
    211                         if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
    212                                 if (scred) {
    213                                         ber_bvfree(scred);
    214                                 }
    215 
    216                                 TALLOC_FREE(ntlmssp_state);
    217                                 return ADS_ERROR(rc);
    218                         }
    219                         if (scred) {
    220                                 blob = data_blob(scred->bv_val, scred->bv_len);
    221                                 ber_bvfree(scred);
    222                         } else {
    223                                 blob = data_blob_null;
    224                         }
    225 
    226                 } else {
    227 
    228                         TALLOC_FREE(ntlmssp_state);
     234                if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)
     235                    && !NT_STATUS_IS_OK(nt_status))
     236                {
     237                        TALLOC_FREE(auth_generic_state);
    229238                        data_blob_free(&blob_out);
    230239                        return ADS_ERROR_NT(nt_status);
    231240                }
    232                
    233                 if ((turn == 1) &&
    234                     (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
    235                         DATA_BLOB tmp_blob = data_blob_null;
    236                         /* the server might give us back two challenges */
    237                         if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in,
    238                                                     &tmp_blob)) {
    239 
    240                                 TALLOC_FREE(ntlmssp_state);
    241                                 data_blob_free(&blob);
    242                                 DEBUG(3,("Failed to parse challenges\n"));
    243                                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     241
     242                if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) {
     243                        break;
     244                }
     245
     246                cred.bv_val = (char *)blob_out.data;
     247                cred.bv_len = blob_out.length;
     248                scred = NULL;
     249                rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred);
     250                data_blob_free(&blob_out);
     251                if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
     252                        if (scred) {
     253                                ber_bvfree(scred);
    244254                        }
    245                         data_blob_free(&tmp_blob);
    246                 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
    247                         if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP,
    248                                                         &blob_in)) {
    249 
    250                                 TALLOC_FREE(ntlmssp_state);
    251                                 data_blob_free(&blob);
    252                                 DEBUG(3,("Failed to parse auth response\n"));
    253                                 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     255
     256                        TALLOC_FREE(auth_generic_state);
     257                        return ADS_ERROR(rc);
     258                }
     259                if (scred) {
     260                        blob_in = data_blob_talloc(talloc_tos(),
     261                                                   scred->bv_val,
     262                                                   scred->bv_len);
     263                        if (blob_in.length != scred->bv_len) {
     264                                ber_bvfree(scred);
     265                                TALLOC_FREE(auth_generic_state);
     266                                return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    254267                        }
    255                 }
    256                 data_blob_free(&blob);
    257                 data_blob_free(&blob_out);
    258                 turn++;
    259         } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
    260        
    261         /* we have a reference conter on ntlmssp_state, if we are signing
    262            then the state will be kept by the signing engine */
     268                        ber_bvfree(scred);
     269                } else {
     270                        blob_in = data_blob_null;
     271                }
     272                if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) {
     273                        break;
     274                }
     275        }
     276
     277        data_blob_free(&blob_in);
     278        data_blob_free(&blob_out);
    263279
    264280        if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SEAL) {
    265281                bool ok;
    266282
    267                 ok = ntlmssp_have_feature(ntlmssp_state,
    268                                           NTLMSSP_FEATURE_SEAL);
     283                ok = gensec_have_feature(auth_generic_state->gensec_security,
     284                                         GENSEC_FEATURE_SEAL);
    269285                if (!ok) {
    270                         DEBUG(0,("The ntlmssp feature sealing request, but unavailable\n"));
    271                         TALLOC_FREE(ntlmssp_state);
     286                        DEBUG(0,("The gensec feature sealing request, but unavailable\n"));
     287                        TALLOC_FREE(auth_generic_state);
    272288                        return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
    273289                }
    274290
    275                 ok = ntlmssp_have_feature(ntlmssp_state,
    276                                           NTLMSSP_FEATURE_SIGN);
     291                ok = gensec_have_feature(auth_generic_state->gensec_security,
     292                                         GENSEC_FEATURE_SIGN);
    277293                if (!ok) {
    278                         DEBUG(0,("The ntlmssp feature signing request, but unavailable\n"));
    279                         TALLOC_FREE(ntlmssp_state);
     294                        DEBUG(0,("The gensec feature signing request, but unavailable\n"));
     295                        TALLOC_FREE(auth_generic_state);
    280296                        return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
    281297                }
     
    284300                bool ok;
    285301
    286                 ok = ntlmssp_have_feature(ntlmssp_state,
    287                                           NTLMSSP_FEATURE_SIGN);
     302                ok = gensec_have_feature(auth_generic_state->gensec_security,
     303                                         GENSEC_FEATURE_SIGN);
    288304                if (!ok) {
    289305                        DEBUG(0,("The gensec feature signing request, but unavailable\n"));
    290                         TALLOC_FREE(ntlmssp_state);
     306                        TALLOC_FREE(auth_generic_state);
    291307                        return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
    292308                }
    293309        }
    294310
     311        ads->auth.tgs_expire = LONG_MAX;
     312        end_nt_time = gensec_expire_time(auth_generic_state->gensec_security);
     313        if (end_nt_time != GENSEC_EXPIRE_TIME_INFINITY) {
     314                struct timeval tv;
     315                nttime_to_timeval(&tv, end_nt_time);
     316                ads->auth.tgs_expire = tv.tv_sec;
     317        }
     318
    295319        if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
    296                 ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
    297                 ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
    298                 ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
     320                size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security);
     321                ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security);
     322
     323                ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped;
     324                /*
     325                 * Note that we have to truncate this to 0x2C
     326                 * (taken from a capture with LDAP unbind), as the
     327                 * signature size is not constant for Kerberos with
     328                 * arcfour-hmac-md5.
     329                 */
     330                ads->ldap.in.min_wrapped = MIN(ads->ldap.out.sig_size, 0x2C);
    299331                ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
    300                 status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
     332                status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security);
    301333                if (!ADS_ERR_OK(status)) {
    302334                        DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
    303335                                ads_errstr(status)));
    304                         TALLOC_FREE(ntlmssp_state);
     336                        TALLOC_FREE(auth_generic_state);
    305337                        return status;
    306338                }
    307         } else {
    308                 TALLOC_FREE(ntlmssp_state);
    309         }
     339                /* Only keep the gensec_security element around long-term */
     340                talloc_steal(NULL, auth_generic_state->gensec_security);
     341        }
     342        TALLOC_FREE(auth_generic_state);
    310343
    311344        return ADS_ERROR(rc);
    312345}
    313346
    314 #ifdef HAVE_GSSAPI
    315 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len)
     347#ifdef HAVE_KRB5
     348static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred)
     349{
     350        ADS_STATUS status;
     351        krb5_context kctx;
     352        krb5_error_code kerr;
     353        krb5_ccache kccache = NULL;
     354        uint32_t maj, min;
     355
     356        *cred = GSS_C_NO_CREDENTIAL;
     357
     358        if (!ads->auth.ccache_name) {
     359                return ADS_SUCCESS;
     360        }
     361
     362        kerr = krb5_init_context(&kctx);
     363        if (kerr) {
     364                return ADS_ERROR_KRB5(kerr);
     365        }
     366
     367#ifdef HAVE_GSS_KRB5_IMPORT_CRED
     368        kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache);
     369        if (kerr) {
     370                status = ADS_ERROR_KRB5(kerr);
     371                goto done;
     372        }
     373
     374        maj = gss_krb5_import_cred(&min, kccache, NULL, NULL, cred);
     375        if (maj != GSS_S_COMPLETE) {
     376                status = ADS_ERROR_GSS(maj, min);
     377                goto done;
     378        }
     379#else
     380        /* We need to fallback to overriding the default creds.
     381         * This operation is not thread safe as it changes the process
     382         * environment variable, but we do not have any better option
     383         * with older kerberos libraries */
     384        {
     385                const char *oldccname = NULL;
     386
     387                oldccname = getenv("KRB5CCNAME");
     388                setenv("KRB5CCNAME", ads->auth.ccache_name, 1);
     389
     390                maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
     391                                       NULL, GSS_C_INITIATE, cred, NULL, NULL);
     392
     393                if (oldccname) {
     394                        setenv("KRB5CCNAME", oldccname, 1);
     395                } else {
     396                        unsetenv("KRB5CCNAME");
     397                }
     398
     399                if (maj != GSS_S_COMPLETE) {
     400                        status = ADS_ERROR_GSS(maj, min);
     401                        goto done;
     402                }
     403        }
     404#endif
     405
     406        status = ADS_SUCCESS;
     407
     408done:
     409        if (!ADS_ERR_OK(status) && kccache != NULL) {
     410                krb5_cc_close(kctx, kccache);
     411        }
     412        krb5_free_context(kctx);
     413        return status;
     414}
     415
     416static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len)
    316417{
    317418        gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
    318419        ADS_STATUS status;
    319420        int gss_rc;
    320         uint32 minor_status;
     421        uint32_t minor_status;
    321422        gss_buffer_desc unwrapped, wrapped;
    322423        int conf_req_flag, conf_state;
     
    359460        ADS_STATUS status;
    360461        int gss_rc;
    361         uint32 minor_status;
     462        uint32_t minor_status;
    362463        gss_buffer_desc unwrapped, wrapped;
    363464        int conf_state;
     
    395496{
    396497        gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data;
    397         uint32 minor_status;
     498        uint32_t minor_status;
    398499
    399500        gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
     
    410511};
    411512
    412 /*
    413    perform a LDAP/SASL/SPNEGO/GSSKRB5 bind
    414 */
    415 static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
    416 {
    417         ADS_STATUS status;
    418         bool ok;
    419         uint32 minor_status;
    420         int gss_rc, rc;
    421         gss_OID_desc krb5_mech_type =
    422         {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
    423         gss_OID mech_type = &krb5_mech_type;
    424         gss_OID actual_mech_type = GSS_C_NULL_OID;
    425         const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL};
    426         gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
    427         gss_buffer_desc input_token, output_token;
    428         uint32 req_flags, ret_flags;
    429         uint32 req_tmp, ret_tmp;
    430         DATA_BLOB unwrapped;
    431         DATA_BLOB wrapped;
    432         struct berval cred, *scred = NULL;
    433 
    434         input_token.value = NULL;
    435         input_token.length = 0;
    436 
    437         req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
    438         switch (ads->ldap.wrap_type) {
    439         case ADS_SASLWRAP_TYPE_SEAL:
    440                 req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG;
    441                 break;
    442         case ADS_SASLWRAP_TYPE_SIGN:
    443                 req_flags |= GSS_C_INTEG_FLAG;
    444                 break;
    445         case ADS_SASLWRAP_TYPE_PLAIN:
    446                 break;
    447         }
    448 
    449         /* Note: here we explicit ask for the krb5 mech_type */
    450         gss_rc = gss_init_sec_context(&minor_status,
    451                                       GSS_C_NO_CREDENTIAL,
    452                                       &context_handle,
    453                                       serv_name,
    454                                       mech_type,
    455                                       req_flags,
    456                                       0,
    457                                       NULL,
    458                                       &input_token,
    459                                       &actual_mech_type,
    460                                       &output_token,
    461                                       &ret_flags,
    462                                       NULL);
    463         if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) {
    464                 status = ADS_ERROR_GSS(gss_rc, minor_status);
    465                 goto failed;
    466         }
    467 
    468         /*
    469          * As some gssapi krb5 mech implementations
    470          * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG
    471          * to req_flags internaly, it's not possible to
    472          * use plain or signing only connection via
    473          * the gssapi interface.
    474          *
    475          * Because of this we need to check it the ret_flags
    476          * has more flags as req_flags and correct the value
    477          * of ads->ldap.wrap_type.
    478          *
    479          * I ads->auth.flags has ADS_AUTH_SASL_FORCE
    480          * we need to give an error.
    481          */
    482         req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
    483         ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
    484 
    485         if (req_tmp == ret_tmp) {
    486                 /* everythings fine... */
    487 
    488         } else if (req_flags & GSS_C_CONF_FLAG) {
    489                 /*
    490                  * here we wanted sealing but didn't got it
    491                  * from the gssapi library
    492                  */
    493                 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
    494                 goto failed;
    495 
    496         } else if ((req_flags & GSS_C_INTEG_FLAG) &&
    497                    !(ret_flags & GSS_C_INTEG_FLAG)) {
    498                 /*
    499                  * here we wanted siging but didn't got it
    500                  * from the gssapi library
    501                  */
    502                 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
    503                 goto failed;
    504 
    505         } else if (ret_flags & GSS_C_CONF_FLAG) {
    506                 /*
    507                  * here we didn't want sealing
    508                  * but the gssapi library forces it
    509                  * so correct the needed wrap_type if
    510                  * the caller didn't forced siging only
    511                  */
    512                 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
    513                         status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
    514                         goto failed;
    515                 }
    516 
    517                 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
    518                 req_flags = ret_flags;
    519 
    520         } else if (ret_flags & GSS_C_INTEG_FLAG) {
    521                 /*
    522                  * here we didn't want signing
    523                  * but the gssapi library forces it
    524                  * so correct the needed wrap_type if
    525                  * the caller didn't forced plain
    526                  */
    527                 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
    528                         status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
    529                         goto failed;
    530                 }
    531 
    532                 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN;
    533                 req_flags = ret_flags;
    534         } else {
    535                 /*
    536                  * This could (should?) not happen
    537                  */
    538                 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
    539                 goto failed;
    540        
    541         }
    542 
    543         /* and wrap that in a shiny SPNEGO wrapper */
    544         unwrapped = data_blob_const(output_token.value, output_token.length);
    545         wrapped = spnego_gen_negTokenInit(talloc_tos(),
    546                         spnego_mechs, &unwrapped, NULL);
    547         gss_release_buffer(&minor_status, &output_token);
    548         if (unwrapped.length > wrapped.length) {
    549                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    550                 goto failed;
    551         }
    552 
    553         cred.bv_val = (char *)wrapped.data;
    554         cred.bv_len = wrapped.length;
    555 
    556         rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL,
    557                               &scred);
    558         data_blob_free(&wrapped);
    559         if (rc != LDAP_SUCCESS) {
    560                 status = ADS_ERROR(rc);
    561                 goto failed;
    562         }
    563 
    564         if (scred) {
    565                 wrapped = data_blob_const(scred->bv_val, scred->bv_len);
    566         } else {
    567                 wrapped = data_blob_null;
    568         }
    569 
    570         ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK,
    571                                         OID_KERBEROS5_OLD,
    572                                         &unwrapped);
    573         if (scred) ber_bvfree(scred);
    574         if (!ok) {
    575                 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
    576                 goto failed;
    577         }
    578 
    579         input_token.value       = unwrapped.data;
    580         input_token.length      = unwrapped.length;
    581 
    582         /*
    583          * As we asked for mutal authentication
    584          * we need to pass the servers response
    585          * to gssapi
    586          */
    587         gss_rc = gss_init_sec_context(&minor_status,
    588                                       GSS_C_NO_CREDENTIAL,
    589                                       &context_handle,
    590                                       serv_name,
    591                                       mech_type,
    592                                       req_flags,
    593                                       0,
    594                                       NULL,
    595                                       &input_token,
    596                                       &actual_mech_type,
    597                                       &output_token,
    598                                       &ret_flags,
    599                                       NULL);
    600         data_blob_free(&unwrapped);
    601         if (gss_rc) {
    602                 status = ADS_ERROR_GSS(gss_rc, minor_status);
    603                 goto failed;
    604         }
    605 
    606         gss_release_buffer(&minor_status, &output_token);
    607 
    608         /*
    609          * If we the sign and seal options
    610          * doesn't match after getting the response
    611          * from the server, we don't want to use the connection
    612          */
    613         req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
    614         ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG);
    615 
    616         if (req_tmp != ret_tmp) {
    617                 /* everythings fine... */
    618                 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE);
    619                 goto failed;
    620         }
    621 
    622         if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
    623                 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
    624 
    625                 gss_rc = gss_wrap_size_limit(&minor_status, context_handle,
    626                                              (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL),
    627                                              GSS_C_QOP_DEFAULT,
    628                                              max_msg_size, &ads->ldap.out.max_unwrapped);
    629                 if (gss_rc) {
    630                         status = ADS_ERROR_GSS(gss_rc, minor_status);
    631                         goto failed;
    632                 }
    633 
    634                 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
    635                 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
    636                 ads->ldap.in.max_wrapped = max_msg_size;
    637                 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
    638                 if (!ADS_ERR_OK(status)) {
    639                         DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
    640                                 ads_errstr(status)));
    641                         goto failed;
    642                 }
    643                 /* make sure we don't free context_handle */
    644                 context_handle = GSS_C_NO_CONTEXT;
    645         }
    646 
    647         status = ADS_SUCCESS;
    648 
    649 failed:
    650         if (context_handle != GSS_C_NO_CONTEXT)
    651                 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
    652         return status;
    653 }
    654 
    655 #endif /* HAVE_GSSAPI */
     513#endif /* HAVE_KRB5 */
    656514
    657515#ifdef HAVE_KRB5
    658516struct ads_service_principal {
    659          char *string;
    660 #ifdef HAVE_GSSAPI
    661          gss_name_t name;
     517        char *service;
     518        char *hostname;
     519        char *string;
     520#ifdef HAVE_KRB5
     521        gss_name_t name;
    662522#endif
    663523};
     
    665525static void ads_free_service_principal(struct ads_service_principal *p)
    666526{
     527        SAFE_FREE(p->service);
     528        SAFE_FREE(p->hostname);
    667529        SAFE_FREE(p->string);
    668530
    669 #ifdef HAVE_GSSAPI
     531#ifdef HAVE_KRB5
    670532        if (p->name) {
    671                 uint32 minor_status;
     533                uint32_t minor_status;
    672534                gss_release_name(&minor_status, &p->name);
    673535        }
     
    676538}
    677539
    678 
    679 static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads,
    680                                               char **returned_principal)
    681 {
     540static ADS_STATUS ads_guess_target(ADS_STRUCT *ads,
     541                                   char **service,
     542                                   char **hostname,
     543                                   char **principal)
     544{
     545        ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY);
    682546        char *princ = NULL;
     547        TALLOC_CTX *frame;
     548        char *server = NULL;
     549        char *realm = NULL;
     550        int rc;
     551
     552        frame = talloc_stackframe();
     553        if (frame == NULL) {
     554                return ADS_ERROR(LDAP_NO_MEMORY);
     555        }
    683556
    684557        if (ads->server.realm && ads->server.ldap_server) {
    685                 char *server, *server_realm;
    686 
    687                 server = SMB_STRDUP(ads->server.ldap_server);
    688                 server_realm = SMB_STRDUP(ads->server.realm);
    689 
    690                 if (!server || !server_realm) {
    691                         SAFE_FREE(server);
    692                         SAFE_FREE(server_realm);
    693                         return ADS_ERROR(LDAP_NO_MEMORY);
    694                 }
    695 
    696                 strlower_m(server);
    697                 strupper_m(server_realm);
    698                 if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
    699                         SAFE_FREE(server);
    700                         SAFE_FREE(server_realm);
    701                         return ADS_ERROR(LDAP_NO_MEMORY);
    702                 }
    703 
    704                 SAFE_FREE(server);
    705                 SAFE_FREE(server_realm);
    706 
    707                 if (!princ) {
    708                         return ADS_ERROR(LDAP_NO_MEMORY);
     558                server = strlower_talloc(frame, ads->server.ldap_server);
     559                if (server == NULL) {
     560                        goto out;
     561                }
     562
     563                realm = strupper_talloc(frame, ads->server.realm);
     564                if (realm == NULL) {
     565                        goto out;
     566                }
     567
     568                /*
     569                 * If we got a name which is bigger than a NetBIOS name,
     570                 * but isn't a FQDN, create one.
     571                 */
     572                if (strlen(server) > 15 && strstr(server, ".") == NULL) {
     573                        char *dnsdomain;
     574
     575                        dnsdomain = strlower_talloc(frame, ads->server.realm);
     576                        if (dnsdomain == NULL) {
     577                                goto out;
     578                        }
     579
     580                        server = talloc_asprintf(frame,
     581                                                 "%s.%s",
     582                                                 server, dnsdomain);
     583                        if (server == NULL) {
     584                                goto out;
     585                        }
    709586                }
    710587        } else if (ads->config.realm && ads->config.ldap_server_name) {
    711                 char *server, *server_realm;
    712 
    713                 server = SMB_STRDUP(ads->config.ldap_server_name);
    714                 server_realm = SMB_STRDUP(ads->config.realm);
    715 
    716                 if (!server || !server_realm) {
    717                         SAFE_FREE(server);
    718                         SAFE_FREE(server_realm);
    719                         return ADS_ERROR(LDAP_NO_MEMORY);
    720                 }
    721 
    722                 strlower_m(server);
    723                 strupper_m(server_realm);
    724                 if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) {
    725                         SAFE_FREE(server);
    726                         SAFE_FREE(server_realm);
    727                         return ADS_ERROR(LDAP_NO_MEMORY);
    728                 }
    729 
    730                 SAFE_FREE(server);
    731                 SAFE_FREE(server_realm);
    732 
    733                 if (!princ) {
    734                         return ADS_ERROR(LDAP_NO_MEMORY);
    735                 }
    736         }
    737 
    738         if (!princ) {
    739                 return ADS_ERROR(LDAP_PARAM_ERROR);
    740         }
    741 
    742         *returned_principal = princ;
    743 
    744         return ADS_SUCCESS;
     588                server = strlower_talloc(frame, ads->config.ldap_server_name);
     589                if (server == NULL) {
     590                        goto out;
     591                }
     592
     593                realm = strupper_talloc(frame, ads->config.realm);
     594                if (realm == NULL) {
     595                        goto out;
     596                }
     597
     598                /*
     599                 * If we got a name which is bigger than a NetBIOS name,
     600                 * but isn't a FQDN, create one.
     601                 */
     602                if (strlen(server) > 15 && strstr(server, ".") == NULL) {
     603                        char *dnsdomain;
     604
     605                        dnsdomain = strlower_talloc(frame, ads->server.realm);
     606                        if (dnsdomain == NULL) {
     607                                goto out;
     608                        }
     609
     610                        server = talloc_asprintf(frame,
     611                                                 "%s.%s",
     612                                                 server, dnsdomain);
     613                        if (server == NULL) {
     614                                goto out;
     615                        }
     616                }
     617        }
     618
     619        if (server == NULL || realm == NULL) {
     620                goto out;
     621        }
     622
     623        *service = SMB_STRDUP("ldap");
     624        if (*service == NULL) {
     625                status = ADS_ERROR(LDAP_PARAM_ERROR);
     626                goto out;
     627        }
     628        *hostname = SMB_STRDUP(server);
     629        if (*hostname == NULL) {
     630                SAFE_FREE(*service);
     631                status = ADS_ERROR(LDAP_PARAM_ERROR);
     632                goto out;
     633        }
     634        rc = asprintf(&princ, "ldap/%s@%s", server, realm);
     635        if (rc == -1 || princ == NULL) {
     636                SAFE_FREE(*service);
     637                SAFE_FREE(*hostname);
     638                status = ADS_ERROR(LDAP_PARAM_ERROR);
     639                goto out;
     640        }
     641
     642        *principal = princ;
     643
     644        status = ADS_SUCCESS;
     645out:
     646        TALLOC_FREE(frame);
     647        return status;
    745648}
    746649
    747650static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads,
    748                                                  const char *given_principal,
    749651                                                 struct ads_service_principal *p)
    750652{
    751653        ADS_STATUS status;
    752 #ifdef HAVE_GSSAPI
     654#ifdef HAVE_KRB5
    753655        gss_buffer_desc input_name;
    754656        /* GSS_KRB5_NT_PRINCIPAL_NAME */
    755657        gss_OID_desc nt_principal =
    756         {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
    757         uint32 minor_status;
     658        {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};
     659        uint32_t minor_status;
    758660        int gss_rc;
    759661#endif
     
    761663        ZERO_STRUCTP(p);
    762664
    763         /* I've seen a child Windows 2000 domain not send
    764            the principal name back in the first round of
    765            the SASL bind reply.  So we guess based on server
    766            name and realm.  --jerry  */
    767         /* Also try best guess when we get the w2k8 ignore principal
    768            back, or when we are configured to ignore it - gd,
    769            abartlet */
    770 
    771         if (!lp_client_use_spnego_principal() ||
    772             !given_principal ||
    773             strequal(given_principal, ADS_IGNORE_PRINCIPAL)) {
    774 
    775                 status = ads_guess_service_principal(ads, &p->string);
    776                 if (!ADS_ERR_OK(status)) {
    777                         return status;
    778                 }
    779         } else {
    780                 p->string = SMB_STRDUP(given_principal);
    781                 if (!p->string) {
    782                         return ADS_ERROR(LDAP_NO_MEMORY);
    783                 }
    784         }
    785 
    786 #ifdef HAVE_GSSAPI
     665        status = ads_guess_target(ads,
     666                                  &p->service,
     667                                  &p->hostname,
     668                                  &p->string);
     669        if (!ADS_ERR_OK(status)) {
     670                return status;
     671        }
     672
     673#ifdef HAVE_KRB5
    787674        input_name.value = p->string;
    788675        input_name.length = strlen(p->string);
     
    798685}
    799686
    800 /*
    801    perform a LDAP/SASL/SPNEGO/KRB5 bind
    802 */
    803 static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)
    804 {
    805         DATA_BLOB blob = data_blob_null;
    806         struct berval cred, *scred = NULL;
    807         DATA_BLOB session_key = data_blob_null;
    808         int rc;
    809 
    810         if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
    811                 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);
    812         }
    813 
    814         rc = spnego_gen_krb5_negTokenInit(talloc_tos(), principal,
    815                                      ads->auth.time_offset, &blob, &session_key, 0,
    816                                      &ads->auth.tgs_expire);
    817 
    818         if (rc) {
    819                 return ADS_ERROR_KRB5(rc);
    820         }
    821 
    822         /* now send the auth packet and we should be done */
    823         cred.bv_val = (char *)blob.data;
    824         cred.bv_len = blob.length;
    825 
    826         rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
    827 
    828         data_blob_free(&blob);
    829         data_blob_free(&session_key);
    830         if(scred)
    831                 ber_bvfree(scred);
    832 
    833         return ADS_ERROR(rc);
    834 }
    835 
    836 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,
    837                                             struct ads_service_principal *p)
    838 {
    839 #ifdef HAVE_GSSAPI
    840         /*
    841          * we only use the gsskrb5 based implementation
    842          * when sasl sign or seal is requested.
    843          *
    844          * This has the following reasons:
    845          * - it's likely that the gssapi krb5 mech implementation
    846          *   doesn't support to negotiate plain connections
    847          * - the ads_sasl_spnego_rawkrb5_bind is more robust
    848          *   against clock skew errors
    849          */
    850         if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
    851                 return ads_sasl_spnego_gsskrb5_bind(ads, p->name);
    852         }
    853 #endif
    854         return ads_sasl_spnego_rawkrb5_bind(ads, p->string);
    855 }
    856687#endif /* HAVE_KRB5 */
    857688
     
    861692static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
    862693{
     694        TALLOC_CTX *frame = talloc_stackframe();
     695        struct ads_service_principal p = {0};
    863696        struct berval *scred=NULL;
    864697        int rc, i;
     
    875708        if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
    876709                status = ADS_ERROR(rc);
    877                 goto failed;
     710                goto done;
    878711        }
    879712
     
    890723        if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
    891724                        OIDs[0] == NULL) {
    892                 data_blob_free(&blob);
    893725                status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
    894                 goto failed;
    895         }
    896         data_blob_free(&blob);
     726                goto done;
     727        }
     728        TALLOC_FREE(given_principal);
    897729
    898730        /* make sure the server understands kerberos */
     
    907739                talloc_free(OIDs[i]);
    908740        }
    909         DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal));
     741
     742        status = ads_generate_service_principal(ads, &p);
     743        if (!ADS_ERR_OK(status)) {
     744                goto done;
     745        }
    910746
    911747#ifdef HAVE_KRB5
     
    913749            got_kerberos_mechanism)
    914750        {
    915                 struct ads_service_principal p;
    916 
    917                 status = ads_generate_service_principal(ads, given_principal, &p);
    918                 TALLOC_FREE(given_principal);
    919                 if (!ADS_ERR_OK(status)) {
    920                         return status;
    921                 }
    922 
    923                 status = ads_sasl_spnego_krb5_bind(ads, &p);
     751                status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
     752                                                     CRED_MUST_USE_KERBEROS,
     753                                                     p.service, p.hostname,
     754                                                     blob);
    924755                if (ADS_ERR_OK(status)) {
    925756                        ads_free_service_principal(&p);
    926                         return status;
    927                 }
    928 
    929                 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, "
     757                        goto done;
     758                }
     759
     760                DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
    930761                          "calling kinit\n", ads_errstr(status)));
    931762
     
    933764
    934765                if (ADS_ERR_OK(status)) {
    935                         status = ads_sasl_spnego_krb5_bind(ads, &p);
     766                        status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
     767                                                        CRED_MUST_USE_KERBEROS,
     768                                                        p.service, p.hostname,
     769                                                        blob);
    936770                        if (!ADS_ERR_OK(status)) {
    937771                                DEBUG(0,("kinit succeeded but "
    938                                         "ads_sasl_spnego_krb5_bind failed: %s\n",
     772                                        "ads_sasl_spnego_gensec_bind(KRB5) failed: %s\n",
    939773                                        ads_errstr(status)));
    940774                        }
    941775                }
    942 
    943                 ads_free_service_principal(&p);
    944776
    945777                /* only fallback to NTLMSSP if allowed */
    946778                if (ADS_ERR_OK(status) ||
    947779                    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
    948                         return status;
    949                 }
    950         } else
     780                        goto done;
     781                }
     782        }
    951783#endif
    952         {
    953                 TALLOC_FREE(given_principal);
    954         }
    955784
    956785        /* lets do NTLMSSP ... this has the big advantage that we don't need
    957786           to sync clocks, and we don't rely on special versions of the krb5
    958787           library for HMAC_MD4 encryption */
    959         return ads_sasl_spnego_ntlmssp_bind(ads);
    960 
    961 failed:
     788        status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
     789                                             CRED_DONT_USE_KERBEROS,
     790                                             p.service, p.hostname,
     791                                             data_blob_null);
     792done:
     793        ads_free_service_principal(&p);
     794        TALLOC_FREE(frame);
    962795        return status;
    963796}
    964797
    965 #ifdef HAVE_GSSAPI
     798#ifdef HAVE_KRB5
    966799#define MAX_GSS_PASSES 3
    967800
     
    974807static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name)
    975808{
    976         uint32 minor_status;
     809        uint32_t minor_status;
     810        gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL;
    977811        gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
    978812        gss_OID mech_type = GSS_C_NULL_OID;
    979813        gss_buffer_desc output_token, input_token;
    980         uint32 req_flags, ret_flags;
     814        uint32_t req_flags, ret_flags;
    981815        int conf_state;
    982816        struct berval cred;
     
    984818        int i=0;
    985819        int gss_rc, rc;
    986         uint8 *p;
    987         uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
    988         uint8 wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
     820        uint8_t *p;
     821        uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;
     822        uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN;
    989823        ADS_STATUS status;
    990824
    991825        input_token.value = NULL;
    992826        input_token.length = 0;
     827
     828        status = ads_init_gssapi_cred(ads, &gss_cred);
     829        if (!ADS_ERR_OK(status)) {
     830                goto failed;
     831        }
    993832
    994833        /*
     
    1001840        for (i=0; i < MAX_GSS_PASSES; i++) {
    1002841                gss_rc = gss_init_sec_context(&minor_status,
    1003                                           GSS_C_NO_CREDENTIAL,
     842                                          gss_cred,
    1004843                                          &context_handle,
    1005844                                          serv_name,
     
    1058897        }
    1059898
    1060         p = (uint8 *)output_token.value;
     899        p = (uint8_t *)output_token.value;
    1061900
    1062901#if 0
     
    1096935                goto failed;
    1097936        }
    1098         p = (uint8 *)output_token.value;
     937        p = (uint8_t *)output_token.value;
    1099938
    1100939        RSIVAL(p,0,max_msg_size);
     
    1148987                ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped;
    1149988                ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */
    1150                 ads->ldap.in.max_wrapped = max_msg_size;
     989                ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
    1151990                status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle);
    1152991                if (!ADS_ERR_OK(status)) {
     
    1160999
    11611000failed:
    1162 
     1001        if (gss_cred != GSS_C_NO_CREDENTIAL)
     1002                gss_release_cred(&minor_status, &gss_cred);
    11631003        if (context_handle != GSS_C_NO_CONTEXT)
    11641004                gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER);
     
    11741014        struct ads_service_principal p;
    11751015
    1176         status = ads_generate_service_principal(ads, NULL, &p);
     1016        status = ads_generate_service_principal(ads, &p);
    11771017        if (!ADS_ERR_OK(status)) {
    11781018                return status;
     
    11991039}
    12001040
    1201 #endif /* HAVE_GSSAPI */
     1041#endif /* HAVE_KRB5 */
    12021042
    12031043/* mapping between SASL mechanisms and functions */
     
    12071047} sasl_mechanisms[] = {
    12081048        {"GSS-SPNEGO", ads_sasl_spnego_bind},
    1209 #ifdef HAVE_GSSAPI
     1049#ifdef HAVE_KRB5
    12101050        {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
    12111051#endif
Note: See TracChangeset for help on using the changeset viewer.