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/libads
Files:
3 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/libads/ads_ldap_protos.h

    r740 r988  
    2525#define _LIBADS_ADS_LDAP_PROTOS_H_
    2626
     27#ifdef HAVE_LDAP_INIT_FD
     28int ldap_init_fd(ber_socket_t fd, int proto, char *uri, LDAP **ldp);
     29#endif
     30
    2731/*
    2832 * Prototypes for ads
    2933 */
    3034
     35LDAP *ldap_open_with_timeout(const char *server,
     36                             struct sockaddr_storage *ss,
     37                             int port, unsigned int to);
    3138void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg);
    3239char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg);
     
    4552                              bool *more_strings);
    4653bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
    47                      uint32 *v);
     54                     uint32_t *v);
    4855bool ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid);
    4956bool ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
     
    5562char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
    5663                        LDAPMessage *msg);
    57 int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
    58                                   TALLOC_CTX *mem_ctx,
    59                                   LDAPMessage *msg,
    60                                   const char *field,
    61                                   enum ads_extended_dn_flags flags,
    62                                   struct dom_sid **sids);
    63 
    6464ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res,
    6565                                 const char *machine);
     
    121121                         struct GROUP_POLICY_OBJECT *gpo);
    122122ADS_STATUS ads_search_retry_dn_sd_flags(ADS_STRUCT *ads, LDAPMessage **res,
    123                                          uint32 sd_flags,
     123                                         uint32_t sd_flags,
    124124                                         const char *dn,
    125125                                         const char **attrs);
    126126ADS_STATUS ads_do_search_all_sd_flags(ADS_STRUCT *ads, const char *bind_path,
    127127                                       int scope, const char *expr,
    128                                        const char **attrs, uint32 sd_flags,
     128                                       const char **attrs, uint32_t sd_flags,
    129129                                       LDAPMessage **res);
    130130ADS_STATUS ads_get_tokensids(ADS_STRUCT *ads,
  • vendor/current/source3/libads/ads_proto.h

    r740 r988  
    5959/* The following definitions come from libads/kerberos_util.c  */
    6060
    61 ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
    62                                     const char *machine_account,
    63                                     const char *password);
    6461int ads_kinit_password(ADS_STRUCT *ads);
    6562
     
    7067ADS_STATUS ads_connect(ADS_STRUCT *ads);
    7168ADS_STATUS ads_connect_user_creds(ADS_STRUCT *ads);
    72 ADS_STATUS ads_connect_gc(ADS_STRUCT *ads);
    7369void ads_disconnect(ADS_STRUCT *ads);
    7470ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path,
     
    8985ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    9086                                const char *name, const char **vals);
    91 uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name);
     87uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name);
    9288uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name);
     89
     90bool ads_element_in_array(const char **el_array, size_t num_el, const char *el);
     91
     92ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
     93                                           ADS_STRUCT *ads,
     94                                           const char *machine_name,
     95                                           char ***spn_array,
     96                                           size_t *num_spns);
    9397ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name);
    9498ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name,
    9599                                          const char *my_fqdn, const char *spn);
    96 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
    97                                    const char *org_unit);
     100ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
     101                                   const char *machine_name,
     102                                   const char *org_unit,
     103                                   uint32_t etype_list);
    98104ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name,
    99105                                 const char *org_unit, bool *moved);
    100106int ads_count_replies(ADS_STRUCT *ads, void *res);
    101 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn);
     107ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32_t *usn);
    102108ADS_STATUS ads_current_time(ADS_STRUCT *ads);
    103 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val);
     109ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val);
    104110ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, struct dom_sid *sid);
    105111ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name);
     
    118124char* ads_get_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name );
    119125ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
    120                         uint32 account_type, const char *org_unit);
     126                        uint32_t account_type, const char *org_unit);
    121127ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname);
    122128ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads,
    123129                               TALLOC_CTX *mem_ctx,
    124130                               const char *samaccountname,
    125                                uint32 *uac_ret,
     131                               uint32_t *uac_ret,
    126132                               const char **dn_ret);
    127133ADS_STATUS ads_config_path(ADS_STRUCT *ads,
  • vendor/current/source3/libads/ads_status.c

    r746 r988  
    2323#include "includes.h"
    2424#include "smb_krb5.h"
     25#include "system/gssapi.h"
    2526#include "smb_ldap.h"
    2627#include "libads/ads_status.h"
     
    116117        case ENUM_ADS_ERROR_KRB5:
    117118                return error_message(status.err.rc);
    118 #endif
    119 #ifdef HAVE_GSSAPI
    120119        case ENUM_ADS_ERROR_GSS:
    121120        {
    122121                char *ret;
    123                 uint32 msg_ctx;
    124                 uint32 minor;
     122                uint32_t msg_ctx;
     123                uint32_t minor;
    125124                gss_buffer_desc msg1, msg2;
    126125
     
    148147}
    149148
    150 #ifdef HAVE_GSSAPI
    151 NTSTATUS gss_err_to_ntstatus(uint32 maj, uint32 min)
     149#ifdef HAVE_KRB5
     150NTSTATUS gss_err_to_ntstatus(uint32_t maj, uint32_t min)
    152151{
    153152        ADS_STATUS adss = ADS_ERROR_GSS(maj, min);
  • vendor/current/source3/libads/ads_status.h

    r740 r988  
    6464NTSTATUS ads_ntstatus(ADS_STATUS status);
    6565const char *ads_errstr(ADS_STATUS status);
    66 NTSTATUS gss_err_to_ntstatus(uint32 maj, uint32 min);
     66NTSTATUS gss_err_to_ntstatus(uint32_t maj, uint32_t min);
    6767
    6868#endif /* _LIBADS_ADS_STATUS_H_ */
  • vendor/current/source3/libads/ads_struct.c

    r746 r988  
    5353        }
    5454
    55         strlcpy(ret,field, len);
     55        if (strlcpy(ret,field, len) >= len) {
     56                /* Truncate ! */
     57                free(r);
     58                free(ret);
     59                return NULL;
     60        }
    5661        p=strtok_r(r, sep, &saveptr);
    5762        if (p) {
    58                 strlcat(ret, p, len);
     63                if (strlcat(ret, p, len) >= len) {
     64                        free(r);
     65                        free(ret);
     66                        return NULL;
     67                }
    5968
    6069                while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) {
     
    102111        }       
    103112
    104         strlower_m( dnsdomain );       
     113        if (!strlower_m( dnsdomain )) {
     114                SAFE_FREE(dnsdomain);
     115                return NULL;
     116        }
     117
    105118        all_string_sub( dnsdomain, "dc=", "", 0);
    106119        all_string_sub( dnsdomain, ",", ".", 0 );
     
    132145        ads->server.ldap_server = ldap_server? SMB_STRDUP(ldap_server) : NULL;
    133146
    134         /* we need to know if this is a foreign realm */
    135         if (realm && *realm && !strequal(lp_realm(), realm)) {
    136                 ads->server.foreign = 1;
    137         }
    138         if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {
    139                 ads->server.foreign = 1;
    140         }
    141 
    142147        /* the caller will own the memory by default */
    143148        ads->is_mine = 1;
     
    150155        ads->auth.flags = wrap_flags;
    151156
    152         /* Start with a page size of 1000 when the connection is new,
     157        /* Start with the configured page size when the connection is new,
    153158         * we will drop it by half we get a timeout.   */
    154         ads->config.ldap_page_size     = 1000;
     159        ads->config.ldap_page_size     = lp_ldap_page_size();
    155160
    156161        return ads;
     
    191196                SAFE_FREE((*ads)->auth.user_name);
    192197                SAFE_FREE((*ads)->auth.kdc_server);
     198                SAFE_FREE((*ads)->auth.ccache_name);
    193199
    194200                SAFE_FREE((*ads)->config.realm);
  • vendor/current/source3/libads/authdata.c

    r740 r988  
    2727#include "smb_krb5.h"
    2828#include "libads/kerberos_proto.h"
     29#include "auth/common_auth.h"
     30#include "lib/param/param.h"
     31#include "librpc/crypto/gse.h"
     32#include "auth/gensec/gensec.h"
     33#include "auth/gensec/gensec_internal.h" /* TODO: remove this */
     34#include "../libcli/auth/spnego.h"
    2935
    3036#ifdef HAVE_KRB5
    3137
     38#include "auth/kerberos/pac_utils.h"
     39
     40struct smb_krb5_context;
     41
    3242/****************************************************************
     43Callback to get the PAC_LOGON_INFO from the blob
    3344****************************************************************/
    34 
    35 static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx,
    36                                           DATA_BLOB pac_data,
    37                                           struct PAC_SIGNATURE_DATA *sig,
    38                                           krb5_context context,
    39                                           krb5_keyblock *keyblock)
     45static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx,
     46                                   TALLOC_CTX *mem_ctx,
     47                                   struct smb_krb5_context *smb_krb5_context,
     48                                   DATA_BLOB *pac_blob,
     49                                   const char *princ_name,
     50                                   const struct tsocket_address *remote_address,
     51                                   uint32_t session_info_flags,
     52                                   struct auth_session_info **session_info)
    4053{
    41         krb5_error_code ret;
    42         krb5_checksum cksum;
    43         krb5_keyusage usage = 0;
    44 
    45         smb_krb5_checksum_from_pac_sig(&cksum, sig);
    46 
    47 #ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */
    48         usage = KRB5_KU_OTHER_CKSUM;
    49 #elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */
    50         usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;
    51 #else
    52 #error UNKNOWN_KRB5_KEYUSAGE
    53 #endif
    54 
    55         ret = smb_krb5_verify_checksum(context,
    56                                        keyblock,
    57                                        usage,
    58                                        &cksum,
    59                                        pac_data.data,
    60                                        pac_data.length);
    61 
    62         if (ret) {
    63                 DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n",
    64                         error_message(ret), ret));
    65                 return ret;
    66         }
    67 
    68         return ret;
     54        TALLOC_CTX *tmp_ctx;
     55        struct PAC_DATA *pac_data = NULL;
     56        struct PAC_DATA_CTR *pac_data_ctr = NULL;
     57        NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
     58
     59        tmp_ctx = talloc_new(mem_ctx);
     60        if (!tmp_ctx) {
     61                return NT_STATUS_NO_MEMORY;
     62        }
     63
     64        if (pac_blob != NULL) {
     65                status = kerberos_decode_pac(tmp_ctx,
     66                                             *pac_blob,
     67                                             NULL,
     68                                             NULL,
     69                                             NULL,
     70                                             NULL,
     71                                             0,
     72                                             &pac_data);
     73                if (!NT_STATUS_IS_OK(status)) {
     74                        goto done;
     75                }
     76
     77                pac_data_ctr = talloc(mem_ctx, struct PAC_DATA_CTR);
     78                if (pac_data_ctr == NULL) {
     79                        status = NT_STATUS_NO_MEMORY;
     80                        goto done;
     81                }
     82
     83                talloc_set_name_const(pac_data_ctr, "struct PAC_DATA_CTR");
     84
     85                pac_data_ctr->pac_data = talloc_steal(pac_data_ctr, pac_data);
     86                pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr,
     87                                                          pac_blob->data,
     88                                                          pac_blob->length);
     89
     90                auth_ctx->private_data = talloc_steal(auth_ctx, pac_data_ctr);
     91        }
     92
     93        *session_info = talloc_zero(mem_ctx, struct auth_session_info);
     94        if (!*session_info) {
     95                status = NT_STATUS_NO_MEMORY;
     96                goto done;
     97        }
     98        status = NT_STATUS_OK;
     99
     100done:
     101        TALLOC_FREE(tmp_ctx);
     102
     103        return status;
    69104}
    70105
    71 /**
    72 * @brief Decode a blob containing a NDR envoded PAC structure
    73 *
    74 * @param mem_ctx          - The memory context
    75 * @param pac_data_blob    - The data blob containing the NDR encoded data
    76 * @param context          - The Kerberos Context
    77 * @param service_keyblock - The Service Key used to verify the checksum
    78 * @param client_principal - The client principal
    79 * @param tgs_authtime     - The ticket timestamp
    80 * @param pac_data_out     - [out] The decoded PAC
    81 *
    82 * @return - A NTSTATUS error code
    83 */
    84 NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx,
    85                          DATA_BLOB *pac_data_blob,
    86                          krb5_context context,
    87                          krb5_keyblock *service_keyblock,
    88                          krb5_const_principal client_principal,
    89                          time_t tgs_authtime,
    90                          struct PAC_DATA **pac_data_out)
    91 {
    92         NTSTATUS status;
    93         enum ndr_err_code ndr_err;
    94         krb5_error_code ret;
    95         DATA_BLOB modified_pac_blob;
    96 
    97         NTTIME tgs_authtime_nttime;
    98         krb5_principal client_principal_pac = NULL;
    99         int i;
    100 
    101         struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
    102         struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
    103         struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
    104         struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
    105         struct PAC_LOGON_NAME *logon_name = NULL;
    106         struct PAC_LOGON_INFO *logon_info = NULL;
    107         struct PAC_DATA *pac_data = NULL;
    108         struct PAC_DATA_RAW *pac_data_raw = NULL;
    109 
    110         DATA_BLOB *srv_sig_blob = NULL;
    111         DATA_BLOB *kdc_sig_blob = NULL;
    112 
    113         bool bool_ret;
    114 
    115         *pac_data_out = NULL;
    116 
    117         pac_data = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA);
    118         pac_data_raw = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA_RAW);
    119         kdc_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA);
    120         srv_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA);
    121         if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
    122                 return NT_STATUS_NO_MEMORY;
    123         }
    124 
    125         ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data, pac_data,
    126                        (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
    127         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    128                 status = ndr_map_error2ntstatus(ndr_err);
    129                 DEBUG(0,("can't parse the PAC: %s\n",
    130                         nt_errstr(status)));
    131                 return status;
    132         }
    133 
    134         if (pac_data->num_buffers < 4) {
    135                 /* we need logon_ingo, service_key and kdc_key */
    136                 DEBUG(0,("less than 4 PAC buffers\n"));
    137                 return NT_STATUS_INVALID_PARAMETER;
    138         }
    139 
    140         ndr_err = ndr_pull_struct_blob(
    141                                 pac_data_blob, pac_data_raw, pac_data_raw,
    142                                 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
    143         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    144                 status = ndr_map_error2ntstatus(ndr_err);
    145                 DEBUG(0,("can't parse the PAC: %s\n",
    146                         nt_errstr(status)));
    147                 return status;
    148         }
    149 
    150         if (pac_data_raw->num_buffers < 4) {
    151                 /* we need logon_ingo, service_key and kdc_key */
    152                 DEBUG(0,("less than 4 PAC buffers\n"));
    153                 return NT_STATUS_INVALID_PARAMETER;
    154         }
    155 
    156         if (pac_data->num_buffers != pac_data_raw->num_buffers) {
    157                 /* we need logon_ingo, service_key and kdc_key */
    158                 DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
    159                           "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
    160                           pac_data_raw->num_buffers));
    161                 return NT_STATUS_INVALID_PARAMETER;
    162         }
    163 
    164         for (i=0; i < pac_data->num_buffers; i++) {
    165                 struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
    166                 struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];
    167 
    168                 if (data_buf->type != raw_buf->type) {
    169                         DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
    170                                   "%d while PAC_DATA_RAW has %d\n", i,
    171                                   data_buf->type, raw_buf->type));
    172                         return NT_STATUS_INVALID_PARAMETER;
    173                 }
    174                 switch (data_buf->type) {
    175                 case PAC_TYPE_LOGON_INFO:
    176                         if (!data_buf->info) {
    177                                 break;
    178                         }
    179                         logon_info = data_buf->info->logon_info.info;
    180                         break;
    181                 case PAC_TYPE_SRV_CHECKSUM:
    182                         if (!data_buf->info) {
    183                                 break;
    184                         }
    185                         srv_sig_ptr = &data_buf->info->srv_cksum;
    186                         srv_sig_blob = &raw_buf->info->remaining;
    187                         break;
    188                 case PAC_TYPE_KDC_CHECKSUM:
    189                         if (!data_buf->info) {
    190                                 break;
    191                         }
    192                         kdc_sig_ptr = &data_buf->info->kdc_cksum;
    193                         kdc_sig_blob = &raw_buf->info->remaining;
    194                         break;
    195                 case PAC_TYPE_LOGON_NAME:
    196                         logon_name = &data_buf->info->logon_name;
    197                         break;
    198                 default:
    199                         break;
    200                 }
    201         }
    202 
    203         if (!logon_info) {
    204                 DEBUG(0,("PAC no logon_info\n"));
    205                 return NT_STATUS_INVALID_PARAMETER;
    206         }
    207 
    208         if (!logon_name) {
    209                 DEBUG(0,("PAC no logon_name\n"));
    210                 return NT_STATUS_INVALID_PARAMETER;
    211         }
    212 
    213         if (!srv_sig_ptr || !srv_sig_blob) {
    214                 DEBUG(0,("PAC no srv_key\n"));
    215                 return NT_STATUS_INVALID_PARAMETER;
    216         }
    217 
    218         if (!kdc_sig_ptr || !kdc_sig_blob) {
    219                 DEBUG(0,("PAC no kdc_key\n"));
    220                 return NT_STATUS_INVALID_PARAMETER;
    221         }
    222 
    223         /* Find and zero out the signatures,
    224          * as required by the signing algorithm */
    225 
    226         /* We find the data blobs above,
    227          * now we parse them to get at the exact portion we should zero */
    228         ndr_err = ndr_pull_struct_blob(
    229                         kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
    230                         (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    231         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    232                 status = ndr_map_error2ntstatus(ndr_err);
    233                 DEBUG(0,("can't parse the KDC signature: %s\n",
    234                         nt_errstr(status)));
    235                 return status;
    236         }
    237 
    238         ndr_err = ndr_pull_struct_blob(
    239                         srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
    240                         (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
    241         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    242                 status = ndr_map_error2ntstatus(ndr_err);
    243                 DEBUG(0,("can't parse the SRV signature: %s\n",
    244                         nt_errstr(status)));
    245                 return status;
    246         }
    247 
    248         /* Now zero the decoded structure */
    249         memset(kdc_sig_wipe->signature.data,
    250                 '\0', kdc_sig_wipe->signature.length);
    251         memset(srv_sig_wipe->signature.data,
    252                 '\0', srv_sig_wipe->signature.length);
    253 
    254         /* and reencode, back into the same place it came from */
    255         ndr_err = ndr_push_struct_blob(
    256                         kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
    257                         (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
    258         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    259                 status = ndr_map_error2ntstatus(ndr_err);
    260                 DEBUG(0,("can't repack the KDC signature: %s\n",
    261                         nt_errstr(status)));
    262                 return status;
    263         }
    264         ndr_err = ndr_push_struct_blob(
    265                         srv_sig_blob, pac_data_raw, srv_sig_wipe,
    266                         (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
    267         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    268                 status = ndr_map_error2ntstatus(ndr_err);
    269                 DEBUG(0,("can't repack the SRV signature: %s\n",
    270                         nt_errstr(status)));
    271                 return status;
    272         }
    273 
    274         /* push out the whole structure, but now with zero'ed signatures */
    275         ndr_err = ndr_push_struct_blob(
    276                         &modified_pac_blob, pac_data_raw, pac_data_raw,
    277                         (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
    278         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    279                 status = ndr_map_error2ntstatus(ndr_err);
    280                 DEBUG(0,("can't repack the RAW PAC: %s\n",
    281                         nt_errstr(status)));
    282                 return status;
    283         }
    284 
    285         /* verify by service_key */
    286         ret = check_pac_checksum(mem_ctx,
    287                                  modified_pac_blob, srv_sig_ptr,
    288                                  context,
    289                                  service_keyblock);
    290         if (ret) {
    291                 DEBUG(1, ("PAC Decode: Failed to verify the service "
    292                           "signature: %s\n", error_message(ret)));
    293                 return NT_STATUS_ACCESS_DENIED;
    294         }
    295 
    296         /* Convert to NT time, so as not to loose accuracy in comparison */
    297         unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
    298 
    299         if (tgs_authtime_nttime != logon_name->logon_time) {
    300                 DEBUG(2, ("PAC Decode: "
    301                           "Logon time mismatch between ticket and PAC!\n"));
    302                 DEBUG(2, ("PAC Decode: PAC: %s\n",
    303                           nt_time_string(mem_ctx, logon_name->logon_time)));
    304                 DEBUG(2, ("PAC Decode: Ticket: %s\n",
    305                           nt_time_string(mem_ctx, tgs_authtime_nttime)));
    306                 return NT_STATUS_ACCESS_DENIED;
    307         }
    308 
    309         ret = smb_krb5_parse_name_norealm(context,
    310                                           logon_name->account_name,
    311                                           &client_principal_pac);
    312         if (ret) {
    313                 DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
    314                           logon_name->account_name, error_message(ret)));
    315                 return NT_STATUS_INVALID_PARAMETER;
    316         }
    317 
    318         bool_ret = smb_krb5_principal_compare_any_realm(context,
    319                                                         client_principal,
    320                                                         client_principal_pac);
    321 
    322         krb5_free_principal(context, client_principal_pac);
    323 
    324         if (!bool_ret) {
    325                 DEBUG(2, ("Name in PAC [%s] does not match principal name "
    326                           "in ticket\n", logon_name->account_name));
    327                 return NT_STATUS_ACCESS_DENIED;
    328         }
    329 
    330         DEBUG(3,("Found account name from PAC: %s [%s]\n",
    331                  logon_info->info3.base.account_name.string,
    332                  logon_info->info3.base.full_name.string));
    333 
    334         DEBUG(10,("Successfully validated Kerberos PAC\n"));
    335 
    336         if (DEBUGLEVEL >= 10) {
    337                 const char *s;
    338                 s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data);
    339                 if (s) {
    340                         DEBUGADD(10,("%s\n", s));
    341                 }
    342         }
    343 
    344         *pac_data_out = pac_data;
    345 
    346         return NT_STATUS_OK;
    347 }
    348 
    349 /****************************************************************
    350 Given a username, password and other details, return the
    351 PAC_LOGON_INFO (the structure containing the important user
    352 information such as groups).
    353 ****************************************************************/
    354 
     106/*
     107 * Given the username/password, do a kinit, store the ticket in
     108 * cache_name if specified, and return the PAC_LOGON_INFO (the
     109 * structure containing the important user information such as
     110 * groups).
     111 */
    355112NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
    356113                             const char *name,
     
    364121                             time_t renewable_time,
    365122                             const char *impersonate_princ_s,
    366                              struct PAC_LOGON_INFO **logon_info)
     123                             const char *local_service,
     124                             struct PAC_DATA_CTR **_pac_data_ctr)
    367125{
    368126        krb5_error_code ret;
    369127        NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
    370         DATA_BLOB tkt, ap_rep, sesskey1, sesskey2;
    371         char *client_princ_out = NULL;
     128        DATA_BLOB tkt, tkt_wrapped, ap_rep, sesskey1;
    372129        const char *auth_princ = NULL;
    373         const char *local_service = NULL;
    374130        const char *cc = "MEMORY:kerberos_return_pac";
     131        struct auth_session_info *session_info;
     132        struct gensec_security *gensec_server_context;
     133        const struct gensec_security_ops **backends;
     134        struct gensec_settings *gensec_settings;
     135        size_t idx = 0;
     136        struct auth4_context *auth_context;
     137        struct loadparm_context *lp_ctx;
     138        struct PAC_DATA_CTR *pac_data_ctr = NULL;
     139
     140        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     141        NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
    375142
    376143        ZERO_STRUCT(tkt);
    377144        ZERO_STRUCT(ap_rep);
    378145        ZERO_STRUCT(sesskey1);
    379         ZERO_STRUCT(sesskey2);
    380146
    381147        if (!name || !pass) {
     
    394160        }
    395161        NT_STATUS_HAVE_NO_MEMORY(auth_princ);
    396 
    397         local_service = talloc_asprintf(mem_ctx, "%s$@%s",
    398                                         global_myname(), lp_realm());
    399         NT_STATUS_HAVE_NO_MEMORY(local_service);
    400162
    401163        ret = kerberos_kinit_password_ext(auth_princ,
     
    455217                goto out;
    456218        }
    457         status = ads_verify_ticket(mem_ctx,
    458                                    lp_realm(),
    459                                    time_offset,
    460                                    &tkt,
    461                                    &client_princ_out,
    462                                    logon_info,
    463                                    &ap_rep,
    464                                    &sesskey2,
    465                                    False);
     219
     220        /* wrap that up in a nice GSS-API wrapping */
     221        tkt_wrapped = spnego_gen_krb5_wrap(tmp_ctx, tkt, TOK_ID_KRB_AP_REQ);
     222        if (tkt_wrapped.data == NULL) {
     223                status = NT_STATUS_NO_MEMORY;
     224                goto out;
     225        }
     226
     227        auth_context = talloc_zero(tmp_ctx, struct auth4_context);
     228        if (auth_context == NULL) {
     229                status = NT_STATUS_NO_MEMORY;
     230                goto out;
     231        }
     232        auth_context->generate_session_info_pac = kerberos_fetch_pac;
     233
     234        lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers());
     235        if (lp_ctx == NULL) {
     236                status = NT_STATUS_INVALID_SERVER_STATE;
     237                DEBUG(10, ("loadparm_init_s3 failed\n"));
     238                goto out;
     239        }
     240
     241        gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
     242        if (gensec_settings == NULL) {
     243                status = NT_STATUS_NO_MEMORY;
     244                DEBUG(10, ("lpcfg_gensec_settings failed\n"));
     245                goto out;
     246        }
     247
     248        backends = talloc_zero_array(gensec_settings,
     249                                     const struct gensec_security_ops *, 2);
     250        if (backends == NULL) {
     251                status = NT_STATUS_NO_MEMORY;
     252                goto out;
     253        }
     254        gensec_settings->backends = backends;
     255
     256        gensec_init();
     257
     258        backends[idx++] = &gensec_gse_krb5_security_ops;
     259
     260        status = gensec_server_start(tmp_ctx, gensec_settings,
     261                                        auth_context, &gensec_server_context);
     262
    466263        if (!NT_STATUS_IS_OK(status)) {
    467                 DEBUG(1,("ads_verify_ticket failed: %s\n",
    468                         nt_errstr(status)));
    469                 goto out;
    470         }
    471 
    472         if (!*logon_info) {
     264                DEBUG(1, (__location__ "Failed to start server-side GENSEC to validate a Kerberos ticket: %s\n", nt_errstr(status)));
     265                goto out;
     266        }
     267
     268        talloc_unlink(tmp_ctx, lp_ctx);
     269        talloc_unlink(tmp_ctx, gensec_settings);
     270        talloc_unlink(tmp_ctx, auth_context);
     271
     272        status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5);
     273        if (!NT_STATUS_IS_OK(status)) {
     274                DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status)));
     275                goto out;
     276        }
     277
     278        /* Do a client-server update dance */
     279        status = gensec_update(gensec_server_context, tmp_ctx, tkt_wrapped, &ap_rep);
     280        if (!NT_STATUS_IS_OK(status)) {
     281                DEBUG(1, ("gensec_update() failed: %s\n", nt_errstr(status)));
     282                goto out;
     283        }
     284
     285        /* Now return the PAC information to the callers.  We ingore
     286         * the session_info and instead pick out the PAC via the
     287         * private_data on the auth_context */
     288        status = gensec_session_info(gensec_server_context, tmp_ctx, &session_info);
     289        if (!NT_STATUS_IS_OK(status)) {
     290                DEBUG(1, ("Unable to obtain PAC via gensec_session_info\n"));
     291                goto out;
     292        }
     293
     294        pac_data_ctr = talloc_get_type_abort(gensec_server_context->auth_context->private_data,
     295                                             struct PAC_DATA_CTR);
     296        if (pac_data_ctr == NULL) {
    473297                DEBUG(1,("no PAC\n"));
    474298                status = NT_STATUS_INVALID_PARAMETER;
     
    476300        }
    477301
     302        *_pac_data_ctr = talloc_move(mem_ctx, &pac_data_ctr);
     303
    478304out:
     305        talloc_free(tmp_ctx);
    479306        if (cc != cache_name) {
    480307                ads_kdestroy(cc);
     
    484311        data_blob_free(&ap_rep);
    485312        data_blob_free(&sesskey1);
    486         data_blob_free(&sesskey2);
    487 
    488         TALLOC_FREE(client_princ_out);
    489313
    490314        return status;
  • vendor/current/source3/libads/cldap.c

    r740 r988  
    2424#include "../libcli/cldap/cldap.h"
    2525#include "../lib/tsocket/tsocket.h"
     26#include "../lib/util/tevent_ntstatus.h"
    2627#include "libads/cldap.h"
     28
     29struct cldap_multi_netlogon_state {
     30        struct tevent_context *ev;
     31        const struct tsocket_address * const *servers;
     32        int num_servers;
     33        const char *domain;
     34        const char *hostname;
     35        unsigned ntversion;
     36        int min_servers;
     37
     38        struct cldap_socket **cldap;
     39        struct tevent_req **subreqs;
     40        int num_sent;
     41        int num_received;
     42        int num_good_received;
     43        struct cldap_netlogon *ios;
     44        struct netlogon_samlogon_response **responses;
     45};
     46
     47static void cldap_multi_netlogon_done(struct tevent_req *subreq);
     48static void cldap_multi_netlogon_next(struct tevent_req *subreq);
     49
     50/*
     51 * Do a parallel cldap ping to the servers. The first "min_servers"
     52 * are fired directly, the remaining ones in 100msec intervals. If
     53 * "min_servers" responses came in successfully, we immediately reply,
     54 * not waiting for the remaining ones.
     55 */
     56
     57struct tevent_req *cldap_multi_netlogon_send(
     58        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     59        const struct tsocket_address * const *servers, int num_servers,
     60        const char *domain, const char *hostname, unsigned ntversion,
     61        int min_servers)
     62{
     63        struct tevent_req *req, *subreq;
     64        struct cldap_multi_netlogon_state *state;
     65        int i;
     66
     67        req = tevent_req_create(mem_ctx, &state,
     68                                struct cldap_multi_netlogon_state);
     69        if (req == NULL) {
     70                return NULL;
     71        }
     72        state->ev = ev;
     73        state->servers = servers;
     74        state->num_servers = num_servers;
     75        state->domain = domain;
     76        state->hostname = hostname;
     77        state->ntversion = ntversion;
     78        state->min_servers = min_servers;
     79
     80        if (min_servers > num_servers) {
     81                tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
     82                return tevent_req_post(req, ev);
     83        }
     84
     85        state->subreqs = talloc_zero_array(state,
     86                                           struct tevent_req *,
     87                                           num_servers);
     88        if (tevent_req_nomem(state->subreqs, req)) {
     89                return tevent_req_post(req, ev);
     90        }
     91
     92        state->cldap = talloc_zero_array(state,
     93                                         struct cldap_socket *,
     94                                         num_servers);
     95        if (tevent_req_nomem(state->cldap, req)) {
     96                return tevent_req_post(req, ev);
     97        }
     98
     99        state->responses = talloc_zero_array(state,
     100                                struct netlogon_samlogon_response *,
     101                                num_servers);
     102        if (tevent_req_nomem(state->responses, req)) {
     103                return tevent_req_post(req, ev);
     104        }
     105
     106        state->ios = talloc_zero_array(state->responses,
     107                                       struct cldap_netlogon,
     108                                       num_servers);
     109        if (tevent_req_nomem(state->ios, req)) {
     110                return tevent_req_post(req, ev);
     111        }
     112
     113        for (i=0; i<num_servers; i++) {
     114                NTSTATUS status;
     115
     116                status = cldap_socket_init(state->cldap,
     117                                           NULL, /* local_addr */
     118                                           state->servers[i],
     119                                           &state->cldap[i]);
     120                if (tevent_req_nterror(req, status)) {
     121                        return tevent_req_post(req, ev);
     122                }
     123
     124                state->ios[i].in.dest_address   = NULL;
     125                state->ios[i].in.dest_port      = 0;
     126                state->ios[i].in.realm          = domain;
     127                state->ios[i].in.host           = NULL;
     128                state->ios[i].in.user           = NULL;
     129                state->ios[i].in.domain_guid    = NULL;
     130                state->ios[i].in.domain_sid     = NULL;
     131                state->ios[i].in.acct_control   = 0;
     132                state->ios[i].in.version        = ntversion;
     133                state->ios[i].in.map_response   = false;
     134        }
     135
     136        for (i=0; i<min_servers; i++) {
     137                state->subreqs[i] = cldap_netlogon_send(state->subreqs,
     138                                                        state->ev,
     139                                                        state->cldap[i],
     140                                                        &state->ios[i]);
     141                if (tevent_req_nomem(state->subreqs[i], req)) {
     142                        return tevent_req_post(req, ev);
     143                }
     144                tevent_req_set_callback(
     145                        state->subreqs[i], cldap_multi_netlogon_done, req);
     146        }
     147        state->num_sent = min_servers;
     148
     149        if (state->num_sent < state->num_servers) {
     150                /*
     151                 * After 100 milliseconds fire the next one
     152                 */
     153                subreq = tevent_wakeup_send(state, state->ev,
     154                                            timeval_current_ofs(0, 100000));
     155                if (tevent_req_nomem(subreq, req)) {
     156                        return tevent_req_post(req, ev);
     157                }
     158                tevent_req_set_callback(subreq, cldap_multi_netlogon_next,
     159                                        req);
     160        }
     161
     162        return req;
     163}
     164
     165static void cldap_multi_netlogon_done(struct tevent_req *subreq)
     166{
     167        struct tevent_req *req = tevent_req_callback_data(
     168                subreq, struct tevent_req);
     169        struct cldap_multi_netlogon_state *state = tevent_req_data(
     170                req, struct cldap_multi_netlogon_state);
     171        NTSTATUS status;
     172        struct netlogon_samlogon_response *response;
     173        int i;
     174
     175        for (i=0; i<state->num_sent; i++) {
     176                if (state->subreqs[i] == subreq) {
     177                        break;
     178                }
     179        }
     180        if (i == state->num_sent) {
     181                /*
     182                 * Got a response we did not fire...
     183                 */
     184                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     185                return;
     186        }
     187        state->subreqs[i] = NULL;
     188
     189        response = talloc_zero(state, struct netlogon_samlogon_response);
     190        if (tevent_req_nomem(response, req)) {
     191                return;
     192        }
     193
     194        status = cldap_netlogon_recv(subreq, response,
     195                                     &state->ios[i]);
     196        TALLOC_FREE(subreq);
     197        state->num_received += 1;
     198
     199        if (NT_STATUS_IS_OK(status)) {
     200                *response = state->ios[i].out.netlogon;
     201                state->responses[i] = talloc_move(state->responses,
     202                                                  &response);
     203                state->num_good_received += 1;
     204        }
     205
     206        if ((state->num_received == state->num_servers) ||
     207            (state->num_good_received >= state->min_servers)) {
     208                tevent_req_done(req);
     209                return;
     210        }
     211}
     212
     213static void cldap_multi_netlogon_next(struct tevent_req *subreq)
     214{
     215        struct tevent_req *req = tevent_req_callback_data(
     216                subreq, struct tevent_req);
     217        struct cldap_multi_netlogon_state *state = tevent_req_data(
     218                req, struct cldap_multi_netlogon_state);
     219        bool ret;
     220
     221        ret = tevent_wakeup_recv(subreq);
     222        TALLOC_FREE(subreq);
     223        if (!ret) {
     224                tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     225                return;
     226        }
     227
     228        subreq = cldap_netlogon_send(state->subreqs,
     229                                     state->ev,
     230                                     state->cldap[state->num_sent],
     231                                     &state->ios[state->num_sent]);
     232        if (tevent_req_nomem(subreq, req)) {
     233                return;
     234        }
     235        tevent_req_set_callback(subreq, cldap_multi_netlogon_done, req);
     236        state->subreqs[state->num_sent] = subreq;
     237        state->num_sent += 1;
     238
     239        if (state->num_sent < state->num_servers) {
     240                /*
     241                 * After 100 milliseconds fire the next one
     242                 */
     243                subreq = tevent_wakeup_send(state, state->ev,
     244                                            timeval_current_ofs(0, 100000));
     245                if (tevent_req_nomem(subreq, req)) {
     246                        return;
     247                }
     248                tevent_req_set_callback(subreq, cldap_multi_netlogon_next,
     249                                        req);
     250        }
     251}
     252
     253NTSTATUS cldap_multi_netlogon_recv(
     254        struct tevent_req *req, TALLOC_CTX *mem_ctx,
     255        struct netlogon_samlogon_response ***responses)
     256{
     257        struct cldap_multi_netlogon_state *state = tevent_req_data(
     258                req, struct cldap_multi_netlogon_state);
     259        NTSTATUS status;
     260
     261        if (tevent_req_is_nterror(req, &status) &&
     262            !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
     263                return status;
     264        }
     265        /*
     266         * If we timeout, give back what we have so far
     267         */
     268        *responses = talloc_move(mem_ctx, &state->responses);
     269        return NT_STATUS_OK;
     270}
     271
     272NTSTATUS cldap_multi_netlogon(
     273        TALLOC_CTX *mem_ctx,
     274        const struct tsocket_address * const *servers,
     275        int num_servers,
     276        const char *domain, const char *hostname, unsigned ntversion,
     277        int min_servers, struct timeval timeout,
     278        struct netlogon_samlogon_response ***responses)
     279{
     280        struct tevent_context *ev;
     281        struct tevent_req *req;
     282        NTSTATUS status = NT_STATUS_NO_MEMORY;
     283
     284        ev = samba_tevent_context_init(talloc_tos());
     285        if (ev == NULL) {
     286                goto fail;
     287        }
     288        req = cldap_multi_netlogon_send(
     289                ev, ev, servers, num_servers, domain, hostname, ntversion,
     290                min_servers);
     291        if (req == NULL) {
     292                goto fail;
     293        }
     294        if (!tevent_req_set_endtime(req, ev, timeout)) {
     295                goto fail;
     296        }
     297        if (!tevent_req_poll_ntstatus(req, ev, &status)) {
     298                goto fail;
     299        }
     300        status = cldap_multi_netlogon_recv(req, mem_ctx, responses);
     301fail:
     302        TALLOC_FREE(ev);
     303        return status;
     304}
    27305
    28306/*******************************************************************
     
    31309
    32310bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
    33                         const char *server,
     311                        struct sockaddr_storage *ss,
    34312                        const char *realm,
    35313                        uint32_t nt_version,
    36314                        struct netlogon_samlogon_response **_reply)
    37315{
    38         struct cldap_socket *cldap;
    39         struct cldap_netlogon io;
    40         struct netlogon_samlogon_response *reply;
    41316        NTSTATUS status;
    42         struct sockaddr_storage ss;
    43317        char addrstr[INET6_ADDRSTRLEN];
    44318        const char *dest_str;
     319        struct tsocket_address *dest_addr;
     320        const struct tsocket_address * const *dest_addrs;
     321        struct netlogon_samlogon_response **responses = NULL;
    45322        int ret;
    46         struct tsocket_address *dest_addr;
    47 
    48         if (!interpret_string_addr_prefer_ipv4(&ss, server, 0)) {
    49                 DEBUG(2,("Failed to resolve[%s] into an address for cldap\n",
    50                         server));
    51                 return false;
    52         }
    53         dest_str = print_sockaddr(addrstr, sizeof(addrstr), &ss);
     323
     324        dest_str = print_sockaddr(addrstr, sizeof(addrstr), ss);
    54325
    55326        ret = tsocket_address_inet_from_strings(mem_ctx, "ip",
     
    63334        }
    64335
    65         /*
    66          * as we use a connected udp socket
    67          */
    68         status = cldap_socket_init(mem_ctx, NULL, NULL, dest_addr, &cldap);
    69         TALLOC_FREE(dest_addr);
     336        dest_addrs = (const struct tsocket_address * const *)&dest_addr;
     337
     338        status = cldap_multi_netlogon(talloc_tos(),
     339                                dest_addrs, 1,
     340                                realm, NULL,
     341                                nt_version, 1,
     342                                timeval_current_ofs(MAX(3,lp_ldap_timeout()/2), 0),
     343                                &responses);
    70344        if (!NT_STATUS_IS_OK(status)) {
    71                 DEBUG(2,("Failed to create cldap socket to %s: %s\n",
    72                          dest_str, nt_errstr(status)));
    73                 return false;
    74         }
    75 
    76         reply = talloc(cldap, struct netlogon_samlogon_response);
    77         if (!reply) {
    78                 goto failed;
    79         }
    80 
    81         /*
    82          * as we use a connected socket, so we don't need to specify the
    83          * destination
    84          */
    85         io.in.dest_address      = NULL;
    86         io.in.dest_port         = 0;
    87         io.in.realm             = realm;
    88         io.in.host              = NULL;
    89         io.in.user              = NULL;
    90         io.in.domain_guid       = NULL;
    91         io.in.domain_sid        = NULL;
    92         io.in.acct_control      = 0;
    93         io.in.version           = nt_version;
    94         io.in.map_response      = false;
    95 
    96         status = cldap_netlogon(cldap, reply, &io);
    97         if (!NT_STATUS_IS_OK(status)) {
    98                 DEBUG(2,("cldap_netlogon() failed: %s\n", nt_errstr(status)));
    99                 goto failed;
    100         }
    101 
    102         *reply = io.out.netlogon;
    103         *_reply = talloc_move(mem_ctx, &reply);
    104         TALLOC_FREE(cldap);
     345                DEBUG(2, ("ads_cldap_netlogon: cldap_multi_netlogon "
     346                          "failed: %s\n", nt_errstr(status)));
     347                return false;
     348        }
     349        if (responses[0] == NULL) {
     350                DEBUG(2, ("ads_cldap_netlogon: did not get a reply\n"));
     351                TALLOC_FREE(responses);
     352                return false;
     353        }
     354        *_reply = talloc_move(mem_ctx, &responses[0]);
     355
    105356        return true;
    106 failed:
    107         TALLOC_FREE(cldap);
    108         return false;
    109357}
    110358
     
    114362
    115363bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
    116                           const char *server,
     364                          struct sockaddr_storage *ss,
    117365                          const char *realm,
    118366                          struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5)
     
    122370        bool ret;
    123371
    124         ret = ads_cldap_netlogon(mem_ctx, server, realm, nt_version, &reply);
     372        ret = ads_cldap_netlogon(mem_ctx, ss, realm, nt_version, &reply);
    125373        if (!ret) {
    126374                return false;
  • vendor/current/source3/libads/cldap.h

    r740 r988  
    2727
    2828/* The following definitions come from libads/cldap.c  */
     29
     30struct tevent_req *cldap_multi_netlogon_send(
     31        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     32        const struct tsocket_address * const *servers,
     33        int num_servers,
     34        const char *domain, const char *hostname, unsigned ntversion,
     35        int min_servers);
     36NTSTATUS cldap_multi_netlogon_recv(
     37        struct tevent_req *req, TALLOC_CTX *mem_ctx,
     38        struct netlogon_samlogon_response ***responses);
     39NTSTATUS cldap_multi_netlogon(
     40        TALLOC_CTX *mem_ctx,
     41        const struct tsocket_address * const *servers,
     42        int num_servers,
     43        const char *domain, const char *hostname, unsigned ntversion,
     44        int min_servers, struct timeval timeout,
     45        struct netlogon_samlogon_response ***responses);
     46
    2947bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx,
    30                         const char *server,
     48                        struct sockaddr_storage *ss,
    3149                        const char *realm,
    3250                        uint32_t nt_version,
    3351                        struct netlogon_samlogon_response **reply);
    3452bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx,
    35                           const char *server,
     53                          struct sockaddr_storage *ss,
    3654                          const char *realm,
    3755                          struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5);
  • vendor/current/source3/libads/disp_sec.c

    r740 r988  
    3030
    3131static struct perm_mask_str {
    32         uint32  mask;
     32        uint32_t  mask;
    3333        const char   *str;
    3434} perms[] = {
     
    6060
    6161/* convert a security permissions into a string */
    62 static void ads_disp_perms(uint32 type)
     62static void ads_disp_perms(uint32_t type)
    6363{
    6464        int i = 0;
  • vendor/current/source3/libads/kerberos.c

    r860 r988  
    2727#include "../librpc/gen_ndr/ndr_misc.h"
    2828#include "libads/kerberos_proto.h"
     29#include "libads/cldap.h"
    2930#include "secrets.h"
     31#include "../lib/tsocket/tsocket.h"
    3032
    3133#ifdef HAVE_KRB5
    32 
    33 #define DEFAULT_KRB5_PORT 88
    3434
    3535#define LIBADS_CCACHE_NAME "MEMORY:libads"
     
    4848{
    4949        if (num_prompts == 0) return 0;
    50 
     50#if HAVE_KRB5_PROMPT_TYPE
     51
     52        /*
     53         * only heimdal has a prompt type and we need to deal with it here to
     54         * avoid loops.
     55         *
     56         * removing the prompter completely is not an option as at least these
     57         * versions would crash: heimdal-1.0.2 and heimdal-1.1. Later heimdal
     58         * version have looping detection and return with a proper error code.
     59         */
     60
     61        if ((num_prompts == 2) &&
     62            (prompts[0].type == KRB5_PROMPT_TYPE_NEW_PASSWORD) &&
     63            (prompts[1].type == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN)) {
     64                /*
     65                 * We don't want to change passwords here. We're
     66                 * called from heimal when the KDC returns
     67                 * KRB5KDC_ERR_KEY_EXPIRED, but at this point we don't
     68                 * have the chance to ask the user for a new
     69                 * password. If we return 0 (i.e. success), we will be
     70                 * spinning in the endless for-loop in
     71                 * change_password() in
     72                 * source4/heimdal/lib/krb5/init_creds_pw.c:526ff
     73                 */
     74                return KRB5KDC_ERR_KEY_EXPIRED;
     75        }
     76#endif /* HAVE_KRB5_PROMPT_TYPE */
    5177        memset(prompts[0].reply->data, '\0', prompts[0].reply->length);
    5278        if (prompts[0].reply->length > 0) {
     
    218244#endif
    219245        if (add_netbios_addr) {
    220                 if ((code = smb_krb5_gen_netbios_krb5_address(&addr))) {
     246                if ((code = smb_krb5_gen_netbios_krb5_address(&addr,
     247                                                        lp_netbios_name()))) {
    221248                        goto out;
    222249                }
     
    224251        }
    225252
    226         if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
    227                                                  kerb_prompter, CONST_DISCARD(char *,password),
     253        if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, discard_const_p(char,password),
     254                                                 kerb_prompter, discard_const_p(char, password),
    228255                                                 0, NULL, opt))) {
    229256                goto out;
     
    353380        fstring salt;
    354381
    355         fstr_sprintf( salt, "host/%s.%s@", global_myname(), lp_realm() );
    356         strlower_m( salt );
     382        fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
     383        (void)strlower_m( salt );
    357384        fstrcat( salt, lp_realm() );
    358385
     
    406433************************************************************************/
    407434
     435static
    408436char* kerberos_secrets_fetch_des_salt( void )
    409437{
     
    412440        if ( (key = des_salt_key()) == NULL ) {
    413441                DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
    414                 return False;
     442                return NULL;
    415443        }
    416444
     
    420448
    421449        return salt;
    422 }
    423 
    424 /************************************************************************
    425  Routine to get the default realm from the kerberos credentials cache.
    426  Caller must free if the return value is not NULL.
    427 ************************************************************************/
    428 
    429 char *kerberos_get_default_realm_from_ccache( void )
    430 {
    431         char *realm = NULL;
    432         krb5_context ctx = NULL;
    433         krb5_ccache cc = NULL;
    434         krb5_principal princ = NULL;
    435 
    436         initialize_krb5_error_table();
    437         if (krb5_init_context(&ctx)) {
    438                 return NULL;
    439         }
    440 
    441         DEBUG(5,("kerberos_get_default_realm_from_ccache: "
    442                 "Trying to read krb5 cache: %s\n",
    443                 krb5_cc_default_name(ctx)));
    444         if (krb5_cc_default(ctx, &cc)) {
    445                 DEBUG(0,("kerberos_get_default_realm_from_ccache: "
    446                         "failed to read default cache\n"));
    447                 goto out;
    448         }
    449         if (krb5_cc_get_principal(ctx, cc, &princ)) {
    450                 DEBUG(0,("kerberos_get_default_realm_from_ccache: "
    451                         "failed to get default principal\n"));
    452                 goto out;
    453         }
    454 
    455 #if defined(HAVE_KRB5_PRINCIPAL_GET_REALM)
    456         realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ));
    457 #elif defined(HAVE_KRB5_PRINC_REALM)
    458         {
    459                 krb5_data *realm_data = krb5_princ_realm(ctx, princ);
    460                 realm = SMB_STRNDUP(realm_data->data, realm_data->length);
    461         }
    462 #endif
    463 
    464   out:
    465 
    466         if (ctx) {
    467                 if (princ) {
    468                         krb5_free_principal(ctx, princ);
    469                 }
    470                 if (cc) {
    471                         krb5_cc_close(ctx, cc);
    472                 }
    473                 krb5_free_context(ctx);
    474         }
    475 
    476         return realm;
    477 }
    478 
    479 /************************************************************************
    480  Routine to get the realm from a given DNS name. Returns malloc'ed memory.
    481  Caller must free() if the return value is not NULL.
    482 ************************************************************************/
    483 
    484 char *kerberos_get_realm_from_hostname(const char *hostname)
    485 {
    486 #if defined(HAVE_KRB5_GET_HOST_REALM) && defined(HAVE_KRB5_FREE_HOST_REALM)
    487 #if defined(HAVE_KRB5_REALM_TYPE)
    488         /* Heimdal. */
    489         krb5_realm *realm_list = NULL;
    490 #else
    491         /* MIT */
    492         char **realm_list = NULL;
    493 #endif
    494         char *realm = NULL;
    495         krb5_error_code kerr;
    496         krb5_context ctx = NULL;
    497 
    498         initialize_krb5_error_table();
    499         if (krb5_init_context(&ctx)) {
    500                 return NULL;
    501         }
    502 
    503         kerr = krb5_get_host_realm(ctx, hostname, &realm_list);
    504         if (kerr != 0) {
    505                 DEBUG(3,("kerberos_get_realm_from_hostname %s: "
    506                         "failed %s\n",
    507                         hostname ? hostname : "(NULL)",
    508                         error_message(kerr) ));
    509                 goto out;
    510         }
    511 
    512         if (realm_list && realm_list[0]) {
    513                 realm = SMB_STRDUP(realm_list[0]);
    514         }
    515 
    516   out:
    517 
    518         if (ctx) {
    519                 if (realm_list) {
    520                         krb5_free_host_realm(ctx, realm_list);
    521                         realm_list = NULL;
    522                 }
    523                 krb5_free_context(ctx);
    524                 ctx = NULL;
    525         }
    526         return realm;
    527 #else
    528         return NULL;
    529 #endif
    530450}
    531451
     
    537457 ************************************************************************/
    538458
     459static
    539460krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
    540461                                                        krb5_principal host_princ,
     
    567488
    568489        return ret_princ;
     490}
     491
     492int create_kerberos_key_from_string(krb5_context context,
     493                                        krb5_principal host_princ,
     494                                        krb5_data *password,
     495                                        krb5_keyblock *key,
     496                                        krb5_enctype enctype,
     497                                        bool no_salt)
     498{
     499        krb5_principal salt_princ = NULL;
     500        int ret;
     501        /*
     502         * Check if we've determined that the KDC is salting keys for this
     503         * principal/enctype in a non-obvious way.  If it is, try to match
     504         * its behavior.
     505         */
     506        if (no_salt) {
     507                KRB5_KEY_DATA(key) = (KRB5_KEY_DATA_CAST *)SMB_MALLOC(password->length);
     508                if (!KRB5_KEY_DATA(key)) {
     509                        return ENOMEM;
     510                }
     511                memcpy(KRB5_KEY_DATA(key), password->data, password->length);
     512                KRB5_KEY_LENGTH(key) = password->length;
     513                KRB5_KEY_TYPE(key) = enctype;
     514                return 0;
     515        }
     516        salt_princ = kerberos_fetch_salt_princ_for_host_princ(context, host_princ, enctype);
     517        ret = smb_krb5_create_key_from_string(context,
     518                                              salt_princ ? salt_princ : host_princ,
     519                                              NULL,
     520                                              password,
     521                                              enctype,
     522                                              key);
     523        if (salt_princ) {
     524                krb5_free_principal(context, salt_princ);
     525        }
     526        return ret;
    569527}
    570528
     
    664622************************************************************************/
    665623
    666 static char *print_kdc_line(char *mem_ctx,
    667                         const char *prev_line,
    668                         const struct sockaddr_storage *pss,
    669                         const char *kdc_name)
    670 {
    671         char *kdc_str = NULL;
    672 
    673         if (pss->ss_family == AF_INET) {
    674                 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
    675                                         prev_line,
    676                                         print_canonical_sockaddr(mem_ctx, pss));
    677         } else {
    678                 char addr[INET6_ADDRSTRLEN];
    679                 uint16_t port = get_sockaddr_port(pss);
    680 
    681                 DEBUG(10,("print_kdc_line: IPv6 case for kdc_name: %s, port: %d\n",
    682                         kdc_name, port));
    683 
    684                 if (port != 0 && port != DEFAULT_KRB5_PORT) {
    685                         /* Currently for IPv6 we can't specify a non-default
    686                            krb5 port with an address, as this requires a ':'.
    687                            Resolve to a name. */
    688                         char hostname[MAX_DNS_NAME_LENGTH];
    689                         int ret = sys_getnameinfo((const struct sockaddr *)pss,
    690                                         sizeof(*pss),
    691                                         hostname, sizeof(hostname),
    692                                         NULL, 0,
    693                                         NI_NAMEREQD);
    694                         if (ret) {
    695                                 DEBUG(0,("print_kdc_line: can't resolve name "
    696                                         "for kdc with non-default port %s. "
    697                                         "Error %s\n.",
    698                                         print_canonical_sockaddr(mem_ctx, pss),
    699                                         gai_strerror(ret)));
    700                                 return NULL;
    701                         }
    702                         /* Success, use host:port */
    703                         kdc_str = talloc_asprintf(mem_ctx,
    704                                         "%s\tkdc = %s:%u\n",
    705                                         prev_line,
    706                                         hostname,
    707                                         (unsigned int)port);
    708                 } else {
    709 
    710                         /* no krb5 lib currently supports "kdc = ipv6 address"
    711                          * at all, so just fill in just the kdc_name if we have
    712                          * it and let the krb5 lib figure out the appropriate
    713                          * ipv6 address - gd */
    714 
    715                         if (kdc_name) {
    716                                 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
    717                                                 prev_line, kdc_name);
    718                         } else {
    719                                 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
    720                                                 prev_line,
    721                                                 print_sockaddr(addr,
    722                                                         sizeof(addr),
    723                                                         pss));
    724                         }
    725                 }
    726         }
    727         return kdc_str;
    728 }
    729 
    730624/************************************************************************
    731625 Create a string list of available kdc's, possibly searching by sitename.
     
    736630************************************************************************/
    737631
     632static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs,
     633                                const struct sockaddr_storage *addr)
     634{
     635        int i;
     636
     637        for (i=0; i<*num_addrs; i++) {
     638                if (sockaddr_equal((const struct sockaddr *)&addrs[i],
     639                                   (const struct sockaddr *)addr)) {
     640                        return;
     641                }
     642        }
     643        addrs[i] = *addr;
     644        *num_addrs += 1;
     645}
     646
     647/* print_canonical_sockaddr prints an ipv6 addr in the form of
     648* [ipv6.addr]. This string, when put in a generated krb5.conf file is not
     649* always properly dealt with by some older krb5 libraries. Adding the hard-coded
     650* portnumber workarounds the issue. - gd */
     651
     652static char *print_canonical_sockaddr_with_port(TALLOC_CTX *mem_ctx,
     653                                                const struct sockaddr_storage *pss)
     654{
     655        char *str = NULL;
     656
     657        str = print_canonical_sockaddr(mem_ctx, pss);
     658        if (str == NULL) {
     659                return NULL;
     660        }
     661
     662        if (pss->ss_family != AF_INET6) {
     663                return str;
     664        }
     665
     666#if defined(HAVE_IPV6)
     667        str = talloc_asprintf_append(str, ":88");
     668#endif
     669        return str;
     670}
     671
    738672static char *get_kdc_ip_string(char *mem_ctx,
    739673                const char *realm,
    740674                const char *sitename,
    741                 struct sockaddr_storage *pss,
    742                 const char *kdc_name)
    743 {
     675                const struct sockaddr_storage *pss)
     676{
     677        TALLOC_CTX *frame = talloc_stackframe();
    744678        int i;
    745679        struct ip_service *ip_srv_site = NULL;
     
    747681        int count_site = 0;
    748682        int count_nonsite;
    749         char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name);
     683        int num_dcs;
     684        struct sockaddr_storage *dc_addrs;
     685        struct tsocket_address **dc_addrs2 = NULL;
     686        const struct tsocket_address * const *dc_addrs3 = NULL;
     687        char *result = NULL;
     688        struct netlogon_samlogon_response **responses = NULL;
     689        NTSTATUS status;
     690        char *kdc_str = talloc_asprintf(mem_ctx, "%s\t\tkdc = %s\n", "",
     691                                        print_canonical_sockaddr_with_port(mem_ctx, pss));
    750692
    751693        if (kdc_str == NULL) {
     694                TALLOC_FREE(frame);
    752695                return NULL;
    753696        }
     
    759702
    760703        if (sitename) {
    761 
    762704                get_kdc_list(realm, sitename, &ip_srv_site, &count_site);
    763 
    764                 for (i = 0; i < count_site; i++) {
    765                         if (sockaddr_equal((struct sockaddr *)&ip_srv_site[i].ss,
    766                                                    (struct sockaddr *)pss)) {
    767                                 continue;
    768                         }
    769                         /* Append to the string - inefficient
    770                          * but not done often. */
    771                         kdc_str = print_kdc_line(mem_ctx,
    772                                                 kdc_str,
    773                                                 &ip_srv_site[i].ss,
    774                                                 NULL);
    775                         if (!kdc_str) {
    776                                 SAFE_FREE(ip_srv_site);
    777                                 return NULL;
    778                         }
    779                 }
     705                DEBUG(10, ("got %d addresses from site %s search\n", count_site,
     706                           sitename));
    780707        }
    781708
     
    783710
    784711        get_kdc_list(realm, NULL, &ip_srv_nonsite, &count_nonsite);
     712        DEBUG(10, ("got %d addresses from site-less search\n", count_nonsite));
     713
     714        dc_addrs = talloc_array(talloc_tos(), struct sockaddr_storage,
     715                                count_site + count_nonsite);
     716        if (dc_addrs == NULL) {
     717                goto out;
     718        }
     719
     720        num_dcs = 0;
     721
     722        for (i = 0; i < count_site; i++) {
     723                if (!sockaddr_equal(
     724                        (const struct sockaddr *)pss,
     725                        (const struct sockaddr *)&ip_srv_site[i].ss)) {
     726                        add_sockaddr_unique(dc_addrs, &num_dcs,
     727                                            &ip_srv_site[i].ss);
     728                }
     729        }
    785730
    786731        for (i = 0; i < count_nonsite; i++) {
    787                 int j;
    788 
    789                 if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss, (struct sockaddr *)pss)) {
     732                if (!sockaddr_equal(
     733                        (const struct sockaddr *)pss,
     734                        (const struct sockaddr *)&ip_srv_nonsite[i].ss)) {
     735                        add_sockaddr_unique(dc_addrs, &num_dcs,
     736                                            &ip_srv_nonsite[i].ss);
     737                }
     738        }
     739
     740        dc_addrs2 = talloc_zero_array(talloc_tos(),
     741                                      struct tsocket_address *,
     742                                      num_dcs);
     743
     744        DEBUG(10, ("%d additional KDCs to test\n", num_dcs));
     745        if (num_dcs == 0) {
     746                goto out;
     747        }
     748        if (dc_addrs2 == NULL) {
     749                goto out;
     750        }
     751
     752        for (i=0; i<num_dcs; i++) {
     753                char addr[INET6_ADDRSTRLEN];
     754                int ret;
     755
     756                print_sockaddr(addr, sizeof(addr), &dc_addrs[i]);
     757
     758                ret = tsocket_address_inet_from_strings(dc_addrs2, "ip",
     759                                                        addr, LDAP_PORT,
     760                                                        &dc_addrs2[i]);
     761                if (ret != 0) {
     762                        status = map_nt_error_from_unix(errno);
     763                        DEBUG(2,("Failed to create tsocket_address for %s - %s\n",
     764                                 addr, nt_errstr(status)));
     765                        goto out;
     766                }
     767        }
     768
     769        dc_addrs3 = (const struct tsocket_address * const *)dc_addrs2;
     770
     771        status = cldap_multi_netlogon(talloc_tos(),
     772                        dc_addrs3, num_dcs,
     773                        realm, lp_netbios_name(),
     774                        NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX,
     775                        MIN(num_dcs, 3), timeval_current_ofs(3, 0), &responses);
     776        TALLOC_FREE(dc_addrs2);
     777        dc_addrs3 = NULL;
     778
     779        if (!NT_STATUS_IS_OK(status)) {
     780                DEBUG(10,("get_kdc_ip_string: cldap_multi_netlogon failed: "
     781                          "%s\n", nt_errstr(status)));
     782                goto out;
     783        }
     784
     785        for (i=0; i<num_dcs; i++) {
     786                char *new_kdc_str;
     787
     788                if (responses[i] == NULL) {
    790789                        continue;
    791790                }
    792791
    793                 /* Ensure this isn't an IP already seen (YUK! this is n*n....) */
    794                 for (j = 0; j < count_site; j++) {
    795                         if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss,
    796                                                 (struct sockaddr *)&ip_srv_site[j].ss)) {
    797                                 break;
    798                         }
    799                         /* As the lists are sorted we can break early if nonsite > site. */
    800                         if (ip_service_compare(&ip_srv_nonsite[i], &ip_srv_site[j]) > 0) {
    801                                 break;
    802                         }
    803                 }
    804                 if (j != i) {
    805                         continue;
    806                 }
    807 
    808792                /* Append to the string - inefficient but not done often. */
    809                 kdc_str = print_kdc_line(mem_ctx,
    810                                 kdc_str,
    811                                 &ip_srv_nonsite[i].ss,
    812                                 NULL);
    813                 if (!kdc_str) {
    814                         SAFE_FREE(ip_srv_site);
    815                         SAFE_FREE(ip_srv_nonsite);
    816                         return NULL;
    817                 }
    818         }
    819 
    820 
     793                new_kdc_str = talloc_asprintf(mem_ctx, "%s\t\tkdc = %s\n",
     794                                              kdc_str,
     795                                              print_canonical_sockaddr_with_port(mem_ctx, &dc_addrs[i]));
     796                if (new_kdc_str == NULL) {
     797                        goto out;
     798                }
     799                TALLOC_FREE(kdc_str);
     800                kdc_str = new_kdc_str;
     801        }
     802
     803out:
     804        DEBUG(10, ("get_kdc_ip_string: Returning %s\n", kdc_str));
     805
     806        result = kdc_str;
    821807        SAFE_FREE(ip_srv_site);
    822808        SAFE_FREE(ip_srv_nonsite);
    823 
    824         DEBUG(10,("get_kdc_ip_string: Returning %s\n",
    825                 kdc_str ));
    826 
    827         return kdc_str;
     809        TALLOC_FREE(frame);
     810        return result;
    828811}
    829812
     
    838821                                                const char *domain,
    839822                                                const char *sitename,
    840                                                 struct sockaddr_storage *pss,
    841                                                 const char *kdc_name)
     823                                                const struct sockaddr_storage *pss)
    842824{
    843825        char *dname;
     
    852834        bool result = false;
    853835        char *aes_enctypes = NULL;
     836        mode_t mask;
    854837
    855838        if (!lp_create_krb5_conf()) {
     
    863846        }
    864847
    865         if (domain == NULL || pss == NULL || kdc_name == NULL) {
     848        if (domain == NULL || pss == NULL) {
    866849                return false;
    867850        }
     
    892875
    893876        realm_upper = talloc_strdup(fname, realm);
    894         strupper_m(realm_upper);
    895 
    896         kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss, kdc_name);
     877        if (!strupper_m(realm_upper)) {
     878                goto done;
     879        }
     880
     881        kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss);
    897882        if (!kdc_ip_string) {
    898883                goto done;
     
    921906                                        "\tdefault_tgs_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
    922907                                        "\tdefault_tkt_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
    923                                         "\tpreferred_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
     908                                        "\tpreferred_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
     909                                        "\tdns_lookup_realm = false\n\n"
    924910                                        "[realms]\n\t%s = {\n"
    925                                         "\t%s\t}\n",
     911                                        "%s\t}\n",
    926912                                        realm_upper, aes_enctypes, aes_enctypes, aes_enctypes,
    927913                                        realm_upper, kdc_ip_string);
     
    933919        flen = strlen(file_contents);
    934920
     921        mask = umask(S_IRWXO | S_IRWXG);
    935922        fd = mkstemp(tmpname);
     923        umask(mask);
    936924        if (fd == -1) {
    937925                DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed,"
     
    989977
    990978        if (strequal(realm, lp_realm())) {
    991                 char linkpath[PATH_MAX+1];
    992                 int lret;
    993 
    994                 lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath, sizeof(linkpath)-1);
    995                 if (lret != -1) {
    996                         linkpath[lret] = '\0';
    997                 }
    998 
    999                 if (lret != -1 || strcmp(linkpath, fname) == 0) {
    1000                         /* Symlink already exists. */
    1001                         goto done;
     979                SMB_STRUCT_STAT sbuf;
     980
     981                if (sys_lstat(SYSTEM_KRB5_CONF_PATH, &sbuf, false) == 0) {
     982                        if (S_ISLNK(sbuf.st_ex_mode) && sbuf.st_ex_size) {
     983                                int lret;
     984                                size_t alloc_size = sbuf.st_ex_size + 1;
     985                                char *linkpath = talloc_array(talloc_tos(), char,
     986                                                alloc_size);
     987                                if (!linkpath) {
     988                                        goto done;
     989                                }
     990                                lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath,
     991                                                alloc_size - 1);
     992                                if (lret == -1) {
     993                                        TALLOC_FREE(linkpath);
     994                                        goto done;
     995                                }
     996                                linkpath[lret] = '\0';
     997
     998                                if (strcmp(linkpath, fname) == 0) {
     999                                        /* Symlink already exists. */
     1000                                        TALLOC_FREE(linkpath);
     1001                                        goto done;
     1002                                }
     1003                                TALLOC_FREE(linkpath);
     1004                        }
    10021005                }
    10031006
    10041007                /* Try and replace with a symlink. */
    10051008                if (symlink(fname, SYSTEM_KRB5_CONF_PATH) == -1) {
    1006                         const char *newpath = SYSTEM_KRB5_CONF_PATH ## ".saved";
     1009                        const char *newpath = SYSTEM_KRB5_CONF_PATH ".saved";
    10071010                        if (errno != EEXIST) {
    10081011                                DEBUG(0,("create_local_private_krb5_conf_for_domain: symlink "
  • vendor/current/source3/libads/kerberos_keytab.c

    r860 r988  
    5050        krb5_keytab_entry zero_kt_entry;
    5151        char *ktprinc = NULL;
     52        krb5_kvno old_kvno = kvno - 1;
    5253
    5354        ZERO_STRUCT(cursor);
     
    116117                 * the client reboots or the client's session key expires and
    117118                 * they get a new session ticket with the new kvno.
     119                 * Some keytab files only store the kvno in 8bits, limit
     120                 * the compare accordingly.
    118121                 */
    119122
    120                 if (!flush && (kt_entry.vno == kvno - 1)) {
     123                if (!flush && ((kt_entry.vno & 0xff) == (old_kvno & 0xff))) {
    121124                        DEBUG(5, (__location__ ": Saving previous (kvno %d) "
    122125                                  "entry for principal: %s.\n",
    123                                   kvno - 1, princ_s));
     126                                  old_kvno, princ_s));
    124127                        continue;
    125128                }
     
    250253        return (int)ret;
    251254}
     255
     256#ifdef HAVE_ADS
    252257
    253258/**********************************************************************
     
    321326        }
    322327
    323         my_fqdn = ads_get_dnshostname(ads, tmpctx, global_myname());
     328        my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name());
    324329        if (!my_fqdn) {
    325330                DEBUG(0, (__location__ ": unable to determine machine "
     
    329334        }
    330335
    331         machine_name = ads_get_samaccountname(ads, tmpctx, global_myname());
     336        machine_name = ads_get_samaccountname(ads, tmpctx, lp_netbios_name());
    332337        if (!machine_name) {
    333338                DEBUG(0, (__location__ ": unable to determine machine "
     
    369374                                                srvPrinc, machine_name,
    370375                                                lp_realm());
    371                 if (!princ_s) {
     376                if (short_princ_s == NULL) {
    372377                        ret = -1;
    373378                        goto out;
     
    385390
    386391                        aderr = ads_add_service_principal_name(ads,
    387                                         global_myname(), my_fqdn, srvPrinc);
     392                                        lp_netbios_name(), my_fqdn, srvPrinc);
    388393                        if (!ADS_ERR_OK(aderr)) {
    389394                                DEBUG(1, (__location__ ": failed to "
     
    394399        }
    395400
    396         kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());
     401        kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
    397402        if (kvno == -1) {
    398403                /* -1 indicates failure, everything else is OK */
     
    463468        }
    464469
    465         kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());
     470        kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
    466471        if (kvno == -1) {
    467472                /* -1 indicates a failure */
     
    477482        }
    478483
    479         aderr = ads_clear_service_principal_names(ads, global_myname());
     484        aderr = ads_clear_service_principal_names(ads, lp_netbios_name());
    480485        if (!ADS_ERR_OK(aderr)) {
    481486                DEBUG(1, (__location__ ": Error while clearing service "
     
    503508        krb5_context context = NULL;
    504509        krb5_keytab keytab = NULL;
    505         krb5_kt_cursor cursor;
    506         krb5_keytab_entry kt_entry;
     510        krb5_kt_cursor cursor = {0};
     511        krb5_keytab_entry kt_entry = {0};
    507512        krb5_kvno kvno;
    508         int i, found = 0;
     513        size_t found = 0;
    509514        char *sam_account_name, *upn;
    510515        char **oldEntries = NULL, *princ_s[26];
    511         TALLOC_CTX *tmpctx = NULL;
     516        TALLOC_CTX *frame;
    512517        char *machine_name;
    513 
    514         /* these are the main ones we need */
    515         ret = ads_keytab_add_entry(ads, "host");
    516         if (ret != 0) {
    517                 DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
    518                           "adding 'host' principal.\n"));
    519                 return ret;
    520         }
    521 
     518        char **spn_array;
     519        size_t num_spns;
     520        size_t i;
     521        ADS_STATUS status;
     522
     523        ZERO_STRUCT(kt_entry);
     524        ZERO_STRUCT(cursor);
     525
     526        frame = talloc_stackframe();
     527        if (frame == NULL) {
     528                ret = -1;
     529                goto done;
     530        }
     531
     532        status = ads_get_service_principal_names(frame,
     533                                                 ads,
     534                                                 lp_netbios_name(),
     535                                                 &spn_array,
     536                                                 &num_spns);
     537        if (!ADS_ERR_OK(status)) {
     538                ret = -1;
     539                goto done;
     540        }
     541
     542        for (i = 0; i < num_spns; i++) {
     543                char *srv_princ;
     544                char *p;
     545
     546                srv_princ = strlower_talloc(frame, spn_array[i]);
     547                if (srv_princ == NULL) {
     548                        ret = -1;
     549                        goto done;
     550                }
     551
     552                p = strchr_m(srv_princ, '/');
     553                if (p == NULL) {
     554                        continue;
     555                }
     556                p[0] = '\0';
     557
     558                /* Add the SPNs found on the DC */
     559                ret = ads_keytab_add_entry(ads, srv_princ);
     560                if (ret != 0) {
     561                        DEBUG(1, ("ads_keytab_add_entry failed while "
     562                                  "adding '%s' principal.\n",
     563                                  spn_array[i]));
     564                        goto done;
     565                }
     566        }
    522567
    523568#if 0   /* don't create the CIFS/... keytab entries since no one except smbd
     
    534579
    535580        memset(princ_s, '\0', sizeof(princ_s));
    536         ZERO_STRUCT(kt_entry);
    537         ZERO_STRUCT(cursor);
    538581
    539582        initialize_krb5_error_table();
     
    542585                DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
    543586                          error_message(ret)));
    544                 return ret;
    545         }
    546 
    547         tmpctx = talloc_init(__location__);
    548         if (!tmpctx) {
    549                 DEBUG(0, (__location__ ": talloc_init() failed!\n"));
    550                 ret = -1;
    551                 goto done;
    552         }
    553 
    554         machine_name = talloc_strdup(tmpctx, global_myname());
     587                goto done;
     588        }
     589
     590        machine_name = talloc_strdup(frame, lp_netbios_name());
    555591        if (!machine_name) {
    556592                ret = -1;
     
    559595
    560596        /* now add the userPrincipalName and sAMAccountName entries */
    561         sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);
     597        sam_account_name = ads_get_samaccountname(ads, frame, machine_name);
    562598        if (!sam_account_name) {
    563599                DEBUG(0, (__location__ ": unable to determine machine "
     
    569605        /* upper case the sAMAccountName to make it easier for apps to
    570606           know what case to use in the keytab file */
    571         strupper_m(sam_account_name);
     607        if (!strupper_m(sam_account_name)) {
     608                ret = -1;
     609                goto done;
     610        }
    572611
    573612        ret = ads_keytab_add_entry(ads, sam_account_name);
     
    580619
    581620        /* remember that not every machine account will have a upn */
    582         upn = ads_get_upn(ads, tmpctx, machine_name);
     621        upn = ads_get_upn(ads, frame, machine_name);
    583622        if (upn) {
    584623                ret = ads_keytab_add_entry(ads, upn);
     
    592631        /* Now loop through the keytab and update any other existing entries */
    593632        kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name);
    594         if (kvno == -1) {
     633        if (kvno == (krb5_kvno)-1) {
    595634                DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to "
    596635                          "determine the system's kvno.\n"));
     
    625664         * we've counted them. Re-open asap to minimise the race. JRA.
    626665         */
    627         DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found));
     666        DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found));
    628667        if (!found) {
    629668                goto done;
    630669        }
    631670
    632         oldEntries = talloc_array(tmpctx, char *, found);
     671        oldEntries = talloc_zero_array(frame, char *, found + 1);
    633672        if (!oldEntries) {
    634673                DEBUG(1, (__location__ ": Failed to allocate space to store "
     
    637676                goto done;
    638677        }
    639         memset(oldEntries, '\0', found * sizeof(char *));
    640678
    641679        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
     
    694732                ZERO_STRUCT(kt_entry);
    695733        }
     734        krb5_kt_end_seq_get(context, keytab, &cursor);
     735        ZERO_STRUCT(cursor);
     736
    696737        ret = 0;
    697738        for (i = 0; oldEntries[i]; i++) {
     
    699740                TALLOC_FREE(oldEntries[i]);
    700741        }
    701         krb5_kt_end_seq_get(context, keytab, &cursor);
    702         ZERO_STRUCT(cursor);
    703742
    704743done:
    705744        TALLOC_FREE(oldEntries);
    706         TALLOC_FREE(tmpctx);
     745        TALLOC_FREE(frame);
    707746
    708747        {
     
    730769        return ret;
    731770}
     771
     772#endif /* HAVE_ADS */
    732773
    733774/**********************************************************************
     
    767808        }
    768809
    769         printf("Vno  Type        Principal\n");
     810        printf("Vno  Type                                        Principal\n");
    770811
    771812        while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
     
    790831                }
    791832
    792                 printf("%3d  %s\t\t %s\n", kt_entry.vno, etype_s, princ_s);
     833                printf("%3d  %-43s %s\n", kt_entry.vno, etype_s, princ_s);
    793834
    794835                TALLOC_FREE(princ_s);
  • vendor/current/source3/libads/kerberos_proto.h

    r740 r988  
    3131#define _LIBADS_KERBEROS_PROTO_H_
    3232
    33 struct PAC_LOGON_INFO;
     33#include "system/kerberos.h"
     34
     35struct PAC_DATA;
     36
     37struct PAC_DATA_CTR {
     38        DATA_BLOB pac_blob;
     39        struct PAC_DATA *pac_data;
     40};
     41
     42#define DEFAULT_KRB5_PORT 88
    3443
    3544#include "libads/ads_status.h"
    36 
    37 /* The following definitions come from libads/kerberos_verify.c  */
    38 
    39 NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
    40                            const char *realm,
    41                            time_t time_offset,
    42                            const DATA_BLOB *ticket,
    43                            char **principal,
    44                            struct PAC_LOGON_INFO **logon_info,
    45                            DATA_BLOB *ap_rep,
    46                            DATA_BLOB *session_key,
    47                            bool use_replay_cache);
    4845
    4946/* The following definitions come from libads/kerberos.c  */
     
    6259char* kerberos_standard_des_salt( void );
    6360bool kerberos_secrets_store_des_salt( const char* salt );
    64 char* kerberos_secrets_fetch_des_salt( void );
    65 char *kerberos_get_default_realm_from_ccache( void );
    66 char *kerberos_get_realm_from_hostname(const char *hostname);
    6761
    6862bool kerberos_secrets_store_salting_principal(const char *service,
     
    7670                                                const char *domain,
    7771                                                const char *sitename,
    78                                                 struct sockaddr_storage *pss,
    79                                                 const char *kdc_name);
     72                                                const struct sockaddr_storage *pss);
    8073
    8174/* The following definitions come from libads/authdata.c  */
     
    9285                             time_t renewable_time,
    9386                             const char *impersonate_princ_s,
    94                              struct PAC_LOGON_INFO **logon_info);
     87                             const char *local_service,
     88                             struct PAC_DATA_CTR **pac_data_ctr);
    9589
    9690/* The following definitions come from libads/krb5_setpw.c  */
     
    10397                                 int time_offset);
    10498
     99#ifdef HAVE_KRB5
     100int create_kerberos_key_from_string(krb5_context context,
     101                                        krb5_principal host_princ,
     102                                        krb5_data *password,
     103                                        krb5_keyblock *key,
     104                                        krb5_enctype enctype,
     105                                        bool no_salt);
     106#endif
     107
    105108#endif /* _LIBADS_KERBEROS_PROTO_H_ */
  • vendor/current/source3/libads/kerberos_util.c

    r740 r988  
    2222#include "smb_krb5.h"
    2323#include "ads.h"
     24#include "lib/param/loadparm.h"
    2425
    2526#ifdef HAVE_KRB5
    26 
    27 /**
    28  * Set the machine account password
    29  * @param ads connection to ads server
    30  * @param hostname machine whose password is being set
    31  * @param password new password
    32  * @return status of password change
    33  **/
    34 ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
    35                                     const char *machine_account,
    36                                     const char *password)
    37 {
    38         ADS_STATUS status;
    39         char *principal = NULL;
    40 
    41         /*
    42           we need to use the '$' form of the name here (the machine account name),
    43           as otherwise the server might end up setting the password for a user
    44           instead
    45          */
    46         if (asprintf(&principal, "%s@%s", machine_account, ads->config.realm) < 0) {
    47                 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    48         }
    49 
    50         status = ads_krb5_set_password(ads->auth.kdc_server, principal,
    51                                        password, ads->auth.time_offset);
    52 
    53         SAFE_FREE(principal);
    54         return status;
    55 }
    5627
    5728/* run kinit to setup our ccache */
     
    7344        } else {
    7445                /* always use the sAMAccountName for security = domain */
    75                 /* global_myname()$@REA.LM */
     46                /* lp_netbios_name()$@REA.LM */
    7647                if ( lp_security() == SEC_DOMAIN ) {
    77                         fstr_sprintf( acct_name, "%s$", global_myname() );
     48                        fstr_sprintf( acct_name, "%s$", lp_netbios_name() );
    7849                        account_name = acct_name;
    7950                }
    8051                else
    81                         /* This looks like host/global_myname()@REA.LM */
     52                        /* This looks like host/lp_netbios_name()@REA.LM */
    8253                        account_name = ads->auth.user_name;
    8354        }
     
    9364        }
    9465
    95         ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
    96                         &ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable,
    97                         NULL);
     66        ret = kerberos_kinit_password_ext(s, ads->auth.password,
     67                                          ads->auth.time_offset,
     68                                          &ads->auth.tgt_expire, NULL,
     69                                          ads->auth.ccache_name, false, false,
     70                                          ads->auth.renewable, NULL);
    9871
    9972        if (ret) {
  • vendor/current/source3/libads/krb5_errs.c

    r414 r988  
    2929        {KRB5_CC_IO, NT_STATUS_UNEXPECTED_IO_ERROR},
    3030        {KRB5KDC_ERR_BADOPTION, NT_STATUS_INVALID_PARAMETER},
    31         {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACCESS_DENIED},
     31        {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACCOUNT_LOCKED_OUT},
    3232        {KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME},
    3333        {KRB5KDC_ERR_ETYPE_NOSUPP, NT_STATUS_LOGON_FAILURE},
  • vendor/current/source3/libads/krb5_setpw.c

    r740 r988  
    2626#ifdef HAVE_KRB5
    2727
    28 #define DEFAULT_KPASSWD_PORT    464
    29 
    30 #define KRB5_KPASSWD_VERS_CHANGEPW              1
    31 
    32 #define KRB5_KPASSWD_VERS_SETPW                 0xff80
    33 #define KRB5_KPASSWD_VERS_SETPW_ALT             2
    34 
    35 #define KRB5_KPASSWD_SUCCESS                    0
    36 #define KRB5_KPASSWD_MALFORMED                  1
    37 #define KRB5_KPASSWD_HARDERROR                  2
    38 #define KRB5_KPASSWD_AUTHERROR                  3
    39 #define KRB5_KPASSWD_SOFTERROR                  4
    40 #define KRB5_KPASSWD_ACCESSDENIED               5
    41 #define KRB5_KPASSWD_BAD_VERSION                6
    42 #define KRB5_KPASSWD_INITIAL_FLAG_NEEDED        7
    43 
    44 /* Those are defined by kerberos-set-passwd-02.txt and are probably
     28/* Those are defined by kerberos-set-passwd-02.txt and are probably
    4529 * not supported by M$ implementation */
    4630#define KRB5_KPASSWD_POLICY_REJECT              8
     
    5337 */
    5438
    55 #define krb5_is_krb_error(packet) \
    56         ( packet && packet->length && (((char *)packet->data)[0] == 0x7e || ((char *)packet->data)[0] == 0x5e))
    57 
    58 /* This implements kerberos password change protocol as specified in
    59  * kerb-chg-password-02.txt and kerberos-set-passwd-02.txt
    60  * as well as microsoft version of the protocol
    61  * as specified in kerberos-set-passwd-00.txt
    62  */
    63 static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
    64 {
    65         char* princ_part1 = NULL;
    66         char* princ_part2 = NULL;
    67         char* realm = NULL;
    68         char* c;
    69         char* princ;
    70 
    71         ASN1_DATA *req;
    72         DATA_BLOB ret;
    73 
    74 
    75         princ = SMB_STRDUP(principal);
    76 
    77         if ((c = strchr_m(princ, '/')) == NULL) {
    78                 c = princ;
    79         } else {
    80                 *c = '\0';
    81                 c++;
    82                 princ_part1 = princ;
    83         }
    84 
    85         princ_part2 = c;
    86 
    87         if ((c = strchr_m(c, '@')) != NULL) {
    88                 *c = '\0';
    89                 c++;
    90                 realm = c;
    91         } else {
    92                 /* We must have a realm component. */
    93                 return data_blob_null;
    94         }
    95 
    96         req = asn1_init(talloc_tos());
    97         if (req == NULL) {
    98                 return data_blob_null;
    99         }
    100 
    101         asn1_push_tag(req, ASN1_SEQUENCE(0));
    102         asn1_push_tag(req, ASN1_CONTEXT(0));
    103         asn1_write_OctetString(req, password, strlen(password));
    104         asn1_pop_tag(req);
    105 
    106         asn1_push_tag(req, ASN1_CONTEXT(1));
    107         asn1_push_tag(req, ASN1_SEQUENCE(0));
    108 
    109         asn1_push_tag(req, ASN1_CONTEXT(0));
    110         asn1_write_Integer(req, 1);
    111         asn1_pop_tag(req);
    112 
    113         asn1_push_tag(req, ASN1_CONTEXT(1));
    114         asn1_push_tag(req, ASN1_SEQUENCE(0));
    115 
    116         if (princ_part1) {
    117                 asn1_write_GeneralString(req, princ_part1);
    118         }
    119        
    120         asn1_write_GeneralString(req, princ_part2);
    121         asn1_pop_tag(req);
    122         asn1_pop_tag(req);
    123         asn1_pop_tag(req);
    124         asn1_pop_tag(req);
    125 
    126         asn1_push_tag(req, ASN1_CONTEXT(2));
    127         asn1_write_GeneralString(req, realm);
    128         asn1_pop_tag(req);
    129         asn1_pop_tag(req);
    130 
    131         ret = data_blob(req->data, req->length);
    132         asn1_free(req);
    133 
    134         free(princ);
    135 
    136         return ret;
    137 }       
    138 
    139 static krb5_error_code build_kpasswd_request(uint16 pversion,
    140                                            krb5_context context,
    141                                            krb5_auth_context auth_context,
    142                                            krb5_data *ap_req,
    143                                            const char *princ,
    144                                            const char *passwd,
    145                                            bool use_tcp,
    146                                            krb5_data *packet)
    147 {
    148         krb5_error_code ret;
    149         krb5_data cipherpw;
    150         krb5_data encoded_setpw;
    151         krb5_replay_data replay;
    152         char *p, *msg_start;
    153         DATA_BLOB setpw;
    154         unsigned int msg_length;
    155 
    156         ret = krb5_auth_con_setflags(context,
    157                                      auth_context,KRB5_AUTH_CONTEXT_DO_SEQUENCE);
    158         if (ret) {
    159                 DEBUG(1,("krb5_auth_con_setflags failed (%s)\n",
    160                          error_message(ret)));
    161                 return ret;
    162         }
    163 
    164         /* handle protocol differences in chpw and setpw */
    165         if (pversion  == KRB5_KPASSWD_VERS_CHANGEPW)
    166                 setpw = data_blob(passwd, strlen(passwd));
    167         else if (pversion == KRB5_KPASSWD_VERS_SETPW ||
    168                  pversion == KRB5_KPASSWD_VERS_SETPW_ALT)
    169                 setpw = encode_krb5_setpw(princ, passwd);
    170         else
    171                 return EINVAL;
    172 
    173         if (setpw.data == NULL || setpw.length == 0) {
    174                 return EINVAL;
    175         }
    176 
    177         encoded_setpw.data = (char *)setpw.data;
    178         encoded_setpw.length = setpw.length;
    179 
    180         ret = krb5_mk_priv(context, auth_context,
    181                            &encoded_setpw, &cipherpw, &replay);
    182        
    183         data_blob_free(&setpw);         /*from 'encode_krb5_setpw(...)' */
    184        
    185         if (ret) {
    186                 DEBUG(1,("krb5_mk_priv failed (%s)\n", error_message(ret)));
    187                 return ret;
    188         }
    189 
    190         packet->data = (char *)SMB_MALLOC(ap_req->length + cipherpw.length + (use_tcp ? 10 : 6 ));
    191         if (!packet->data)
    192                 return -1;
    193 
    194 
    195 
    196         /* see the RFC for details */
    197 
    198         msg_start = p = ((char *)packet->data) + (use_tcp ? 4 : 0);
    199         p += 2;
    200         RSSVAL(p, 0, pversion);
    201         p += 2;
    202         RSSVAL(p, 0, ap_req->length);
    203         p += 2;
    204         memcpy(p, ap_req->data, ap_req->length);
    205         p += ap_req->length;
    206         memcpy(p, cipherpw.data, cipherpw.length);
    207         p += cipherpw.length;
    208         packet->length = PTR_DIFF(p,packet->data);
    209         msg_length = PTR_DIFF(p,msg_start);
    210 
    211         if (use_tcp) {
    212                 RSIVAL(packet->data, 0, msg_length);
    213         }
    214         RSSVAL(msg_start, 0, msg_length);
    215        
    216         free(cipherpw.data);    /* from 'krb5_mk_priv(...)' */
    217 
    218         return 0;
    219 }
    220 
    221 static const struct kpasswd_errors {
    222         int result_code;
    223         const char *error_string;
    224 } kpasswd_errors[] = {
    225         {KRB5_KPASSWD_MALFORMED, "Malformed request error"},
    226         {KRB5_KPASSWD_HARDERROR, "Server error"},
    227         {KRB5_KPASSWD_AUTHERROR, "Authentication error"},
    228         {KRB5_KPASSWD_SOFTERROR, "Password change rejected"},
    229         {KRB5_KPASSWD_ACCESSDENIED, "Client does not have proper authorization"},
    230         {KRB5_KPASSWD_BAD_VERSION, "Protocol version not supported"},
    231         {KRB5_KPASSWD_INITIAL_FLAG_NEEDED, "Authorization ticket must have initial flag set"},
    232         {KRB5_KPASSWD_POLICY_REJECT, "Password rejected due to policy requirements"},
    233         {KRB5_KPASSWD_BAD_PRINCIPAL, "Target principal does not exist"},
    234         {KRB5_KPASSWD_ETYPE_NOSUPP, "Unsupported encryption type"},
    235         {0, NULL}
    236 };
    237 
    238 static krb5_error_code setpw_result_code_string(krb5_context context,
    239                                                 int result_code,
    240                                                 const char **code_string)
    241 {
    242         unsigned int idx = 0;
    243 
    244         while (kpasswd_errors[idx].error_string != NULL) {
    245                 if (kpasswd_errors[idx].result_code ==
    246                     result_code) {
    247                         *code_string = kpasswd_errors[idx].error_string;
    248                         return 0;
    249                 }
    250                 idx++;
    251         }
    252         *code_string = "Password change failed";
    253         return (0);
    254 }
    255 
    256  krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code)
     39static krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code)
    25740{
    25841        switch(res_code) {
     
    27356        }
    27457}
    275 static krb5_error_code parse_setpw_reply(krb5_context context,
    276                                          bool use_tcp,
    277                                          krb5_auth_context auth_context,
    278                                          krb5_data *packet)
    279 {
    280         krb5_data ap_rep;
    281         char *p;
    282         int vnum, ret, res_code;
    283         krb5_data cipherresult;
    284         krb5_data clearresult;
    285         krb5_ap_rep_enc_part *ap_rep_enc;
    286         krb5_replay_data replay;
    287         unsigned int msg_length = packet->length;
    288 
    289 
    290         if (packet->length < (use_tcp ? 8 : 4)) {
    291                 return KRB5KRB_AP_ERR_MODIFIED;
    292         }
    293        
    294         p = (char *)packet->data;
    295         /*
    296         ** see if it is an error
    297         */
    298         if (krb5_is_krb_error(packet)) {
    299 
    300                 ret = handle_krberror_packet(context, packet);
    301                 if (ret) {
    302                         return ret;
    303                 }
    304         }
    305 
    306        
    307         /* tcp... */
    308         if (use_tcp) {
    309                 msg_length -= 4;
    310                 if (RIVAL(p, 0) != msg_length) {
    311                         DEBUG(1,("Bad TCP packet length (%d/%d) from kpasswd server\n",
    312                         RIVAL(p, 0), msg_length));
    313                         return KRB5KRB_AP_ERR_MODIFIED;
    314                 }
    315 
    316                 p += 4;
    317         }
    318        
    319         if (RSVAL(p, 0) != msg_length) {
    320                 DEBUG(1,("Bad packet length (%d/%d) from kpasswd server\n",
    321                          RSVAL(p, 0), msg_length));
    322                 return KRB5KRB_AP_ERR_MODIFIED;
    323         }
    324 
    325         p += 2;
    326 
    327         vnum = RSVAL(p, 0); p += 2;
    328 
    329         /* FIXME: According to standard there is only one type of reply */     
    330         if (vnum != KRB5_KPASSWD_VERS_SETPW &&
    331             vnum != KRB5_KPASSWD_VERS_SETPW_ALT &&
    332             vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
    333                 DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum));
    334                 return KRB5KDC_ERR_BAD_PVNO;
    335         }
    336        
    337         ap_rep.length = RSVAL(p, 0); p += 2;
    338        
    339         if (p + ap_rep.length >= (char *)packet->data + packet->length) {
    340                 DEBUG(1,("ptr beyond end of packet from kpasswd server\n"));
    341                 return KRB5KRB_AP_ERR_MODIFIED;
    342         }
    343        
    344         if (ap_rep.length == 0) {
    345                 DEBUG(1,("got unencrypted setpw result?!\n"));
    346                 return KRB5KRB_AP_ERR_MODIFIED;
    347         }
    348 
    349         /* verify ap_rep */
    350         ap_rep.data = p;
    351         p += ap_rep.length;
    352        
    353         ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
    354         if (ret) {
    355                 DEBUG(1,("failed to rd setpw reply (%s)\n", error_message(ret)));
    356                 return KRB5KRB_AP_ERR_MODIFIED;
    357         }
    358        
    359         krb5_free_ap_rep_enc_part(context, ap_rep_enc);
    360        
    361         cipherresult.data = p;
    362         cipherresult.length = ((char *)packet->data + packet->length) - p;
    363                
    364         ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
    365                            &replay);
    366         if (ret) {
    367                 DEBUG(1,("failed to decrypt setpw reply (%s)\n", error_message(ret)));
    368                 return KRB5KRB_AP_ERR_MODIFIED;
    369         }
    370 
    371         if (clearresult.length < 2) {
    372                 free(clearresult.data);
    373                 ret = KRB5KRB_AP_ERR_MODIFIED;
    374                 return KRB5KRB_AP_ERR_MODIFIED;
    375         }
    376        
    377         p = (char *)clearresult.data;
    378        
    379         res_code = RSVAL(p, 0);
    380        
    381         free(clearresult.data);
    382 
    383         if ((res_code < KRB5_KPASSWD_SUCCESS) ||
    384             (res_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
    385                 return KRB5KRB_AP_ERR_MODIFIED;
    386         }
    387 
    388         if (res_code == KRB5_KPASSWD_SUCCESS) {
    389                 return 0;
    390         } else {
    391                 const char *errstr;
    392                 setpw_result_code_string(context, res_code, &errstr);
    393                 DEBUG(1, ("Error changing password: %s (%d)\n", errstr, res_code));
    394 
    395                 return kpasswd_err_to_krb5_err(res_code);
    396         }
    397 }
    398 
    399 static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
    400                                           const char *kdc_host,
    401                                           uint16 pversion,
    402                                           krb5_creds *credsp,
    403                                           const char *princ,
    404                                           const char *newpw)
    405 {
    406         krb5_auth_context auth_context = NULL;
    407         krb5_data ap_req, chpw_req, chpw_rep;
    408         int ret, sock;
    409         socklen_t addr_len;
    410         struct sockaddr_storage remote_addr, local_addr;
    411         struct sockaddr_storage addr;
    412         krb5_address local_kaddr, remote_kaddr;
    413         bool use_tcp = False;
    414 
    415 
    416         if (!interpret_string_addr(&addr, kdc_host, 0)) {
    417         }
    418 
    419         ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
    420                                    NULL, credsp, &ap_req);
    421         if (ret) {
    422                 DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret)));
    423                 return ADS_ERROR_KRB5(ret);
    424         }
    425 
    426         do {
    427 
    428                 if (!use_tcp) {
    429 
    430                         sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT);
    431                         if (sock == -1) {
    432                                 int rc = errno;
    433                                 SAFE_FREE(ap_req.data);
    434                                 krb5_auth_con_free(context, auth_context);
    435                                 DEBUG(1,("failed to open kpasswd socket to %s "
    436                                          "(%s)\n", kdc_host, strerror(errno)));
    437                                 return ADS_ERROR_SYSTEM(rc);
    438                         }
    439                 } else {
    440                         NTSTATUS status;
    441                         status = open_socket_out(&addr, DEFAULT_KPASSWD_PORT,
    442                                                  LONG_CONNECT_TIMEOUT, &sock);
    443                         if (!NT_STATUS_IS_OK(status)) {
    444                                 SAFE_FREE(ap_req.data);
    445                                 krb5_auth_con_free(context, auth_context);
    446                                 DEBUG(1,("failed to open kpasswd socket to %s "
    447                                          "(%s)\n", kdc_host,
    448                                          nt_errstr(status)));
    449                                 return ADS_ERROR_NT(status);
    450                         }
    451                 }
    452 
    453                 addr_len = sizeof(remote_addr);
    454                 if (getpeername(sock, (struct sockaddr *)&remote_addr, &addr_len) != 0) {
    455                         close(sock);
    456                         SAFE_FREE(ap_req.data);
    457                         krb5_auth_con_free(context, auth_context);
    458                         DEBUG(1,("getpeername() failed (%s)\n", error_message(errno)));
    459                         return ADS_ERROR_SYSTEM(errno);
    460                 }
    461                 addr_len = sizeof(local_addr);
    462                 if (getsockname(sock, (struct sockaddr *)&local_addr, &addr_len) != 0) {
    463                         close(sock);
    464                         SAFE_FREE(ap_req.data);
    465                         krb5_auth_con_free(context, auth_context);
    466                         DEBUG(1,("getsockname() failed (%s)\n", error_message(errno)));
    467                         return ADS_ERROR_SYSTEM(errno);
    468                 }
    469                 if (!setup_kaddr(&remote_kaddr, &remote_addr) ||
    470                                 !setup_kaddr(&local_kaddr, &local_addr)) {
    471                         DEBUG(1,("do_krb5_kpasswd_request: "
    472                                 "Failed to setup addresses.\n"));
    473                         close(sock);
    474                         SAFE_FREE(ap_req.data);
    475                         krb5_auth_con_free(context, auth_context);
    476                         errno = EINVAL;
    477                         return ADS_ERROR_SYSTEM(EINVAL);
    478                 }
    479 
    480                 ret = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL);
    481                 if (ret) {
    482                         close(sock);
    483                         SAFE_FREE(ap_req.data);
    484                         krb5_auth_con_free(context, auth_context);
    485                         DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret)));
    486                         return ADS_ERROR_KRB5(ret);
    487                 }
    488 
    489                 ret = build_kpasswd_request(pversion, context, auth_context, &ap_req,
    490                                           princ, newpw, use_tcp, &chpw_req);
    491                 if (ret) {
    492                         close(sock);
    493                         SAFE_FREE(ap_req.data);
    494                         krb5_auth_con_free(context, auth_context);
    495                         DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret)));
    496                         return ADS_ERROR_KRB5(ret);
    497                 }
    498 
    499                 ret = write(sock, chpw_req.data, chpw_req.length);
    500 
    501                 if (ret != chpw_req.length) {
    502                         close(sock);
    503                         SAFE_FREE(chpw_req.data);
    504                         SAFE_FREE(ap_req.data);
    505                         krb5_auth_con_free(context, auth_context);
    506                         DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
    507                         return ADS_ERROR_SYSTEM(errno);
    508                 }
    509        
    510                 SAFE_FREE(chpw_req.data);
    511        
    512                 chpw_rep.length = 1500;
    513                 chpw_rep.data = (char *) SMB_MALLOC(chpw_rep.length);
    514                 if (!chpw_rep.data) {
    515                         close(sock);
    516                         SAFE_FREE(ap_req.data);
    517                         krb5_auth_con_free(context, auth_context);
    518                         DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
    519                         errno = ENOMEM;
    520                         return ADS_ERROR_SYSTEM(errno);
    521                 }
    522        
    523                 ret = read(sock, chpw_rep.data, chpw_rep.length);
    524                 if (ret < 0) {
    525                         close(sock);
    526                         SAFE_FREE(chpw_rep.data);
    527                         SAFE_FREE(ap_req.data);
    528                         krb5_auth_con_free(context, auth_context);
    529                         DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno)));
    530                         return ADS_ERROR_SYSTEM(errno);
    531                 }
    532        
    533                 close(sock);
    534                 chpw_rep.length = ret;
    535        
    536                 ret = krb5_auth_con_setaddrs(context, auth_context, NULL,&remote_kaddr);
    537                 if (ret) {
    538                         SAFE_FREE(chpw_rep.data);
    539                         SAFE_FREE(ap_req.data);
    540                         krb5_auth_con_free(context, auth_context);
    541                         DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n",
    542                                  error_message(ret)));
    543                         return ADS_ERROR_KRB5(ret);
    544                 }
    545        
    546                 ret = parse_setpw_reply(context, use_tcp, auth_context, &chpw_rep);
    547                 SAFE_FREE(chpw_rep.data);
    548        
    549                 if (ret) {
    550                        
    551                         if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !use_tcp) {
    552                                 DEBUG(5, ("Trying setpw with TCP!!!\n"));
    553                                 use_tcp = True;
    554                                 continue;
    555                         }
    556 
    557                         SAFE_FREE(ap_req.data);
    558                         krb5_auth_con_free(context, auth_context);
    559                         DEBUG(1,("parse_setpw_reply failed (%s)\n",
    560                                  error_message(ret)));
    561                         return ADS_ERROR_KRB5(ret);
    562                 }
    563        
    564                 SAFE_FREE(ap_req.data);
    565                 krb5_auth_con_free(context, auth_context);
    566         } while ( ret );
    567 
    568         return ADS_SUCCESS;
    569 }
    570 
    571 ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ,
     58
     59ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *principal,
    57260                                 const char *newpw, int time_offset)
    57361{
     
    57664        krb5_error_code ret = 0;
    57765        krb5_context context = NULL;
    578         const char *realm = NULL;
    579         unsigned int realm_len = 0;
    580         krb5_creds creds, *credsp = NULL;
     66        krb5_principal princ = NULL;
    58167        krb5_ccache ccache = NULL;
    582 
    583         ZERO_STRUCT(creds);
    584        
     68        int result_code;
     69        krb5_data result_code_string = { 0 };
     70        krb5_data result_string = { 0 };
     71
    58572        initialize_krb5_error_table();
    58673        ret = krb5_init_context(&context);
     
    58976                return ADS_ERROR_KRB5(ret);
    59077        }
    591        
     78
     79        if (principal) {
     80                ret = smb_krb5_parse_name(context, principal, &princ);
     81                if (ret) {
     82                        krb5_free_context(context);
     83                        DEBUG(1, ("Failed to parse %s (%s)\n", principal,
     84                                  error_message(ret)));
     85                        return ADS_ERROR_KRB5(ret);
     86                }
     87        }
     88
    59289        if (time_offset != 0) {
    59390                krb5_set_real_time(context, time(NULL) + time_offset, 0);
     
    59693        ret = krb5_cc_default(context, &ccache);
    59794        if (ret) {
     95                krb5_free_principal(context, princ);
    59896                krb5_free_context(context);
    59997                DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
     
    60199        }
    602100
    603         ret = krb5_cc_get_principal(context, ccache, &creds.client);
     101        ret = krb5_set_password_using_ccache(context,
     102                                             ccache,
     103                                             discard_const_p(char, newpw),
     104                                             princ,
     105                                             &result_code,
     106                                             &result_code_string,
     107                                             &result_string);
    604108        if (ret) {
    605                 krb5_cc_close(context, ccache);
    606                 krb5_free_context(context);
    607                 DEBUG(1,("Failed to get principal from ccache (%s)\n",
    608                          error_message(ret)));
    609                 return ADS_ERROR_KRB5(ret);
    610         }
    611 
    612         realm = smb_krb5_principal_get_realm(context, creds.client);
    613         realm_len = strlen(realm);
    614         ret = krb5_build_principal(context,
    615                                    &creds.server,
    616                                    realm_len,
    617                                    realm, "kadmin", "changepw", NULL);
    618 
    619         ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
    620         if (ret) {
    621                 krb5_cc_close(context, ccache);
    622                 krb5_free_principal(context, creds.client);
    623                 krb5_free_principal(context, creds.server);
    624                 krb5_free_context(context);
    625                 DEBUG(1,("krb5_build_prinipal_ext (%s)\n", error_message(ret)));
    626                 return ADS_ERROR_KRB5(ret);
    627         }
    628        
    629         ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
    630         if (ret) {
    631                 krb5_cc_close(context, ccache);
    632                 krb5_free_principal(context, creds.client);
    633                 krb5_free_principal(context, creds.server);
    634                 krb5_free_context(context);
    635                 DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
    636                 return ADS_ERROR_KRB5(ret);
    637         }
    638        
    639         /* we might have to call krb5_free_creds(...) from now on ... */
    640 
    641         aret = do_krb5_kpasswd_request(context, kdc_host,
    642                                        KRB5_KPASSWD_VERS_SETPW,
    643                                        credsp, princ, newpw);
    644 
    645         krb5_free_creds(context, credsp);
    646         krb5_free_principal(context, creds.client);
    647         krb5_free_principal(context, creds.server);
     109                DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret)));
     110                aret = ADS_ERROR_KRB5(ret);
     111                goto done;
     112        }
     113
     114        if (result_code != KRB5_KPASSWD_SUCCESS) {
     115                ret = kpasswd_err_to_krb5_err(result_code);
     116                DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret)));
     117                aret = ADS_ERROR_KRB5(ret);
     118                goto done;
     119        }
     120
     121        aret = ADS_SUCCESS;
     122
     123done:
     124        kerberos_free_data_contents(context, &result_code_string);
     125        kerberos_free_data_contents(context, &result_string);
     126        krb5_free_principal(context, princ);
    648127        krb5_cc_close(context, ccache);
    649128        krb5_free_context(context);
     
    693172    krb5_creds creds;
    694173    char *chpw_princ = NULL, *password;
    695     const char *realm = NULL;
     174    char *realm = NULL;
     175    int result_code;
     176    krb5_data result_code_string = { 0 };
     177    krb5_data result_string = { 0 };
     178    smb_krb5_addresses *addr = NULL;
    696179
    697180    initialize_krb5_error_table();
     
    710193
    711194    krb5_get_init_creds_opt_init(&opts);
     195
    712196    krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
    713197    krb5_get_init_creds_opt_set_renew_life(&opts, 0);
     
    715199    krb5_get_init_creds_opt_set_proxiable(&opts, 0);
    716200
     201    /* note that heimdal will fill in the local addresses if the addresses
     202     * in the creds_init_opt are all empty and then later fail with invalid
     203     * address, sending our local netbios krb5 address - just like windows
     204     * - avoids this - gd */
     205    ret = smb_krb5_gen_netbios_krb5_address(&addr, lp_netbios_name());
     206    if (ret) {
     207        krb5_free_principal(context, princ);
     208        krb5_free_context(context);
     209        return ADS_ERROR_KRB5(ret);
     210    }
     211    krb5_get_init_creds_opt_set_address_list(&opts, addr->addrs);
     212
    717213    realm = smb_krb5_principal_get_realm(context, princ);
    718214
     
    720216    if (asprintf(&chpw_princ, "kadmin/changepw@%s", realm) == -1) {
    721217        krb5_free_context(context);
     218        free(realm);
    722219        DEBUG(1,("ads_krb5_chg_password: asprintf fail\n"));
    723220        return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
    724221    }
    725222
     223    free(realm);
    726224    password = SMB_STRDUP(oldpw);
    727225    ret = krb5_get_init_creds_password(context, &creds, princ, password,
     
    742240    }
    743241
    744     aret = do_krb5_kpasswd_request(context, kdc_host,
    745                                    KRB5_KPASSWD_VERS_CHANGEPW,
    746                                    &creds, principal, newpw);
    747 
     242    ret = krb5_change_password(context,
     243                               &creds,
     244                               discard_const_p(char, newpw),
     245                               &result_code,
     246                               &result_code_string,
     247                               &result_string);
     248    if (ret) {
     249        DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret)));
     250        aret = ADS_ERROR_KRB5(ret);
     251        goto done;
     252    }
     253
     254    if (result_code != KRB5_KPASSWD_SUCCESS) {
     255        ret = kpasswd_err_to_krb5_err(result_code);
     256        DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret)));
     257        aret = ADS_ERROR_KRB5(ret);
     258        goto done;
     259    }
     260
     261    aret = ADS_SUCCESS;
     262
     263done:
     264    kerberos_free_data_contents(context, &result_code_string);
     265    kerberos_free_data_contents(context, &result_string);
    748266    krb5_free_principal(context, princ);
    749267    krb5_free_context(context);
  • vendor/current/source3/libads/ldap.c

    r860 r988  
    2626#include "libads/sitename_cache.h"
    2727#include "libads/cldap.h"
    28 #include "libads/dns.h"
     28#include "../lib/addns/dnsquery.h"
    2929#include "../libds/common/flags.h"
    3030#include "smbldap.h"
    3131#include "../libcli/security/security.h"
     32#include "../librpc/gen_ndr/netlogon.h"
     33#include "lib/param/loadparm.h"
    3234
    3335#ifdef HAVE_LDAP
     
    6062}
    6163
    62  LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to)
     64 LDAP *ldap_open_with_timeout(const char *server,
     65                              struct sockaddr_storage *ss,
     66                              int port, unsigned int to)
    6367{
    6468        LDAP *ldp = NULL;
    65 
     69        int ldap_err;
     70        char *uri;
    6671
    6772        DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout "
    6873                   "%u seconds\n", server, port, to));
    6974
    70         /* Setup timeout */
    71         gotalarm = 0;
    72         CatchSignal(SIGALRM, gotalarm_sig);
    73         alarm(to);
    74         /* End setup timeout. */
    75 
     75        if (to) {
     76                /* Setup timeout */
     77                gotalarm = 0;
     78                CatchSignal(SIGALRM, gotalarm_sig);
     79                alarm(to);
     80                /* End setup timeout. */
     81        }
     82
     83        if ( strchr_m(server, ':') ) {
     84                /* IPv6 URI */
     85                uri = talloc_asprintf(talloc_tos(), "ldap://[%s]:%u", server, port);
     86        } else {
     87                /* IPv4 URI */
     88                uri = talloc_asprintf(talloc_tos(), "ldap://%s:%u", server, port);
     89        }
     90        if (uri == NULL) {
     91                return NULL;
     92        }
     93
     94#ifdef HAVE_LDAP_INITIALIZE
     95        ldap_err = ldap_initialize(&ldp, uri);
     96#else
    7697        ldp = ldap_open(server, port);
    77 
    78         if (ldp == NULL) {
    79                 DEBUG(2,("Could not open connection to LDAP server %s:%d: %s\n",
    80                          server, port, strerror(errno)));
     98        if (ldp != NULL) {
     99                ldap_err = LDAP_SUCCESS;
    81100        } else {
    82                 DEBUG(10, ("Connected to LDAP server '%s:%d'\n", server, port));
    83         }
    84 
    85         /* Teardown timeout. */
    86         CatchSignal(SIGALRM, SIG_IGN);
    87         alarm(0);
     101                ldap_err = LDAP_OTHER;
     102        }
     103#endif
     104        if (ldap_err != LDAP_SUCCESS) {
     105                DEBUG(2,("Could not initialize connection for LDAP server '%s': %s\n",
     106                         uri, ldap_err2string(ldap_err)));
     107        } else {
     108                DEBUG(10, ("Initialized connection for LDAP server '%s'\n", uri));
     109        }
     110
     111        if (to) {
     112                /* Teardown timeout. */
     113                alarm(0);
     114                CatchSignal(SIGALRM, SIG_IGN);
     115        }
    88116
    89117        return ldp;
     
    101129                                    LDAPMessage **res )
    102130{
     131        int to = lp_ldap_timeout();
    103132        struct timeval timeout;
     133        struct timeval *timeout_ptr = NULL;
    104134        int result;
    105135
    106136        /* Setup timeout for the ldap_search_ext_s call - local and remote. */
    107         timeout.tv_sec = lp_ldap_timeout();
    108         timeout.tv_usec = 0;
    109 
    110         /* Setup alarm timeout.... Do we need both of these ? JRA. */
    111137        gotalarm = 0;
    112         CatchSignal(SIGALRM, gotalarm_sig);
    113         alarm(lp_ldap_timeout());
    114         /* End setup timeout. */
     138
     139        if (to) {
     140                timeout.tv_sec = to;
     141                timeout.tv_usec = 0;
     142                timeout_ptr = &timeout;
     143
     144                /* Setup alarm timeout. */
     145                CatchSignal(SIGALRM, gotalarm_sig);
     146                /* Make the alarm time one second beyond
     147                   the timout we're setting for the
     148                   remote search timeout, to allow that
     149                   to fire in preference. */
     150                alarm(to+1);
     151                /* End setup timeout. */
     152        }
     153
    115154
    116155        result = ldap_search_ext_s(ld, base, scope, filter, attrs,
    117                                    attrsonly, sctrls, cctrls, &timeout,
     156                                   attrsonly, sctrls, cctrls, timeout_ptr,
    118157                                   sizelimit, res);
    119158
    120         /* Teardown timeout. */
    121         CatchSignal(SIGALRM, SIG_IGN);
    122         alarm(0);
     159        if (to) {
     160                /* Teardown alarm timeout. */
     161                CatchSignal(SIGALRM, SIG_IGN);
     162                alarm(0);
     163        }
    123164
    124165        if (gotalarm != 0)
     
    195236  in the ads struct if successful
    196237 */
    197 static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)
    198 {
    199         char *srv;
     238static bool ads_try_connect(ADS_STRUCT *ads, bool gc,
     239                            struct sockaddr_storage *ss)
     240{
    200241        struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply;
    201242        TALLOC_CTX *frame = talloc_stackframe();
    202243        bool ret = false;
    203 
    204         if (!server || !*server) {
     244        char addr[INET6_ADDRSTRLEN];
     245
     246        if (ss == NULL) {
    205247                TALLOC_FREE(frame);
    206248                return False;
    207249        }
    208250
    209         if (!is_ipaddress(server)) {
    210                 struct sockaddr_storage ss;
    211                 char addr[INET6_ADDRSTRLEN];
    212 
    213                 if (!resolve_name(server, &ss, 0x20, true)) {
    214                         DEBUG(5,("ads_try_connect: unable to resolve name %s\n",
    215                                 server ));
    216                         TALLOC_FREE(frame);
    217                         return false;
    218                 }
    219                 print_sockaddr(addr, sizeof(addr), &ss);
    220                 srv = talloc_strdup(frame, addr);
    221         } else {
    222                 /* this copes with inet_ntoa brokenness */
    223                 srv = talloc_strdup(frame, server);
    224         }
    225 
    226         if (!srv) {
    227                 TALLOC_FREE(frame);
    228                 return false;
    229         }
     251        print_sockaddr(addr, sizeof(addr), ss);
    230252
    231253        DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n",
    232                 srv, ads->server.realm));
     254                addr, ads->server.realm));
    233255
    234256        ZERO_STRUCT( cldap_reply );
    235257
    236         if ( !ads_cldap_netlogon_5(frame, srv, ads->server.realm, &cldap_reply ) ) {
    237                 DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));
     258        if ( !ads_cldap_netlogon_5(frame, ss, ads->server.realm, &cldap_reply ) ) {
     259                DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr));
    238260                ret = false;
    239261                goto out;
     
    244266        if ( !(cldap_reply.server_type & NBT_SERVER_LDAP) ) {
    245267                DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n",
    246                         srv));
     268                        addr));
    247269                ret = false;
    248270                goto out;
     
    261283        ads->config.ldap_server_name   = SMB_STRDUP(cldap_reply.pdc_dns_name);
    262284        ads->config.realm              = SMB_STRDUP(cldap_reply.dns_domain);
    263         strupper_m(ads->config.realm);
     285        if (!strupper_m(ads->config.realm)) {
     286                ret = false;
     287                goto out;
     288        }
     289
    264290        ads->config.bind_path          = ads_build_dn(ads->config.realm);
    265291        if (*cldap_reply.server_site) {
     
    274300
    275301        ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT;
    276         if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) {
    277                 DEBUG(1,("ads_try_connect: unable to convert %s "
    278                         "to an address\n",
    279                         srv));
    280                 ret = false;
    281                 goto out;
    282         }
     302        ads->ldap.ss = *ss;
    283303
    284304        /* Store our site name. */
     
    295315
    296316/**********************************************************************
     317 send a cldap ping to list of servers, one at a time, until one of
     318 them answers it's an ldap server. Record success in the ADS_STRUCT.
     319 Take note of and update negative connection cache.
     320**********************************************************************/
     321
     322static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,const char *domain,
     323                                struct ip_service *ip_list, int count)
     324{
     325        int i;
     326        bool ok;
     327
     328        for (i = 0; i < count; i++) {
     329                char server[INET6_ADDRSTRLEN];
     330
     331                print_sockaddr(server, sizeof(server), &ip_list[i].ss);
     332
     333                if (!NT_STATUS_IS_OK(
     334                        check_negative_conn_cache(domain, server)))
     335                        continue;
     336
     337                ok = ads_try_connect(ads, false, &ip_list[i].ss);
     338                if (ok) {
     339                        return NT_STATUS_OK;
     340                }
     341
     342                /* keep track of failures */
     343                add_failed_connection_entry(domain, server,
     344                                            NT_STATUS_UNSUCCESSFUL);
     345        }
     346
     347        return NT_STATUS_NO_LOGON_SERVERS;
     348}
     349
     350/***************************************************************************
     351 resolve a name and perform an "ldap ping" using NetBIOS and related methods
     352****************************************************************************/
     353
     354static NTSTATUS resolve_and_ping_netbios(ADS_STRUCT *ads,
     355                                         const char *domain, const char *realm)
     356{
     357        int count, i;
     358        struct ip_service *ip_list;
     359        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     360
     361        DEBUG(6, ("resolve_and_ping_netbios: (cldap) looking for domain '%s'\n",
     362                  domain));
     363
     364        status = get_sorted_dc_list(domain, NULL, &ip_list, &count,
     365                                    false);
     366        if (!NT_STATUS_IS_OK(status)) {
     367                return status;
     368        }
     369
     370        /* remove servers which are known to be dead based on
     371           the corresponding DNS method */
     372        if (*realm) {
     373                for (i = 0; i < count; ++i) {
     374                        char server[INET6_ADDRSTRLEN];
     375
     376                        print_sockaddr(server, sizeof(server), &ip_list[i].ss);
     377
     378                        if(!NT_STATUS_IS_OK(
     379                                check_negative_conn_cache(realm, server))) {
     380                                /* Ensure we add the workgroup name for this
     381                                   IP address as negative too. */
     382                                add_failed_connection_entry(
     383                                    domain, server,
     384                                    NT_STATUS_UNSUCCESSFUL);
     385                        }
     386                }
     387        }
     388
     389        status = cldap_ping_list(ads, domain, ip_list, count);
     390
     391        SAFE_FREE(ip_list);
     392
     393        return status;
     394}
     395
     396
     397/**********************************************************************
     398 resolve a name and perform an "ldap ping" using DNS
     399**********************************************************************/
     400
     401static NTSTATUS resolve_and_ping_dns(ADS_STRUCT *ads, const char *sitename,
     402                                     const char *realm)
     403{
     404        int count;
     405        struct ip_service *ip_list;
     406        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     407
     408        DEBUG(6, ("resolve_and_ping_dns: (cldap) looking for realm '%s'\n",
     409                  realm));
     410
     411        status = get_sorted_dc_list(realm, sitename, &ip_list, &count,
     412                                    true);
     413        if (!NT_STATUS_IS_OK(status)) {
     414                return status;
     415        }
     416
     417        status = cldap_ping_list(ads, realm, ip_list, count);
     418
     419        SAFE_FREE(ip_list);
     420
     421        return status;
     422}
     423
     424/**********************************************************************
    297425 Try to find an AD dc using our internal name resolution routines
    298  Try the realm first and then then workgroup name if netbios is not 
     426 Try the realm first and then then workgroup name if netbios is not
    299427 disabled
    300428**********************************************************************/
     
    302430static NTSTATUS ads_find_dc(ADS_STRUCT *ads)
    303431{
    304         const char *c_domain;
     432        const char *c_domain = "";
    305433        const char *c_realm;
    306         int count, i=0;
    307         struct ip_service *ip_list;
    308         const char *realm;
    309         const char *domain;
    310         bool got_realm = False;
    311434        bool use_own_domain = False;
    312         char *sitename;
     435        char *sitename = NULL;
    313436        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     437        bool ok = false;
    314438
    315439        /* if the realm and workgroup are both empty, assume they are ours */
     
    318442        c_realm = ads->server.realm;
    319443
    320         if ( !c_realm || !*c_realm ) {
     444        if (c_realm == NULL)
     445                c_realm = "";
     446
     447        if (!*c_realm) {
    321448                /* special case where no realm and no workgroup means our own */
    322449                if ( !ads->server.workgroup || !*ads->server.workgroup ) {
     
    326453        }
    327454
    328         if (c_realm && *c_realm)
    329                 got_realm = True;
    330 
    331         /* we need to try once with the realm name and fallback to the
    332            netbios domain name if we fail (if netbios has not been disabled */
    333 
    334         if ( !got_realm && !lp_disable_netbios() ) {
    335                 c_realm = ads->server.workgroup;
    336                 if (!c_realm || !*c_realm) {
    337                         if ( use_own_domain )
    338                                 c_realm = lp_workgroup();
    339                 }
    340         }
    341 
    342         if ( !c_realm || !*c_realm ) {
    343                 DEBUG(0,("ads_find_dc: no realm or workgroup!  Don't know what to do\n"));
     455        if (!lp_disable_netbios()) {
     456                if (use_own_domain) {
     457                        c_domain = lp_workgroup();
     458                } else {
     459                        c_domain = ads->server.workgroup;
     460                        if (!*c_realm && (!c_domain || !*c_domain)) {
     461                                c_domain = lp_workgroup();
     462                        }
     463                }
     464
     465                if (!c_domain) {
     466                        c_domain = "";
     467                }
     468        }
     469
     470        if (!*c_realm && !*c_domain) {
     471                DEBUG(0, ("ads_find_dc: no realm or workgroup!  Don't know "
     472                          "what to do\n"));
    344473                return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */
    345474        }
    346 
    347         if ( use_own_domain ) {
    348                 c_domain = lp_workgroup();
    349         } else {
    350                 c_domain = ads->server.workgroup;
    351         }
    352 
    353         realm = c_realm;
    354         domain = c_domain;
    355475
    356476        /*
     
    362482                struct sockaddr_storage ip_out;
    363483
    364                 DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n",
    365                         (got_realm ? "realm" : "domain"), realm));
    366 
    367                 if (get_dc_name(domain, realm, srv_name, &ip_out)) {
     484                DEBUG(6, ("ads_find_dc: (ldap) looking for realm '%s'"
     485                          " and falling back to domain '%s'\n",
     486                          c_realm, c_domain));
     487
     488                ok = get_dc_name(c_domain, c_realm, srv_name, &ip_out);
     489                if (ok) {
    368490                        /*
    369491                         * we call ads_try_connect() to fill in the
    370492                         * ads->config details
    371493                         */
    372                         if (ads_try_connect(ads, srv_name, false)) {
     494                        ok = ads_try_connect(ads, false, &ip_out);
     495                        if (ok) {
    373496                                return NT_STATUS_OK;
    374497                        }
     
    378501        }
    379502
    380         sitename = sitename_fetch(realm);
    381 
    382  again:
    383 
    384         DEBUG(6,("ads_find_dc: (cldap) looking for %s '%s'\n",
    385                 (got_realm ? "realm" : "domain"), realm));
    386 
    387         status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm);
    388         if (!NT_STATUS_IS_OK(status)) {
    389                 /* fall back to netbios if we can */
    390                 if ( got_realm && !lp_disable_netbios() ) {
    391                         got_realm = False;
    392                         goto again;
    393                 }
    394 
    395                 SAFE_FREE(sitename);
    396                 return status;
    397         }
    398 
    399         /* if we fail this loop, then giveup since all the IP addresses returned were dead */
    400         for ( i=0; i<count; i++ ) {
    401                 char server[INET6_ADDRSTRLEN];
    402 
    403                 print_sockaddr(server, sizeof(server), &ip_list[i].ss);
    404 
    405                 if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) )
    406                         continue;
    407 
    408                 if (!got_realm) {
    409                         /* realm in this case is a workgroup name. We need
    410                            to ignore any IP addresses in the negative connection
    411                            cache that match ip addresses returned in the ad realm
    412                            case. It sucks that I have to reproduce the logic above... */
    413                         c_realm = ads->server.realm;
    414                         if ( !c_realm || !*c_realm ) {
    415                                 if ( !ads->server.workgroup || !*ads->server.workgroup ) {
    416                                         c_realm = lp_realm();
    417                                 }
     503        if (*c_realm) {
     504                sitename = sitename_fetch(talloc_tos(), c_realm);
     505                status = resolve_and_ping_dns(ads, sitename, c_realm);
     506
     507                if (NT_STATUS_IS_OK(status)) {
     508                        TALLOC_FREE(sitename);
     509                        return status;
     510                }
     511
     512                /* In case we failed to contact one of our closest DC on our
     513                 * site we
     514                 * need to try to find another DC, retry with a site-less SRV
     515                 * DNS query
     516                 * - Guenther */
     517
     518                if (sitename) {
     519                        DEBUG(3, ("ads_find_dc: failed to find a valid DC on "
     520                                  "our site (%s), Trying to find another DC "
     521                                  "for realm '%s' (domain '%s')\n",
     522                                  sitename, c_realm, c_domain));
     523                        namecache_delete(c_realm, 0x1C);
     524                        status =
     525                            resolve_and_ping_dns(ads, NULL, c_realm);
     526
     527                        if (NT_STATUS_IS_OK(status)) {
     528                                TALLOC_FREE(sitename);
     529                                return status;
    418530                        }
    419                         if (c_realm && *c_realm &&
    420                                         !NT_STATUS_IS_OK(check_negative_conn_cache(c_realm, server))) {
    421                                 /* Ensure we add the workgroup name for this
    422                                    IP address as negative too. */
    423                                 add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );
    424                                 continue;
    425                         }
    426                 }
    427 
    428                 if ( ads_try_connect(ads, server, false) ) {
    429                         SAFE_FREE(ip_list);
    430                         SAFE_FREE(sitename);
    431                         return NT_STATUS_OK;
    432                 }
    433 
    434                 /* keep track of failures */
    435                 add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL );
    436         }
    437 
    438         SAFE_FREE(ip_list);
    439 
    440         /* In case we failed to contact one of our closest DC on our site we
    441          * need to try to find another DC, retry with a site-less SRV DNS query
    442          * - Guenther */
    443 
    444         if (sitename) {
    445                 DEBUG(1,("ads_find_dc: failed to find a valid DC on our site (%s), "
    446                                 "trying to find another DC\n", sitename));
    447                 SAFE_FREE(sitename);
    448                 namecache_delete(realm, 0x1C);
    449                 goto again;
    450         }
    451 
    452         return NT_STATUS_NO_LOGON_SERVERS;
    453 }
    454 
    455 /*********************************************************************
    456  *********************************************************************/
    457 
    458 static NTSTATUS ads_lookup_site(void)
    459 {
    460         ADS_STRUCT *ads = NULL;
    461         ADS_STATUS ads_status;
    462         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
    463 
    464         ads = ads_init(lp_realm(), NULL, NULL);
    465         if (!ads) {
    466                 return NT_STATUS_NO_MEMORY;
    467         }
    468 
    469         /* The NO_BIND here will find a DC and set the client site
    470            but not establish the TCP connection */
    471 
    472         ads->auth.flags = ADS_AUTH_NO_BIND;
    473         ads_status = ads_connect(ads);
    474         if (!ADS_ERR_OK(ads_status)) {
    475                 DEBUG(4, ("ads_lookup_site: ads_connect to our realm failed! (%s)\n",
    476                           ads_errstr(ads_status)));
    477         }
    478         nt_status = ads_ntstatus(ads_status);
    479 
    480         if (ads) {
    481                 ads_destroy(&ads);
    482         }
    483 
    484         return nt_status;
    485 }
    486 
    487 /*********************************************************************
    488  *********************************************************************/
    489 
    490 static const char* host_dns_domain(const char *fqdn)
    491 {
    492         const char *p = fqdn;
    493 
    494         /* go to next char following '.' */
    495 
    496         if ((p = strchr_m(fqdn, '.')) != NULL) {
    497                 p++;
    498         }
    499 
    500         return p;
    501 }
    502 
    503 
    504 /**
    505  * Connect to the Global Catalog server
    506  * @param ads Pointer to an existing ADS_STRUCT
    507  * @return status of connection
    508  *
    509  * Simple wrapper around ads_connect() that fills in the
    510  * GC ldap server information
    511  **/
    512 
    513 ADS_STATUS ads_connect_gc(ADS_STRUCT *ads)
    514 {
    515         TALLOC_CTX *frame = talloc_stackframe();
    516         struct dns_rr_srv *gcs_list;
    517         int num_gcs;
    518         char *realm = ads->server.realm;
    519         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
    520         ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
    521         int i;
    522         bool done = false;
    523         char *sitename = NULL;
    524 
    525         if (!realm)
    526                 realm = lp_realm();
    527 
    528         if ((sitename = sitename_fetch(realm)) == NULL) {
    529                 ads_lookup_site();
    530                 sitename = sitename_fetch(realm);
    531         }
    532 
    533         do {
    534                 /* We try once with a sitename and once without
    535                    (unless we don't have a sitename and then we're
    536                    done */
    537 
    538                 if (sitename == NULL)
    539                         done = true;
    540 
    541                 nt_status = ads_dns_query_gcs(frame, realm, sitename,
    542                                               &gcs_list, &num_gcs);
    543 
    544                 SAFE_FREE(sitename);
    545 
    546                 if (!NT_STATUS_IS_OK(nt_status)) {
    547                         ads_status = ADS_ERROR_NT(nt_status);
    548                         goto done;
    549                 }
    550 
    551                 /* Loop until we get a successful connection or have gone
    552                    through them all.  When connecting a GC server, make sure that
    553                    the realm is the server's DNS name and not the forest root */
    554 
    555                 for (i=0; i<num_gcs; i++) {
    556                         ads->server.gc = true;
    557                         ads->server.ldap_server = SMB_STRDUP(gcs_list[i].hostname);
    558                         ads->server.realm = SMB_STRDUP(host_dns_domain(ads->server.ldap_server));
    559                         ads_status = ads_connect(ads);
    560                         if (ADS_ERR_OK(ads_status)) {
    561                                 /* Reset the bind_dn to "".  A Global Catalog server
    562                                    may host  multiple domain trees in a forest.
    563                                    Windows 2003 GC server will accept "" as the search
    564                                    path to imply search all domain trees in the forest */
    565 
    566                                 SAFE_FREE(ads->config.bind_path);
    567                                 ads->config.bind_path = SMB_STRDUP("");
    568 
    569 
    570                                 goto done;
    571                         }
    572                         SAFE_FREE(ads->server.ldap_server);
    573                         SAFE_FREE(ads->server.realm);
    574                 }
    575 
    576                 TALLOC_FREE(gcs_list);
    577                 num_gcs = 0;
    578         } while (!done);
    579 
    580 done:
    581         SAFE_FREE(sitename);
    582         talloc_destroy(frame);
    583 
    584         return ads_status;
    585 }
    586 
    587 
     531                }
     532
     533                TALLOC_FREE(sitename);
     534        }
     535
     536        /* try netbios as fallback - if permitted,
     537           or if configuration specifically requests it */
     538        if (*c_domain) {
     539                if (*c_realm) {
     540                        DEBUG(3, ("ads_find_dc: falling back to netbios "
     541                                  "name resolution for domain '%s' (realm '%s')\n",
     542                                  c_domain, c_realm));
     543                }
     544
     545                status = resolve_and_ping_netbios(ads, c_domain, c_realm);
     546                if (NT_STATUS_IS_OK(status)) {
     547                        return status;
     548                }
     549        }
     550
     551        DEBUG(1, ("ads_find_dc: "
     552                  "name resolution for realm '%s' (domain '%s') failed: %s\n",
     553                  c_realm, c_domain, nt_errstr(status)));
     554        return status;
     555}
    588556/**
    589557 * Connect to the LDAP server
     
    611579        }
    612580
    613         if (ads->server.ldap_server)
    614         {
    615                 if (ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) {
     581        if (ads->server.ldap_server) {
     582                bool ok = false;
     583                struct sockaddr_storage ss;
     584
     585                ok = resolve_name(ads->server.ldap_server, &ss, 0x20, true);
     586                if (!ok) {
     587                        DEBUG(5,("ads_connect: unable to resolve name %s\n",
     588                                 ads->server.ldap_server));
     589                        status = ADS_ERROR_NT(NT_STATUS_NOT_FOUND);
     590                        goto out;
     591                }
     592                ok = ads_try_connect(ads, ads->server.gc, &ss);
     593                if (ok) {
    616594                        goto got_connection;
    617595                }
     
    644622                   and not servicePrincipalName; found by Guenther Deschner */
    645623
    646                 if (asprintf(&ads->auth.user_name, "%s$", global_myname() ) == -1) {
     624                if (asprintf(&ads->auth.user_name, "%s$", lp_netbios_name() ) == -1) {
    647625                        DEBUG(0,("ads_connect: asprintf fail.\n"));
    648626                        ads->auth.user_name = NULL;
     
    658636                ads->auth.kdc_server = SMB_STRDUP(addr);
    659637        }
    660 
    661 #if KRB5_DNS_HACK
    662         /* this is a really nasty hack to avoid ADS DNS problems. It needs a patch
    663            to MIT kerberos to work (tridge) */
    664         {
    665                 char *env = NULL;
    666                 if (asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->config.realm) > 0) {
    667                         setenv(env, ads->auth.kdc_server, 1);
    668                         free(env);
    669                 }
    670         }
    671 #endif
    672638
    673639        /* If the caller() requested no LDAP bind, then we are done */
     
    686652        /* Otherwise setup the TCP LDAP session */
    687653
    688         ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name,
     654        ads->ldap.ld = ldap_open_with_timeout(addr,
     655                                              &ads->ldap.ss,
    689656                                              ads->ldap.port, lp_ldap_timeout());
    690657        if (ads->ldap.ld == NULL) {
     
    703670
    704671        if ( lp_ldap_ssl_ads() ) {
    705                 status = ADS_ERROR(smb_ldap_start_tls(ads->ldap.ld, version));
     672                status = ADS_ERROR(smbldap_start_tls(ads->ldap.ld, version));
    706673                if (!ADS_ERR_OK(status)) {
    707674                        goto out;
     
    782749        if (!in_val) return NULL;
    783750
    784         value = TALLOC_ZERO_P(ctx, struct berval);
     751        value = talloc_zero(ctx, struct berval);
    785752        if (value == NULL)
    786753                return NULL;
     
    788755
    789756        value->bv_len = in_val->bv_len;
    790         value->bv_val = (char *)TALLOC_MEMDUP(ctx, in_val->bv_val,
     757        value->bv_val = (char *)talloc_memdup(ctx, in_val->bv_val,
    791758                                              in_val->bv_len);
    792759        return value;
     
    805772        for (i=0; in_vals[i]; i++)
    806773                ; /* count values */
    807         values = TALLOC_ZERO_ARRAY(ctx, struct berval *, i+1);
     774        values = talloc_zero_array(ctx, struct berval *, i+1);
    808775        if (!values) return NULL;
    809776
     
    826793        for (i=0; in_vals[i]; i++)
    827794                ; /* count values */
    828         values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);
     795        values = talloc_zero_array(ctx, char *, i+1);
    829796        if (!values) return NULL;
    830797
     
    850817        for (i=0; in_vals[i]; i++)
    851818                ; /* count values */
    852         values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);
     819        values = talloc_zero_array(ctx, char *, i+1);
    853820        if (!values) return NULL;
    854821
     
    938905        }
    939906        ber_flatten(cookie_be, &cookie_bv);
    940         PagedResults.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID);
     907        PagedResults.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID);
    941908        PagedResults.ldctl_iscritical = (char) 1;
    942909        PagedResults.ldctl_value.bv_len = cookie_bv->bv_len;
    943910        PagedResults.ldctl_value.bv_val = cookie_bv->bv_val;
    944911
    945         NoReferrals.ldctl_oid = CONST_DISCARD(char *, ADS_NO_REFERRALS_OID);
     912        NoReferrals.ldctl_oid = discard_const_p(char, ADS_NO_REFERRALS_OID);
    946913        NoReferrals.ldctl_iscritical = (char) 0;
    947914        NoReferrals.ldctl_value.bv_len = 0;
    948         NoReferrals.ldctl_value.bv_val = CONST_DISCARD(char *, "");
     915        NoReferrals.ldctl_value.bv_val = discard_const_p(char, "");
    949916
    950917        if (external_control &&
     
    952919             strequal(external_control->control, ADS_SD_FLAGS_OID))) {
    953920
    954                 ExternalCtrl.ldctl_oid = CONST_DISCARD(char *, external_control->control);
     921                ExternalCtrl.ldctl_oid = discard_const_p(char, external_control->control);
    955922                ExternalCtrl.ldctl_iscritical = (char) external_control->critical;
    956923
     
    1013980                DEBUG(3,("ads_do_paged_search_args: ldap_search_with_timeout(%s) -> %s\n", expr,
    1014981                         ldap_err2string(rc)));
     982                if (rc == LDAP_OTHER) {
     983                        char *ldap_errmsg;
     984                        int ret;
     985
     986                        ret = ldap_parse_result(ads->ldap.ld,
     987                                                *res,
     988                                                NULL,
     989                                                NULL,
     990                                                &ldap_errmsg,
     991                                                NULL,
     992                                                NULL,
     993                                                0);
     994                        if (ret == LDAP_SUCCESS) {
     995                                DEBUG(3, ("ldap_search_with_timeout(%s) "
     996                                          "error: %s\n", expr, ldap_errmsg));
     997                                ldap_memfree(ldap_errmsg);
     998                        }
     999                }
    10151000                goto done;
    10161001        }
     
    10971082        while (cookie) {
    10981083                LDAPMessage *res2 = NULL;
    1099                 ADS_STATUS status2;
    11001084                LDAPMessage *msg, *next;
    11011085
    1102                 status2 = ads_do_paged_search_args(ads, bind_path, scope, expr,
     1086                status = ads_do_paged_search_args(ads, bind_path, scope, expr,
    11031087                                              attrs, args, &res2, &count, &cookie);
    1104 
    1105                 if (!ADS_ERR_OK(status2)) break;
     1088                if (!ADS_ERR_OK(status)) {
     1089                        /* Ensure we free all collected results */
     1090                        ads_msgfree(ads, *res);
     1091                        *res = NULL;
     1092                        break;
     1093                }
    11061094
    11071095                /* this relies on the way that ldap_add_result_entry() works internally. I hope
     
    11311119 ADS_STATUS ads_do_search_all_sd_flags(ADS_STRUCT *ads, const char *bind_path,
    11321120                                       int scope, const char *expr,
    1133                                        const char **attrs, uint32 sd_flags,
     1121                                       const char **attrs, uint32_t sd_flags,
    11341122                                       LDAPMessage **res)
    11351123{
     
    13571345        ADS_STATUS status;
    13581346        char *expr;
    1359         const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
     1347        const char *attrs[] = {"*", "msDS-SupportedEncryptionTypes", "nTSecurityDescriptor", NULL};
    13601348
    13611349        *res = NULL;
     
    13831371        LDAPMod **mods;
    13841372
    1385         if ((mods = TALLOC_ZERO_ARRAY(ctx, LDAPMod *, ADS_MODLIST_ALLOC_SIZE + 1)))
     1373        if ((mods = talloc_zero_array(ctx, LDAPMod *, ADS_MODLIST_ALLOC_SIZE + 1)))
    13861374                /* -1 is safety to make sure we don't go over the end.
    13871375                   need to reset it to NULL before doing ldap modify */
     
    13991387                                  const void *_invals)
    14001388{
    1401         const void **invals = (const void **)_invals;
    14021389        int curmod;
    14031390        LDAPMod **modlist = (LDAPMod **) *mods;
     
    14051392        char **char_values = NULL;
    14061393
    1407         if (!invals) {
     1394        if (!_invals) {
    14081395                mod_op = LDAP_MOD_DELETE;
    14091396        } else {
    1410                 if (mod_op & LDAP_MOD_BVALUES)
    1411                         ber_values = ads_dup_values(ctx,
    1412                                                 (const struct berval **)invals);
    1413                 else
    1414                         char_values = ads_push_strvals(ctx,
    1415                                                   (const char **) invals);
     1397                if (mod_op & LDAP_MOD_BVALUES) {
     1398                        const struct berval **b;
     1399                        b = discard_const_p(const struct berval *, _invals);
     1400                        ber_values = ads_dup_values(ctx, b);
     1401                } else {
     1402                        const char **c;
     1403                        c = discard_const_p(const char *, _invals);
     1404                        char_values = ads_push_strvals(ctx, c);
     1405                }
    14161406        }
    14171407
     
    14201410             curmod++);
    14211411        if (modlist[curmod] == (LDAPMod *) -1) {
    1422                 if (!(modlist = TALLOC_REALLOC_ARRAY(ctx, modlist, LDAPMod *,
     1412                if (!(modlist = talloc_realloc(ctx, modlist, LDAPMod *,
    14231413                                curmod+ADS_MODLIST_ALLOC_SIZE+1)))
    14241414                        return ADS_ERROR(LDAP_NO_MEMORY);
     
    14291419        }
    14301420
    1431         if (!(modlist[curmod] = TALLOC_ZERO_P(ctx, LDAPMod)))
     1421        if (!(modlist[curmod] = talloc_zero(ctx, LDAPMod)))
    14321422                return ADS_ERROR(LDAP_NO_MEMORY);
    14331423        modlist[curmod]->mod_type = talloc_strdup(ctx, name);
     
    15051495#endif
    15061496
     1497static void ads_print_error(int ret, LDAP *ld)
     1498{
     1499        if (ret != 0) {
     1500                char *ld_error = NULL;
     1501                ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_error);
     1502                DEBUG(10,("AD LDAP failure %d (%s):\n%s\n", ret,
     1503                        ldap_err2string(ret), ld_error));
     1504                SAFE_FREE(ld_error);
     1505        }
     1506}
     1507
    15071508/**
    15081509 * Perform an ldap modify
     
    15221523        */
    15231524        LDAPControl PermitModify = {
    1524                 CONST_DISCARD(char *, ADS_PERMIT_MODIFY_OID),
     1525                discard_const_p(char, ADS_PERMIT_MODIFY_OID),
    15251526                {0, NULL},
    15261527                (char) 1};
     
    15401541        ret = ldap_modify_ext_s(ads->ldap.ld, utf8_dn,
    15411542                                (LDAPMod **) mods, controls, NULL);
     1543        ads_print_error(ret, ads->ldap.ld);
    15421544        TALLOC_FREE(utf8_dn);
    15431545        return ADS_ERROR(ret);
     
    15681570
    15691571        ret = ldap_add_s(ads->ldap.ld, utf8_dn, (LDAPMod**)mods);
     1572        ads_print_error(ret, ads->ldap.ld);
    15701573        TALLOC_FREE(utf8_dn);
    15711574        return ADS_ERROR(ret);
     
    15891592
    15901593        ret = ldap_delete_s(ads->ldap.ld, utf8_dn);
     1594        ads_print_error(ret, ads->ldap.ld);
    15911595        TALLOC_FREE(utf8_dn);
    15921596        return ADS_ERROR(ret);
     
    17401744 **/
    17411745
    1742 uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name)
     1746uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name)
    17431747{
    17441748        LDAPMessage *res = NULL;
    1745         uint32 kvno = (uint32)-1;      /* -1 indicates a failure */
     1749        uint32_t kvno = (uint32_t)-1;      /* -1 indicates a failure */
    17461750        char *filter;
    17471751        const char *attrs[] = {"msDS-KeyVersionNumber", NULL};
     
    18781882
    18791883/**
     1884 * @brief Search for an element in a string array.
     1885 *
     1886 * @param[in]  el_array  The string array to search.
     1887 *
     1888 * @param[in]  num_el    The number of elements in the string array.
     1889 *
     1890 * @param[in]  el        The string to search.
     1891 *
     1892 * @return               True if found, false if not.
     1893 */
     1894bool ads_element_in_array(const char **el_array, size_t num_el, const char *el)
     1895{
     1896        size_t i;
     1897
     1898        if (el_array == NULL || num_el == 0 || el == NULL) {
     1899                return false;
     1900        }
     1901
     1902        for (i = 0; i < num_el && el_array[i] != NULL; i++) {
     1903                int cmp;
     1904
     1905                cmp = strcasecmp_m(el_array[i], el);
     1906                if (cmp == 0) {
     1907                        return true;
     1908                }
     1909        }
     1910
     1911        return false;
     1912}
     1913
     1914/**
     1915 * @brief This gets the service principal names of an existing computer account.
     1916 *
     1917 * @param[in]  mem_ctx      The memory context to use to allocate the spn array.
     1918 *
     1919 * @param[in]  ads          The ADS context to use.
     1920 *
     1921 * @param[in]  machine_name The NetBIOS name of the computer, which is used to
     1922 *                          identify the computer account.
     1923 *
     1924 * @param[in]  spn_array    A pointer to store the array for SPNs.
     1925 *
     1926 * @param[in]  num_spns     The number of principals stored in the array.
     1927 *
     1928 * @return                  0 on success, or a ADS error if a failure occured.
     1929 */
     1930ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx,
     1931                                           ADS_STRUCT *ads,
     1932                                           const char *machine_name,
     1933                                           char ***spn_array,
     1934                                           size_t *num_spns)
     1935{
     1936        ADS_STATUS status;
     1937        LDAPMessage *res = NULL;
     1938        int count;
     1939
     1940        status = ads_find_machine_acct(ads,
     1941                                       &res,
     1942                                       machine_name);
     1943        if (!ADS_ERR_OK(status)) {
     1944                DEBUG(1,("Host Account for %s not found... skipping operation.\n",
     1945                         machine_name));
     1946                return status;
     1947        }
     1948
     1949        count = ads_count_replies(ads, res);
     1950        if (count != 1) {
     1951                status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     1952                goto done;
     1953        }
     1954
     1955        *spn_array = ads_pull_strings(ads,
     1956                                      mem_ctx,
     1957                                      res,
     1958                                      "servicePrincipalName",
     1959                                      num_spns);
     1960        if (*spn_array == NULL) {
     1961                DEBUG(1, ("Host account for %s does not have service principal "
     1962                          "names.\n",
     1963                          machine_name));
     1964                status = ADS_ERROR(LDAP_NO_SUCH_OBJECT);
     1965                goto done;
     1966        }
     1967
     1968done:
     1969        ads_msgfree(ads, res);
     1970
     1971        return status;
     1972}
     1973
     1974/**
    18801975 * This adds a service principal name to an existing computer account
    18811976 * (found by hostname) in AD.
     
    19212016                return ADS_ERROR(LDAP_NO_MEMORY);
    19222017        }
    1923         strlower_m(&psp1[strlen(spn) + 1]);
     2018        if (!strlower_m(&psp1[strlen(spn) + 1])) {
     2019                ret = ADS_ERROR(LDAP_NO_MEMORY);
     2020                goto out;
     2021        }
    19242022        servicePrincipalName[0] = psp1;
    19252023
     
    19342032                goto out;
    19352033        }
    1936         strlower_m(&psp2[strlen(spn) + 1]);
     2034        if (!strlower_m(&psp2[strlen(spn) + 1])) {
     2035                ret = ADS_ERROR(LDAP_NO_MEMORY);
     2036                goto out;
     2037        }
    19372038        servicePrincipalName[1] = psp2;
    19382039
     
    19772078**/
    19782079
    1979 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
    1980                                    const char *org_unit)
     2080ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads,
     2081                                   const char *machine_name,
     2082                                   const char *org_unit,
     2083                                   uint32_t etype_list)
    19812084{
    19822085        ADS_STATUS ret;
     
    19892092                                     "user", "computer", NULL};
    19902093        LDAPMessage *res = NULL;
    1991         uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\
     2094        uint32_t acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\
    19922095                                UF_DONT_EXPIRE_PASSWD |\
    19932096                                UF_ACCOUNTDISABLE );
     2097        uint32_t func_level = 0;
     2098
     2099        ret = ads_domain_func_level(ads, &func_level);
     2100        if (!ADS_ERR_OK(ret)) {
     2101                return ret;
     2102        }
    19942103
    19952104        if (!(ctx = talloc_init("ads_add_machine_acct")))
     
    20262135        ads_mod_strlist(ctx, &mods, "objectClass", objectClass);
    20272136        ads_mod_str(ctx, &mods, "userAccountControl", controlstr);
     2137
     2138        if (func_level >= DS_DOMAIN_FUNCTION_2008) {
     2139                const char *etype_list_str;
     2140
     2141                etype_list_str = talloc_asprintf(ctx, "%d", (int)etype_list);
     2142                if (etype_list_str == NULL) {
     2143                        goto done;
     2144                }
     2145                ads_mod_str(ctx, &mods, "msDS-SupportedEncryptionTypes",
     2146                            etype_list_str);
     2147        }
    20282148
    20292149        ret = ads_gen_add(ads, new_dn, mods);
     
    21492269                struct dom_sid sid;
    21502270                fstring tmp;
    2151                 if (!sid_parse(values[i]->bv_val, values[i]->bv_len, &sid)) {
     2271                if (!sid_parse((const uint8_t *)values[i]->bv_val,
     2272                               values[i]->bv_len, &sid)) {
    21522273                        return;
    21532274                }
     
    21652286        NTSTATUS status;
    21662287
    2167         status = unmarshall_sec_desc(talloc_tos(), (uint8 *)values[0]->bv_val,
     2288        status = unmarshall_sec_desc(talloc_tos(), (uint8_t *)values[0]->bv_val,
    21682289                                     values[0]->bv_len, &psd);
    21692290        if (!NT_STATUS_IS_OK(status)) {
     
    22242345
    22252346        for (i=0; handlers[i].name; i++) {
    2226                 if (StrCaseCmp(handlers[i].name, field) == 0) {
     2347                if (strcasecmp_m(handlers[i].name, field) == 0) {
    22272348                        if (!values) /* first time, indicate string or not */
    22282349                                return handlers[i].string;
     
    22842405                                                    (LDAPMessage *)msg,b)) {
    22852406                        struct berval **ber_vals;
    2286                         char **str_vals, **utf8_vals;
     2407                        char **str_vals;
     2408                        char **utf8_vals;
    22872409                        char *field;
    22882410                        bool string;
     
    22992421
    23002422                        if (string) {
     2423                                const char **p;
     2424
    23012425                                utf8_vals = ldap_get_values(ads->ldap.ld,
    23022426                                                 (LDAPMessage *)msg, field);
    2303                                 str_vals = ads_pull_strvals(ctx,
    2304                                                   (const char **) utf8_vals);
     2427                                p = discard_const_p(const char *, utf8_vals);
     2428                                str_vals = ads_pull_strvals(ctx, p);
    23052429                                fn(ads, field, (void **) str_vals, data_area);
    23062430                                ldap_value_free(utf8_vals);
     
    24292553        *num_values = ldap_count_values(values);
    24302554
    2431         ret = TALLOC_ARRAY(mem_ctx, char *, *num_values + 1);
     2555        ret = talloc_array(mem_ctx, char *, *num_values + 1);
    24322556        if (!ret) {
    24332557                ldap_value_free(values);
     
    25422666        }
    25432667
    2544         strings = TALLOC_REALLOC_ARRAY(mem_ctx, current_strings, char *,
     2668        strings = talloc_realloc(mem_ctx, current_strings, char *,
    25452669                                 *num_strings + num_new_strings);
    25462670
     
    25782702
    25792703/**
    2580  * pull a single uint32 from a ADS result
     2704 * pull a single uint32_t from a ADS result
    25812705 * @param ads connection to ads server
    25822706 * @param msg Results of search
     
    25862710*/
    25872711 bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field,
    2588                       uint32 *v)
     2712                      uint32_t *v)
    25892713{
    25902714        char **values;
     
    26652789
    26662790        if (i) {
    2667                 (*sids) = TALLOC_ARRAY(mem_ctx, struct dom_sid, i);
     2791                (*sids) = talloc_array(mem_ctx, struct dom_sid, i);
    26682792                if (!(*sids)) {
    26692793                        ldap_value_free_len(values);
     
    26762800        count = 0;
    26772801        for (i=0; values[i]; i++) {
    2678                 ret = sid_parse(values[i]->bv_val, values[i]->bv_len, &(*sids)[count]);
     2802                ret = sid_parse((const uint8_t *)values[i]->bv_val,
     2803                                values[i]->bv_len, &(*sids)[count]);
    26792804                if (ret) {
    26802805                        DEBUG(10, ("pulling SID: %s\n",
     
    27112836                NTSTATUS status;
    27122837                status = unmarshall_sec_desc(mem_ctx,
    2713                                              (uint8 *)values[0]->bv_val,
     2838                                             (uint8_t *)values[0]->bv_val,
    27142839                                             values[0]->bv_len, sd);
    27152840                if (!NT_STATUS_IS_OK(status)) {
     
    27612886 * @return status of search
    27622887 **/
    2763 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
     2888ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32_t *usn)
    27642889{
    27652890        const char *attrs[] = {"highestCommittedUSN", NULL};
     
    28532978        if (ads->config.current_time != 0) {
    28542979                ads->auth.time_offset = ads->config.current_time - time(NULL);
    2855                 DEBUG(4,("time offset is %d seconds\n", ads->auth.time_offset));
     2980                DEBUG(4,("KDC time offset is %d seconds\n", ads->auth.time_offset));
    28562981        }
    28572982
     
    28732998********************************************************************/
    28742999
    2875 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val)
     3000ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val)
    28763001{
    28773002        const char *attrs[] = {"domainFunctionality", NULL};
     
    31433268        for (msg = ads_first_entry(ads, res); msg;
    31443269             msg = ads_next_entry(ads, msg)) {
    3145 
     3270                const char **p = discard_const_p(const char *, *ous);
    31463271                char *dn = NULL;
    31473272
     
    31523277                }
    31533278
    3154                 if (!add_string_to_array(mem_ctx, dn,
    3155                                          (const char ***)ous,
    3156                                          (int *)num_ous)) {
     3279                if (!add_string_to_array(mem_ctx, dn, &p, num_ous)) {
    31573280                        TALLOC_FREE(dn);
    31583281                        ads_msgfree(ads, res);
     
    31613284
    31623285                TALLOC_FREE(dn);
     3286                *ous = discard_const_p(char *, p);
    31633287        }
    31643288
     
    32423366                }
    32433367
    3244                 if (!sid_parse(buf, buf_len, sid)) {
     3368                if (!sid_parse((const uint8_t *)buf, buf_len, sid)) {
    32453369                        DEBUG(10,("failed to parse sid\n"));
    32463370                        return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     
    32543378
    32553379        return ADS_ERROR_NT(NT_STATUS_OK);
    3256 }
    3257 
    3258 /**
    3259  * pull an array of struct dom_sids from a ADS result
    3260  * @param ads connection to ads server
    3261  * @param mem_ctx TALLOC_CTX for allocating sid array
    3262  * @param msg Results of search
    3263  * @param field Attribute to retrieve
    3264  * @param flags string type of extended_dn
    3265  * @param sids pointer to sid array to allocate
    3266  * @return the count of SIDs pulled
    3267  **/
    3268  int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,
    3269                                    TALLOC_CTX *mem_ctx,
    3270                                    LDAPMessage *msg,
    3271                                    const char *field,
    3272                                    enum ads_extended_dn_flags flags,
    3273                                    struct dom_sid **sids)
    3274 {
    3275         int i;
    3276         ADS_STATUS rc;
    3277         size_t dn_count, ret_count = 0;
    3278         char **dn_strings;
    3279 
    3280         if ((dn_strings = ads_pull_strings(ads, mem_ctx, msg, field,
    3281                                            &dn_count)) == NULL) {
    3282                 return 0;
    3283         }
    3284 
    3285         (*sids) = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, dn_count + 1);
    3286         if (!(*sids)) {
    3287                 TALLOC_FREE(dn_strings);
    3288                 return 0;
    3289         }
    3290 
    3291         for (i=0; i<dn_count; i++) {
    3292                 rc = ads_get_sid_from_extended_dn(mem_ctx, dn_strings[i],
    3293                                                   flags, &(*sids)[i]);
    3294                 if (!ADS_ERR_OK(rc)) {
    3295                         if (NT_STATUS_EQUAL(ads_ntstatus(rc),
    3296                             NT_STATUS_NOT_FOUND)) {
    3297                                 continue;
    3298                         }
    3299                         else {
    3300                                 TALLOC_FREE(*sids);
    3301                                 TALLOC_FREE(dn_strings);
    3302                                 return 0;
    3303                         }
    3304                 }
    3305                 ret_count++;
    3306         }
    3307 
    3308         TALLOC_FREE(dn_strings);
    3309 
    3310         return ret_count;
    33113380}
    33123381
     
    33213390        char *name = NULL;
    33223391
    3323         status = ads_find_machine_acct(ads, &res, global_myname());
     3392        status = ads_find_machine_acct(ads, &res, lp_netbios_name());
    33243393        if (!ADS_ERR_OK(status)) {
    33253394                DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
    3326                         global_myname()));
     3395                        lp_netbios_name()));
    33273396                goto out;
    33283397        }
     
    33563425        if (!ADS_ERR_OK(status)) {
    33573426                DEBUG(0,("ads_get_upn: Failed to find account for %s\n",
    3358                         global_myname()));
     3427                        lp_netbios_name()));
    33593428                goto out;
    33603429        }
     
    33853454        char *name = NULL;
    33863455
    3387         status = ads_find_machine_acct(ads, &res, global_myname());
     3456        status = ads_find_machine_acct(ads, &res, lp_netbios_name());
    33883457        if (!ADS_ERR_OK(status)) {
    33893458                DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n",
    3390                         global_myname()));
     3459                        lp_netbios_name()));
    33913460                goto out;
    33923461        }
     
    34203489 **/
    34213490ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name,
    3422                         uint32 account_type, const char *org_unit)
     3491                        uint32_t account_type, const char *org_unit)
    34233492{
    34243493        ADS_STATUS status;
     
    34813550        pldap_control[0] = &ldap_control;
    34823551        memset(&ldap_control, 0, sizeof(LDAPControl));
    3483         ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID;
     3552        ldap_control.ldctl_oid = discard_const_p(char, LDAP_SERVER_TREE_DELETE_OID);
    34843553
    34853554        /* hostname must be lowercase */
    34863555        host = SMB_STRDUP(hostname);
    3487         strlower_m(host);
     3556        if (!strlower_m(host)) {
     3557                SAFE_FREE(host);
     3558                return ADS_ERROR_SYSTEM(EINVAL);
     3559        }
    34883560
    34893561        status = ads_find_machine_acct(ads, &res, host);
     
    36133685        struct dom_sid tmp_user_sid;
    36143686        struct dom_sid tmp_primary_group_sid;
    3615         uint32 pgid;
     3687        uint32_t pgid;
    36163688        const char *attrs[] = {
    36173689                "objectSid",
     
    36953767 * @param mem_ctx TALLOC_CTX for allocating sid array
    36963768 * @param samaccountname to search
    3697  * @param uac_ret uint32 pointer userAccountControl attribute value
     3769 * @param uac_ret uint32_t pointer userAccountControl attribute value
    36983770 * @param dn_ret pointer to dn
    36993771 * @return status of token query
     
    37023774                               TALLOC_CTX *mem_ctx,
    37033775                               const char *samaccountname,
    3704                                uint32 *uac_ret,
     3776                               uint32_t *uac_ret,
    37053777                               const char **dn_ret)
    37063778{
     
    37103782        LDAPMessage *res = NULL;
    37113783        char *dn = NULL;
    3712         uint32 uac = 0;
     3784        uint32_t uac = 0;
    37133785
    37143786        filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))",
     
    38683940        char *ou_string;
    38693941
    3870         exploded_dn = ldap_explode_dn(*account_ou, 0);
    3871         if (exploded_dn) {
    3872                 ldap_value_free(exploded_dn);
    3873                 return ADS_SUCCESS;
     3942        if (account_ou == NULL) {
     3943                return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
     3944        }
     3945
     3946        if (*account_ou != NULL) {
     3947                exploded_dn = ldap_explode_dn(*account_ou, 0);
     3948                if (exploded_dn) {
     3949                        ldap_value_free(exploded_dn);
     3950                        return ADS_SUCCESS;
     3951                }
    38743952        }
    38753953
  • vendor/current/source3/libads/ldap_printer.c

    r740 r988  
    2323#include "../librpc/gen_ndr/ndr_spoolss_c.h"
    2424#include "rpc_client/cli_spoolss.h"
    25 #include "registry/reg_objects.h"
     25#include "registry.h"
     26#include "libcli/registry/util_reg.h"
    2627
    2728#ifdef HAVE_ADS
     
    115116  map a REG_SZ to an ldap mod
    116117*/
    117 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    118                    struct regval_blob *value)
     118static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
     119                   const char *name, struct registry_value *value)
     120{
     121        const char *str_value = NULL;
     122        ADS_STATUS status;
     123
     124        if (value->type != REG_SZ)
     125                return false;
     126
     127        if (value->data.length  && value->data.data) {
     128                if (!pull_reg_sz(ctx, &value->data, &str_value)) {
     129                        return false;
     130                }
     131                status = ads_mod_str(ctx, mods, name, str_value);
     132                return ADS_ERR_OK(status);
     133        }
     134        return true;
     135}
     136
     137/*
     138  map a REG_DWORD to an ldap mod
     139*/
     140static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
     141                      const char *name, struct registry_value *value)
    119142{
    120143        char *str_value = NULL;
    121         size_t converted_size;
    122         ADS_STATUS status;
    123 
    124         if (regval_type(value) != REG_SZ)
    125                 return false;
    126 
    127         if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
    128                 if (!pull_ucs2_talloc(ctx, &str_value,
    129                                       (const smb_ucs2_t *) regval_data_p(value),
    130                                       &converted_size))
    131                 {
     144        ADS_STATUS status;
     145
     146        if (value->type != REG_DWORD) {
     147                return false;
     148        }
     149        if (value->data.length != sizeof(uint32_t)) {
     150                return false;
     151        }
     152        str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0));
     153        if (!str_value) {
     154                return false;
     155        }
     156        status = ads_mod_str(ctx, mods, name, str_value);
     157        return ADS_ERR_OK(status);
     158}
     159
     160/*
     161  map a boolean REG_BINARY to an ldap mod
     162*/
     163static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
     164                     const char *name, struct registry_value *value)
     165{
     166        const char *str_value;
     167        ADS_STATUS status;
     168
     169        if (value->type != REG_BINARY) {
     170                return false;
     171        }
     172        if (value->data.length != 1) {
     173                return false;
     174        }
     175
     176        str_value =  *value->data.data ? "TRUE" : "FALSE";
     177
     178        status = ads_mod_str(ctx, mods, name, str_value);
     179        return ADS_ERR_OK(status);
     180}
     181
     182/*
     183  map a REG_MULTI_SZ to an ldap mod
     184*/
     185static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
     186                         const char *name, struct registry_value *value)
     187{
     188        const char **str_values = NULL;
     189        ADS_STATUS status;
     190
     191        if (value->type != REG_MULTI_SZ) {
     192                return false;
     193        }
     194
     195        if (value->data.length  && value->data.data) {
     196                if (!pull_reg_multi_sz(ctx, &value->data, &str_values)) {
    132197                        return false;
    133198                }
    134                 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
     199                status = ads_mod_strlist(ctx, mods, name, str_values);
    135200                return ADS_ERR_OK(status);
    136201        }
    137202        return true;
    138                
    139 }
    140 
    141 /*
    142   map a REG_DWORD to an ldap mod
    143 */
    144 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    145                       struct regval_blob *value)
    146 {
    147         char *str_value = NULL;
    148         ADS_STATUS status;
    149 
    150         if (regval_type(value) != REG_DWORD)
    151                 return False;
    152         str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
    153         if (!str_value) {
    154                 return False;
    155         }
    156         status = ads_mod_str(ctx, mods, regval_name(value), str_value);
    157         return ADS_ERR_OK(status);
    158 }
    159 
    160 /*
    161   map a boolean REG_BINARY to an ldap mod
    162 */
    163 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    164                      struct regval_blob *value)
    165 {
    166         char *str_value;
    167         ADS_STATUS status;
    168 
    169         if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
    170                 return False;
    171         str_value =  talloc_asprintf(ctx, "%s",
    172                                      *(regval_data_p(value)) ? "TRUE" : "FALSE");
    173         if (!str_value) {
    174                 return False;
    175         }
    176         status = ads_mod_str(ctx, mods, regval_name(value), str_value);
    177         return ADS_ERR_OK(status);
    178 }
    179 
    180 /*
    181   map a REG_MULTI_SZ to an ldap mod
    182 */
    183 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    184                          struct regval_blob *value)
    185 {
    186         char **str_values = NULL;
    187         size_t converted_size;
    188         smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
    189         uint32 size = 0, num_vals = 0, i=0;
    190         ADS_STATUS status;
    191 
    192         if (regval_type(value) != REG_MULTI_SZ)
    193                 return False;
    194 
    195         while(cur_str && *cur_str && (size < regval_size(value))) {
    196                 size += 2 * (strlen_w(cur_str) + 1);
    197                 cur_str += strlen_w(cur_str) + 1;
    198                 num_vals++;
    199         };
    200 
    201         if (num_vals) {
    202                 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
    203                 if (!str_values) {
    204                         return False;
    205                 }
    206                 memset(str_values, '\0',
    207                        (num_vals + 1) * sizeof(char *));
    208 
    209                 cur_str = (smb_ucs2_t *) regval_data_p(value);
    210                 for (i=0; i < num_vals; i++) {
    211                         cur_str += pull_ucs2_talloc(ctx, &str_values[i],
    212                                                     cur_str, &converted_size) ?
    213                             converted_size : (size_t)-1;
    214                 }
    215 
    216                 status = ads_mod_strlist(ctx, mods, regval_name(value),
    217                                          (const char **) str_values);
    218                 return ADS_ERR_OK(status);
    219         }
    220         return True;
    221203}
    222204
    223205struct valmap_to_ads {
    224206        const char *valname;
    225         bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
     207        bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const char *, struct registry_value *);
    226208};
    227209
     
    230212*/
    231213static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
    232                               struct regval_blob *value)
     214                              const char *name, struct registry_value *value)
    233215{
    234216        const struct valmap_to_ads map[] = {
     
    290272
    291273        for (i=0; map[i].valname; i++) {
    292                 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
    293                         if (!map[i].fn(ctx, mods, value)) {
    294                                 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
     274                if (strcasecmp_m(map[i].valname, name) == 0) {
     275                        if (!map[i].fn(ctx, mods, name, value)) {
     276                                DEBUG(5, ("Add of value %s to modlist failed\n", name));
    295277                        } else {
    296                                 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
     278                                DEBUG(7, ("Mapped value %s\n", name));
    297279                        }
    298                        
    299280                }
    300281        }
     
    312293        struct spoolss_PrinterEnumValues *info;
    313294        uint32_t count;
    314         uint32 i;
     295        uint32_t i;
    315296        struct policy_handle pol;
    316297        WERROR werr;
     
    344325                /* Have the data we need now, so start building */
    345326                for (i=0; i < count; i++) {
    346                         struct regval_blob *v;
    347 
    348                         v = regval_compose(mem_ctx, info[i].value_name,
    349                                            info[i].type,
    350                                            info[i].data->data,
    351                                            info[i].data->length);
    352                         if (v == NULL) {
    353                                 return WERR_NOMEM;
    354                         }
    355 
    356                         map_regval_to_ads(mem_ctx, mods, v);
    357                         talloc_free(v);
     327                        struct registry_value v;
     328                        v.type = info[i].type;
     329                        v.data = *info[i].data;
     330
     331                        map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
    358332                }
    359333        }
     
    369343        } else {
    370344                for (i=0; i < count; i++) {
    371                         struct regval_blob *v;
    372 
    373                         v = regval_compose(mem_ctx, info[i].value_name,
    374                                            info[i].type,
    375                                            info[i].data->data,
    376                                            info[i].data->length);
    377                         if (v == NULL) {
    378                                 return WERR_NOMEM;
    379                         }
    380 
    381                         map_regval_to_ads(mem_ctx, mods, v);
    382                         talloc_free(v);
     345                        struct registry_value v;
     346                        v.type = info[i].type;
     347                        v.data = *info[i].data;
     348
     349                        map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v);
    383350                }
    384351        }
  • vendor/current/source3/libads/ldap_schema.c

    r740 r988  
    7777        }
    7878
    79         if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
     79        if (((*names) = talloc_array(mem_ctx, char *, *count)) == NULL) {
    8080                status = ADS_ERROR(LDAP_NO_MEMORY);
    8181                goto out;
    8282        }
    83         if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {
     83        if (((*OIDs_out) = talloc_array(mem_ctx, char *, *count)) == NULL) {
    8484                status = ADS_ERROR(LDAP_NO_MEMORY);
    8585                goto out;
     
    253253        }
    254254
    255         if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) {
     255        if ( (schema = talloc(mem_ctx, struct posix_schema)) == NULL ) {
    256256                TALLOC_FREE( ctx );
    257257                return ADS_ERROR(LDAP_NO_MEMORY);
  • vendor/current/source3/libads/ldap_utils.c

    r746 r988  
    2323#include "includes.h"
    2424#include "ads.h"
     25#include "lib/param/loadparm.h"
    2526
    2627#ifdef HAVE_LDAP
     
    3637                                             char ***strings,
    3738                                             size_t *num_strings,
    38                                              uint32 *first_usn,
     39                                             uint32_t *first_usn,
    3940                                             int *num_retries,
    4041                                             bool *more_values);
     
    8586        while (--count) {
    8687
    87                 if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && ads->config.ldap_page_size >= 250) {
     88                if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) &&
     89                    ads->config.ldap_page_size >= (lp_ldap_page_size() / 4) &&
     90                    lp_ldap_page_size() > 4) {
    8891                        int new_page_size = (ads->config.ldap_page_size / 2);
    8992                        DEBUG(1, ("Reducing LDAP page size from %d to %d due to IO_TIMEOUT\n",
     
    169172
    170173 ADS_STATUS ads_search_retry_dn_sd_flags(ADS_STRUCT *ads, LDAPMessage **res,
    171                                          uint32 sd_flags,
     174                                         uint32_t sd_flags,
    172175                                         const char *dn,
    173176                                         const char **attrs)
     
    214217        ADS_STATUS status;
    215218
    216         sid_string = sid_binstring_hex(sid);
     219        sid_string = sid_binstring_hex_talloc(talloc_tos(), sid);
    217220        if (sid_string == NULL) {
    218221                return ADS_ERROR(LDAP_NO_MEMORY);
     
    220223
    221224        if (!asprintf(&dn, "<SID=%s>", sid_string)) {
    222                 SAFE_FREE(sid_string);
     225                TALLOC_FREE(sid_string);
    223226                return ADS_ERROR(LDAP_NO_MEMORY);
    224227        }
     
    227230                                   "(objectclass=*)", attrs, res);
    228231        SAFE_FREE(dn);
    229         SAFE_FREE(sid_string);
     232        TALLOC_FREE(sid_string);
    230233        return status;
    231234}
     
    242245{
    243246        ADS_STATUS status;
    244         uint32 first_usn;
     247        uint32_t first_usn;
    245248        int num_retries = 0;
    246249        const char **attrs;
     
    250253        *strings = NULL;
    251254
    252         attrs = TALLOC_ARRAY(mem_ctx, const char *, 3);
     255        attrs = talloc_array(mem_ctx, const char *, 3);
    253256        ADS_ERROR_HAVE_NO_MEMORY(attrs);
    254257
     
    296299                                      char ***strings,
    297300                                      size_t *num_strings,
    298                                       uint32 *first_usn,
     301                                      uint32_t *first_usn,
    299302                                      int *num_retries,
    300303                                      bool *more_values)
     
    303306        ADS_STATUS status;
    304307        int count;
    305         uint32 current_usn;
     308        uint32_t current_usn;
    306309
    307310        DEBUG(10, ("Searching for attrs[0] = %s, attrs[1] = %s\n", attrs[0], attrs[1]));
  • vendor/current/source3/libads/ndr.c

    r740 r988  
    2323#include "ads.h"
    2424#include "../librpc/gen_ndr/ndr_netlogon.h"
    25 #include "librpc/ndr/util.h"
     25#include "../librpc/ndr/libndr.h"
     26#include "lib/param/loadparm.h"
    2627
    2728static void ndr_print_ads_auth_flags(struct ndr_print *ndr, const char *name, uint32_t r)
     
    3738        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_SASL_SEAL", ADS_AUTH_SASL_SEAL, r);
    3839        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_SASL_FORCE", ADS_AUTH_SASL_FORCE, r);
     40        ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_USER_CREDS", ADS_AUTH_USER_CREDS, r);
    3941        ndr->depth--;
    4042}
     
    5052        ndr_print_string(ndr, "workgroup", r->server.workgroup);
    5153        ndr_print_string(ndr, "ldap_server", r->server.ldap_server);
    52         ndr_print_bool(ndr, "foreign", r->server.foreign);
    5354        ndr->depth--;
    5455        ndr_print_struct(ndr, name, "auth");
  • 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
  • vendor/current/source3/libads/sasl_wrapping.c

    r740 r988  
    4646        ads->ldap.in.size       = 4 + ads->ldap.in.min_wrapped;
    4747        ads->ldap.in.buf        = talloc_array(ads->ldap.mem_ctx,
    48                                                uint8, ads->ldap.in.size);
     48                                               uint8_t, ads->ldap.in.size);
    4949        if (!ads->ldap.in.buf) {
    5050                return -1;
     
    6363        ads->ldap.in.buf        = talloc_realloc(ads->ldap.mem_ctx,
    6464                                                 ads->ldap.in.buf,
    65                                                  uint8, ads->ldap.in.size);
     65                                                 uint8_t, ads->ldap.in.size);
    6666        if (!ads->ldap.in.buf) {
    6767                return -1;
     
    172172}
    173173
    174 static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32 len)
     174static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32_t len)
    175175{
    176176        ads->ldap.out.ofs       = 0;
     
    178178        ads->ldap.out.size      = 4 + ads->ldap.out.sig_size + len;
    179179        ads->ldap.out.buf       = talloc_array(ads->ldap.mem_ctx,
    180                                                uint8, ads->ldap.out.size);
     180                                               uint8_t, ads->ldap.out.size);
    181181        if (!ads->ldap.out.buf) {
    182182                return -1;
     
    215215                if (ret < 0) return ret;
    216216               
    217                 status = ads->ldap.wrap_ops->wrap(ads, (uint8 *)buf, rlen);
     217                status = ads->ldap.wrap_ops->wrap(ads, (uint8_t *)buf, rlen);
    218218                if (!ADS_ERR_OK(status)) {
    219219                        errno = EACCES;
  • vendor/current/source3/libads/sitename_cache.c

    r740 r988  
    8080****************************************************************************/
    8181
    82 char *sitename_fetch(const char *realm)
     82char *sitename_fetch(TALLOC_CTX *mem_ctx, const char *realm)
    8383{
    8484        char *sitename = NULL;
     
    9696        key = sitename_key(query_realm);
    9797
    98         ret = gencache_get( key, &sitename, &timeout );
     98        ret = gencache_get( key, mem_ctx, &sitename, &timeout );
    9999        SAFE_FREE(key);
    100100        if ( !ret ) {
     
    123123        }
    124124
    125         new_sitename = sitename_fetch(realm);
     125        new_sitename = sitename_fetch(talloc_tos(), realm);
    126126
    127127        if (sitename && new_sitename && !strequal(sitename, new_sitename)) {
     
    131131                ret = True;
    132132        }
    133         SAFE_FREE(new_sitename);
     133        TALLOC_FREE(new_sitename);
    134134        return ret;
    135135}
  • vendor/current/source3/libads/sitename_cache.h

    r740 r988  
    2323
    2424bool sitename_store(const char *realm, const char *sitename);
    25 char *sitename_fetch(const char *realm);
     25char *sitename_fetch(TALLOC_CTX *mem_ctx, const char *realm);
    2626bool stored_sitename_changed(const char *realm, const char *sitename);
    2727
  • vendor/current/source3/libads/util.c

    r740 r988  
    3636        }
    3737
    38         new_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
    39    
     38        new_password = generate_random_password(talloc_tos(),
     39                                DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
     40                                DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
     41
    4042        ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
    4143
Note: See TracChangeset for help on using the changeset viewer.