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

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/kdc/pac-glue.c

    r740 r988  
    2727#include "auth/auth.h"
    2828#include "auth/auth_sam_reply.h"
    29 #include "kdc/kdc-glue.h"
     29#include "system/kerberos.h"
     30#include "auth/kerberos/kerberos.h"
     31#include "kdc/samba_kdc.h"
     32#include "kdc/pac-glue.h"
    3033#include "param/param.h"
    3134#include "librpc/gen_ndr/ndr_krb5pac.h"
     35#include "libcli/security/security.h"
     36#include "dsdb/samdb/samdb.h"
     37#include "auth/kerberos/pac_utils.h"
    3238
    3339static
     
    5157
    5258        pac_info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO);
    53         if (!mem_ctx) {
     59        if (!pac_info.logon_info.info) {
    5460                return NT_STATUS_NO_MEMORY;
    5561        }
     
    7278krb5_error_code samba_make_krb5_pac(krb5_context context,
    7379                                    DATA_BLOB *pac_blob,
     80                                    DATA_BLOB *deleg_blob,
    7481                                    krb5_pac *pac)
    7582{
    7683        krb5_data pac_data;
     84        krb5_data deleg_data;
    7785        krb5_error_code ret;
    7886
     
    8290        }
    8391
    84         ret = krb5_data_copy(&pac_data, pac_blob->data, pac_blob->length);
     92        ret = krb5_copy_data_contents(&pac_data,
     93                                      pac_blob->data,
     94                                      pac_blob->length);
    8595        if (ret != 0) {
    8696                return ret;
    8797        }
    8898
     99        ZERO_STRUCT(deleg_data);
     100        if (deleg_blob) {
     101                ret = krb5_copy_data_contents(&deleg_data,
     102                                              deleg_blob->data,
     103                                              deleg_blob->length);
     104                if (ret != 0) {
     105                        kerberos_free_data_contents(context, &pac_data);
     106                        return ret;
     107                }
     108        }
     109
    89110        ret = krb5_pac_init(context, pac);
    90111        if (ret != 0) {
    91                 krb5_data_free(&pac_data);
     112                kerberos_free_data_contents(context, &pac_data);
     113                kerberos_free_data_contents(context, &deleg_data);
    92114                return ret;
    93115        }
    94116
    95117        ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data);
    96         krb5_data_free(&pac_data);
     118        kerberos_free_data_contents(context, &pac_data);
    97119        if (ret != 0) {
     120                kerberos_free_data_contents(context, &deleg_data);
    98121                return ret;
    99122        }
    100123
     124        if (deleg_blob) {
     125                ret = krb5_pac_add_buffer(context, *pac,
     126                                          PAC_TYPE_CONSTRAINED_DELEGATION,
     127                                          &deleg_data);
     128                kerberos_free_data_contents(context, &deleg_data);
     129                if (ret != 0) {
     130                        return ret;
     131                }
     132        }
     133
    101134        return ret;
    102135}
    103136
    104 bool samba_princ_needs_pac(struct hdb_entry_ex *princ)
    105 {
    106 
    107         struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry);
     137bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry)
     138{
     139
    108140        uint32_t userAccountControl;
    109141
    110 
    111142        /* The service account may be set not to want the PAC */
    112         userAccountControl = ldb_msg_find_attr_as_uint(p->msg, "userAccountControl", 0);
     143        userAccountControl = ldb_msg_find_attr_as_uint(skdc_entry->msg, "userAccountControl", 0);
    113144        if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) {
    114145                return false;
     
    118149}
    119150
    120 /* Was the krbtgt an RODC (and we are not) */
    121 bool samba_krbtgt_was_untrusted_rodc(struct hdb_entry_ex *princ)
    122 {
    123 
    124         struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry);
    125         int rodc_krbtgt_number;
    126 
    127         /* Determine if this was printed by an RODC */
     151/* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */
     152int samba_krbtgt_is_in_db(struct samba_kdc_entry *p,
     153                          bool *is_in_db,
     154                          bool *is_untrusted)
     155{
     156        NTSTATUS status;
     157        int rodc_krbtgt_number, trust_direction;
     158        uint32_t rid;
     159
     160        TALLOC_CTX *mem_ctx = talloc_new(NULL);
     161        if (!mem_ctx) {
     162                return ENOMEM;
     163        }
     164       
     165        trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0);
     166
     167        if (trust_direction != 0) {
     168                /* Domain trust - we cannot check the sig, but we trust it for a correct PAC
     169                   
     170                   This is exactly where we should flag for SID
     171                   validation when we do inter-foreest trusts
     172                 */
     173                talloc_free(mem_ctx);
     174                *is_untrusted = false;
     175                *is_in_db = false;
     176                return 0;
     177        }
     178
     179        /* The lack of password controls etc applies to krbtgt by
     180         * virtue of being that particular RID */
     181        status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"), NULL, &rid);
     182
     183        if (!NT_STATUS_IS_OK(status)) {
     184                talloc_free(mem_ctx);
     185                return EINVAL;
     186        }
     187
    128188        rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1);
    129         if (rodc_krbtgt_number == -1) {
    130                 return false;
    131         } else if (rodc_krbtgt_number != p->kdc_db_ctx->my_krbtgt_number) {
    132                 return true;
    133         }
    134 
    135         return false;
     189
     190        if (p->kdc_db_ctx->my_krbtgt_number == 0) {
     191                if (rid == DOMAIN_RID_KRBTGT) {
     192                        *is_untrusted = false;
     193                        *is_in_db = true;
     194                        talloc_free(mem_ctx);
     195                        return 0;
     196                } else if (rodc_krbtgt_number != -1) {
     197                        *is_in_db = true;
     198                        *is_untrusted = true;
     199                        talloc_free(mem_ctx);
     200                        return 0;
     201                }
     202        } else if ((rid != DOMAIN_RID_KRBTGT) && (rodc_krbtgt_number == p->kdc_db_ctx->my_krbtgt_number)) {
     203                talloc_free(mem_ctx);
     204                *is_untrusted = false;
     205                *is_in_db = true;
     206                return 0;
     207        } else if (rid == DOMAIN_RID_KRBTGT) {
     208                /* krbtgt viewed from an RODC */
     209                talloc_free(mem_ctx);
     210                *is_untrusted = false;
     211                *is_in_db = false;
     212                return 0;
     213        }
     214
     215        /* Another RODC */
     216        talloc_free(mem_ctx);
     217        *is_untrusted = true;
     218        *is_in_db = false;
     219        return 0;
    136220}
    137221
    138222NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx,
    139                                 struct hdb_entry_ex *client,
     223                                struct samba_kdc_entry *p,
    140224                                DATA_BLOB **_pac_blob)
    141225{
    142         struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry);
    143226        struct auth_user_info_dc *user_info_dc;
    144227        DATA_BLOB *pac_blob;
     
    146229
    147230        /* The user account may be set not to want the PAC */
    148         if ( ! samba_princ_needs_pac(client)) {
     231        if ( ! samba_princ_needs_pac(p)) {
    149232                *_pac_blob = NULL;
    150233                return NT_STATUS_OK;
     
    183266NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx,
    184267                                   krb5_context context,
    185                                    krb5_pac *pac, DATA_BLOB *pac_blob)
     268                                   const krb5_pac pac, DATA_BLOB *pac_blob,
     269                                   struct PAC_SIGNATURE_DATA *pac_srv_sig,
     270                                   struct PAC_SIGNATURE_DATA *pac_kdc_sig)
    186271{
    187272        struct auth_user_info_dc *user_info_dc;
     
    189274        NTSTATUS nt_status;
    190275
    191         ret = kerberos_pac_to_user_info_dc(mem_ctx, *pac,
    192                                            context, &user_info_dc, NULL, NULL);
     276        ret = kerberos_pac_to_user_info_dc(mem_ctx, pac,
     277                                           context, &user_info_dc, pac_srv_sig, pac_kdc_sig);
    193278        if (ret) {
    194279                return NT_STATUS_UNSUCCESSFUL;
     
    201286}
    202287
    203 /* this function allocates 'data' using malloc.
    204  * The caller is responsible for freeing it */
    205 void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data)
    206 {
    207         PA_DATA pa;
    208         unsigned char *buf;
    209         size_t len;
    210         krb5_error_code ret = 0;
    211 
    212         if (!e_data)
    213                 return;
    214 
    215         pa.padata_type          = KRB5_PADATA_PW_SALT;
    216         pa.padata_value.length  = 12;
    217         pa.padata_value.data    = malloc(pa.padata_value.length);
    218         if (!pa.padata_value.data) {
    219                 e_data->length = 0;
    220                 e_data->data = NULL;
    221                 return;
    222         }
    223 
    224         SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status));
    225         SIVAL(pa.padata_value.data, 4, 0);
    226         SIVAL(pa.padata_value.data, 8, 1);
    227 
    228         ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret);
    229         free(pa.padata_value.data);
    230 
    231         e_data->data   = buf;
    232         e_data->length = len;
    233 
    234         return;
     288NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx,
     289                                krb5_context context,
     290                                const krb5_pac pac,
     291                                const krb5_principal server_principal,
     292                                const krb5_principal proxy_principal,
     293                                DATA_BLOB *new_blob)
     294{
     295        krb5_data old_data;
     296        DATA_BLOB old_blob;
     297        krb5_error_code ret;
     298        NTSTATUS nt_status;
     299        enum ndr_err_code ndr_err;
     300        union PAC_INFO info;
     301        struct PAC_CONSTRAINED_DELEGATION _d;
     302        struct PAC_CONSTRAINED_DELEGATION *d = NULL;
     303        char *server = NULL;
     304        char *proxy = NULL;
     305        uint32_t i;
     306        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     307
     308        if (tmp_ctx == NULL) {
     309                return NT_STATUS_NO_MEMORY;
     310        }
     311
     312        ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data);
     313        if (ret == ENOENT) {
     314                ZERO_STRUCT(old_data);
     315        } else if (ret) {
     316                talloc_free(tmp_ctx);
     317                return NT_STATUS_UNSUCCESSFUL;
     318        }
     319
     320        old_blob.length = old_data.length;
     321        old_blob.data = (uint8_t *)old_data.data;
     322
     323        ZERO_STRUCT(info);
     324        if (old_blob.length > 0) {
     325                ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx,
     326                                &info, PAC_TYPE_CONSTRAINED_DELEGATION,
     327                                (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO);
     328                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     329                        kerberos_free_data_contents(context, &old_data);
     330                        nt_status = ndr_map_error2ntstatus(ndr_err);
     331                        DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
     332                        talloc_free(tmp_ctx);
     333                        return nt_status;
     334                }
     335        } else {
     336                ZERO_STRUCT(_d);
     337                info.constrained_delegation.info = &_d;
     338        }
     339        kerberos_free_data_contents(context, &old_data);
     340
     341        ret = krb5_unparse_name(context, server_principal, &server);
     342        if (ret) {
     343                talloc_free(tmp_ctx);
     344                return NT_STATUS_INTERNAL_ERROR;
     345        }
     346
     347        ret = krb5_unparse_name_flags(context, proxy_principal,
     348                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &proxy);
     349        if (ret) {
     350                SAFE_FREE(server);
     351                talloc_free(tmp_ctx);
     352                return NT_STATUS_INTERNAL_ERROR;
     353        }
     354
     355        d = info.constrained_delegation.info;
     356        i = d->num_transited_services;
     357        d->proxy_target.string = server;
     358        d->transited_services = talloc_realloc(mem_ctx, d->transited_services,
     359                                               struct lsa_String, i + 1);
     360        d->transited_services[i].string = proxy;
     361        d->num_transited_services = i + 1;
     362
     363        ndr_err = ndr_push_union_blob(new_blob, mem_ctx,
     364                                &info, PAC_TYPE_CONSTRAINED_DELEGATION,
     365                                (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
     366        SAFE_FREE(server);
     367        SAFE_FREE(proxy);
     368        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     369                kerberos_free_data_contents(context, &old_data);
     370                nt_status = ndr_map_error2ntstatus(ndr_err);
     371                DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status)));
     372                talloc_free(tmp_ctx);
     373                return nt_status;
     374        }
     375
     376        talloc_free(tmp_ctx);
     377        return NT_STATUS_OK;
    235378}
    236379
     
    241384
    242385        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE))
    243                 ret = KRB5KDC_ERR_KEY_EXPIRED;
     386                ret = KRB5KDC_ERR_KEY_EXP;
    244387        else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED))
    245                 ret = KRB5KDC_ERR_KEY_EXPIRED;
     388                ret = KRB5KDC_ERR_KEY_EXP;
    246389        else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED))
    247390                ret = KRB5KDC_ERR_CLIENT_REVOKED;
     
    287430        return nt_status;
    288431}
    289 
Note: See TracChangeset for help on using the changeset viewer.