Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/libads/kerberos_keytab.c

    r414 r745  
    2828#include "includes.h"
    2929#include "smb_krb5.h"
     30#include "ads.h"
     31#include "secrets.h"
    3032
    3133#ifdef HAVE_KRB5
     
    3436**********************************************************************/
    3537
    36 int smb_krb5_kt_add_entry_ext(krb5_context context,
    37                               krb5_keytab keytab,
    38                               krb5_kvno kvno,
    39                               const char *princ_s,
    40                               krb5_enctype *enctypes,
    41                               krb5_data password,
    42                               bool no_salt,
    43                               bool keep_old_entries)
     38static krb5_error_code seek_and_delete_old_entries(krb5_context context,
     39                                                   krb5_keytab keytab,
     40                                                   krb5_kvno kvno,
     41                                                   const char *princ_s,
     42                                                   krb5_principal princ,
     43                                                   bool flush,
     44                                                   bool keep_old_entries)
    4445{
    45         krb5_error_code ret = 0;
     46        krb5_error_code ret;
    4647        krb5_kt_cursor cursor;
     48        krb5_kt_cursor zero_csr;
    4749        krb5_keytab_entry kt_entry;
    48         krb5_principal princ = NULL;
    49         int i;
     50        krb5_keytab_entry zero_kt_entry;
    5051        char *ktprinc = NULL;
    5152
     53        ZERO_STRUCT(cursor);
     54        ZERO_STRUCT(zero_csr);
    5255        ZERO_STRUCT(kt_entry);
    53         ZERO_STRUCT(cursor);
    54        
    55         ret = smb_krb5_parse_name(context, princ_s, &princ);
    56         if (ret) {
    57                 DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
    58                 goto out;
    59         }
    60 
    61         /* Seek and delete old keytab entries */
     56        ZERO_STRUCT(zero_kt_entry);
     57
    6258        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    63         if (ret != KRB5_KT_END && ret != ENOENT ) {
    64                 DEBUG(3,("smb_krb5_kt_add_entry_ext: Will try to delete old keytab entries\n"));
    65                 while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
    66                         bool compare_name_ok = False;
    67 
    68                         ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &ktprinc);
     59        if (ret == KRB5_KT_END || ret == ENOENT ) {
     60                /* no entries */
     61                return 0;
     62        }
     63
     64        DEBUG(3, (__location__ ": Will try to delete old keytab entries\n"));
     65        while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
     66                bool name_ok = False;
     67
     68                if (!flush && (princ_s != NULL)) {
     69                        ret = smb_krb5_unparse_name(talloc_tos(), context,
     70                                                    kt_entry.principal,
     71                                                    &ktprinc);
    6972                        if (ret) {
    70                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_unparse_name failed (%s)\n",
    71                                         error_message(ret)));
     73                                DEBUG(1, (__location__
     74                                          ": smb_krb5_unparse_name failed "
     75                                          "(%s)\n", error_message(ret)));
    7276                                goto out;
    7377                        }
    7478
    75                         /*---------------------------------------------------------------------------
    76                          * Save the entries with kvno - 1.   This is what microsoft does
    77                          * to allow people with existing sessions that have kvno - 1 to still
    78                          * work.   Otherwise, when the password for the machine changes, all
    79                          * kerberizied sessions will 'break' until either the client reboots or
    80                          * the client's session key expires and they get a new session ticket
    81                          * with the new kvno.
    82                          */
    83 
    8479#ifdef HAVE_KRB5_KT_COMPARE
    85                         compare_name_ok = (krb5_kt_compare(context, &kt_entry, princ, 0, 0) == True);
     80                        name_ok = krb5_kt_compare(context, &kt_entry,
     81                                                  princ, 0, 0);
    8682#else
    87                         compare_name_ok = (strcmp(ktprinc, princ_s) == 0);
     83                        name_ok = (strcmp(ktprinc, princ_s) == 0);
    8884#endif
    8985
    90                         if (!compare_name_ok) {
    91                                 DEBUG(10,("smb_krb5_kt_add_entry_ext: ignoring keytab entry principal %s, kvno = %d\n",
    92                                         ktprinc, kt_entry.vno));
     86                        if (!name_ok) {
     87                                DEBUG(10, (__location__ ": ignoring keytab "
     88                                           "entry principal %s, kvno = %d\n",
     89                                           ktprinc, kt_entry.vno));
     90
     91                                /* Not a match,
     92                                 * just free this entry and continue. */
     93                                ret = smb_krb5_kt_free_entry(context,
     94                                                             &kt_entry);
     95                                ZERO_STRUCT(kt_entry);
     96                                if (ret) {
     97                                        DEBUG(1, (__location__
     98                                                  ": smb_krb5_kt_free_entry "
     99                                                  "failed (%s)\n",
     100                                                  error_message(ret)));
     101                                        goto out;
     102                                }
     103
     104                                TALLOC_FREE(ktprinc);
     105                                continue;
    93106                        }
    94107
    95108                        TALLOC_FREE(ktprinc);
    96 
    97                         if (compare_name_ok) {
    98                                 if (kt_entry.vno == kvno - 1) {
    99                                         DEBUG(5,("smb_krb5_kt_add_entry_ext: Saving previous (kvno %d) entry for principal: %s.\n",
    100                                                 kvno - 1, princ_s));
    101                                 } else if (!keep_old_entries) {
    102                                         DEBUG(5,("smb_krb5_kt_add_entry_ext: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
    103                                                 princ_s, kt_entry.vno));
    104                                         ret = krb5_kt_end_seq_get(context, keytab, &cursor);
    105                                         ZERO_STRUCT(cursor);
    106                                         if (ret) {
    107                                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_end_seq_get() failed (%s)\n",
    108                                                         error_message(ret)));
    109                                                 goto out;
    110                                         }
    111                                         ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
    112                                         if (ret) {
    113                                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_remove_entry failed (%s)\n",
    114                                                         error_message(ret)));
    115                                                 goto out;
    116                                         }
    117 
    118                                         DEBUG(5,("smb_krb5_kt_add_entry_ext: removed old entry for principal: %s (kvno %d).\n",
    119                                                 princ_s, kt_entry.vno));
    120 
    121                                         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    122                                         if (ret) {
    123                                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_start_seq failed (%s)\n",
    124                                                         error_message(ret)));
    125                                                 goto out;
    126                                         }
    127                                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
    128                                         ZERO_STRUCT(kt_entry);
    129                                         if (ret) {
    130                                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_remove_entry failed (%s)\n",
    131                                                         error_message(ret)));
    132                                                 goto out;
    133                                         }
    134                                         continue;
    135                                 }
    136                         }
    137 
    138                         /* Not a match, just free this entry and continue. */
    139                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
    140                         ZERO_STRUCT(kt_entry);
    141                         if (ret) {
    142                                 DEBUG(1,("smb_krb5_kt_add_entry_ext: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
    143                                 goto out;
    144                         }
    145                 }
     109                }
     110
     111                /*------------------------------------------------------------
     112                 * Save the entries with kvno - 1. This is what microsoft does
     113                 * to allow people with existing sessions that have kvno - 1
     114                 * to still work. Otherwise, when the password for the machine
     115                 * changes, all kerberizied sessions will 'break' until either
     116                 * the client reboots or the client's session key expires and
     117                 * they get a new session ticket with the new kvno.
     118                 */
     119
     120                if (!flush && (kt_entry.vno == kvno - 1)) {
     121                        DEBUG(5, (__location__ ": Saving previous (kvno %d) "
     122                                  "entry for principal: %s.\n",
     123                                  kvno - 1, princ_s));
     124                        continue;
     125                }
     126
     127                if (keep_old_entries) {
     128                        DEBUG(5, (__location__ ": Saving old (kvno %d) "
     129                                  "entry for principal: %s.\n",
     130                                  kvno, princ_s));
     131                        continue;
     132                }
     133
     134                DEBUG(5, (__location__ ": Found old entry for principal: %s "
     135                          "(kvno %d) - trying to remove it.\n",
     136                          princ_s, kt_entry.vno));
    146137
    147138                ret = krb5_kt_end_seq_get(context, keytab, &cursor);
    148139                ZERO_STRUCT(cursor);
    149140                if (ret) {
    150                         DEBUG(1,("smb_krb5_kt_add_entry_ext: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
    151                         goto out;
    152                 }
    153         }
    154 
    155         /* Ensure we don't double free. */
    156         ZERO_STRUCT(kt_entry);
    157         ZERO_STRUCT(cursor);
    158 
    159         /* If we get here, we have deleted all the old entries with kvno's not equal to the current kvno-1. */
    160 
    161         /* Now add keytab entries for all encryption types */
    162         for (i = 0; enctypes[i]; i++) {
    163                 krb5_keyblock *keyp;
    164 
    165                 keyp = KRB5_KT_KEY(&kt_entry);
    166 
    167                 if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i], no_salt)) {
    168                         continue;
    169                 }
    170 
    171                 kt_entry.principal = princ;
    172                 kt_entry.vno       = kvno;
    173 
    174                 DEBUG(3,("smb_krb5_kt_add_entry_ext: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
    175                         princ_s, enctypes[i], kt_entry.vno));
    176                 ret = krb5_kt_add_entry(context, keytab, &kt_entry);
    177                 krb5_free_keyblock_contents(context, keyp);
     141                        DEBUG(1, (__location__ ": krb5_kt_end_seq_get() "
     142                                  "failed (%s)\n", error_message(ret)));
     143                        goto out;
     144                }
     145                ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
     146                if (ret) {
     147                        DEBUG(1, (__location__ ": krb5_kt_remove_entry() "
     148                                  "failed (%s)\n", error_message(ret)));
     149                        goto out;
     150                }
     151
     152                DEBUG(5, (__location__ ": removed old entry for principal: "
     153                          "%s (kvno %d).\n", princ_s, kt_entry.vno));
     154
     155                ret = krb5_kt_start_seq_get(context, keytab, &cursor);
     156                if (ret) {
     157                        DEBUG(1, (__location__ ": krb5_kt_start_seq() failed "
     158                                  "(%s)\n", error_message(ret)));
     159                        goto out;
     160                }
     161                ret = smb_krb5_kt_free_entry(context, &kt_entry);
    178162                ZERO_STRUCT(kt_entry);
    179163                if (ret) {
    180                         DEBUG(1,("smb_krb5_kt_add_entry_ext: adding entry to keytab failed (%s)\n", error_message(ret)));
    181                         goto out;
    182                 }
    183         }
    184 
     164                        DEBUG(1, (__location__ ": krb5_kt_remove_entry() "
     165                                  "failed (%s)\n", error_message(ret)));
     166                        goto out;
     167                }
     168        }
    185169
    186170out:
    187         {
    188                 krb5_keytab_entry zero_kt_entry;
    189                 ZERO_STRUCT(zero_kt_entry);
    190                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
    191                         smb_krb5_kt_free_entry(context, &kt_entry);
    192                 }
    193         }
    194         if (princ) {
    195                 krb5_free_principal(context, princ);
    196         }
    197        
    198         {
    199                 krb5_kt_cursor zero_csr;
    200                 ZERO_STRUCT(zero_csr);
    201                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
    202                         krb5_kt_end_seq_get(context, keytab, &cursor); 
    203                 }
    204         }
    205        
    206         return (int)ret;
     171        if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
     172                smb_krb5_kt_free_entry(context, &kt_entry);
     173        }
     174        if (keytab) {
     175                if (memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) {
     176                        krb5_kt_end_seq_get(context, keytab, &cursor);
     177                }
     178        }
     179
     180        return ret;
    207181}
    208182
     
    212186                                 const char *princ_s,
    213187                                 krb5_enctype *enctypes,
    214                                  krb5_data password)
     188                                 krb5_data password,
     189                                 bool no_salt,
     190                                 bool keep_old_entries)
    215191{
    216         return smb_krb5_kt_add_entry_ext(context,
    217                                          keytab,
    218                                          kvno,
    219                                          princ_s,
    220                                          enctypes,
    221                                          password,
    222                                          false,
    223                                          false);
     192        krb5_error_code ret;
     193        krb5_keytab_entry kt_entry;
     194        krb5_principal princ = NULL;
     195        int i;
     196
     197        ZERO_STRUCT(kt_entry);
     198
     199        ret = smb_krb5_parse_name(context, princ_s, &princ);
     200        if (ret) {
     201                DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) "
     202                          "failed (%s)\n", princ_s, error_message(ret)));
     203                goto out;
     204        }
     205
     206        /* Seek and delete old keytab entries */
     207        ret = seek_and_delete_old_entries(context, keytab, kvno,
     208                                          princ_s, princ, false,
     209                                          keep_old_entries);
     210        if (ret) {
     211                goto out;
     212        }
     213
     214        /* If we get here, we have deleted all the old entries with kvno's
     215         * not equal to the current kvno-1. */
     216
     217        /* Now add keytab entries for all encryption types */
     218        for (i = 0; enctypes[i]; i++) {
     219                krb5_keyblock *keyp;
     220
     221                keyp = KRB5_KT_KEY(&kt_entry);
     222
     223                if (create_kerberos_key_from_string(context, princ,
     224                                                    &password, keyp,
     225                                                    enctypes[i], no_salt)) {
     226                        continue;
     227                }
     228
     229                kt_entry.principal = princ;
     230                kt_entry.vno       = kvno;
     231
     232                DEBUG(3, (__location__ ": adding keytab entry for (%s) with "
     233                          "encryption type (%d) and version (%d)\n",
     234                          princ_s, enctypes[i], kt_entry.vno));
     235                ret = krb5_kt_add_entry(context, keytab, &kt_entry);
     236                krb5_free_keyblock_contents(context, keyp);
     237                ZERO_STRUCT(kt_entry);
     238                if (ret) {
     239                        DEBUG(1, (__location__ ": adding entry to keytab "
     240                                  "failed (%s)\n", error_message(ret)));
     241                        goto out;
     242                }
     243        }
     244
     245out:
     246        if (princ) {
     247                krb5_free_principal(context, princ);
     248        }
     249
     250        return (int)ret;
    224251}
    225252
     
    235262        krb5_data password;
    236263        krb5_kvno kvno;
    237         krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, 0, 0 };
    238         char *princ_s = NULL, *short_princ_s = NULL;
     264        krb5_enctype enctypes[4] = {
     265                ENCTYPE_DES_CBC_CRC,
     266                ENCTYPE_DES_CBC_MD5,
     267                ENCTYPE_ARCFOUR_HMAC,
     268                0
     269        };
     270        char *princ_s = NULL;
     271        char *short_princ_s = NULL;
    239272        char *password_s = NULL;
    240273        char *my_fqdn;
    241         TALLOC_CTX *ctx = NULL;
     274        TALLOC_CTX *tmpctx = NULL;
    242275        char *machine_name;
    243 
    244 #if defined(ENCTYPE_ARCFOUR_HMAC)
    245         enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
    246 #endif
     276        ADS_STATUS aderr;
    247277
    248278        initialize_krb5_error_table();
    249279        ret = krb5_init_context(&context);
    250280        if (ret) {
    251                 DEBUG(1,("ads_keytab_add_entry: could not krb5_init_context: %s\n",error_message(ret)));
     281                DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
     282                          error_message(ret)));
    252283                return -1;
    253284        }
     
    255286        ret = smb_krb5_open_keytab(context, NULL, True, &keytab);
    256287        if (ret) {
    257                 DEBUG(1,("ads_keytab_add_entry: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
     288                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     289                          error_message(ret)));
    258290                goto out;
    259291        }
     
    261293        /* retrieve the password */
    262294        if (!secrets_init()) {
    263                 DEBUG(1,("ads_keytab_add_entry: secrets_init failed\n"));
     295                DEBUG(1, (__location__ ": secrets_init failed\n"));
    264296                ret = -1;
    265297                goto out;
     
    267299        password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
    268300        if (!password_s) {
    269                 DEBUG(1,("ads_keytab_add_entry: failed to fetch machine password\n"));
     301                DEBUG(1, (__location__ ": failed to fetch machine password\n"));
    270302                ret = -1;
    271303                goto out;
     
    276308
    277309        /* we need the dNSHostName value here */
    278        
    279         if ( (ctx = talloc_init("ads_keytab_add_entry")) == NULL ) {
    280                 DEBUG(0,("ads_keytab_add_entry: talloc() failed!\n"));
    281                 ret = -1;
    282                 goto out;
    283         }
    284        
    285         if ( (my_fqdn = ads_get_dnshostname( ads, ctx, global_myname())) == NULL ) {
    286                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's dns name in AD!\n"));
    287                 ret = -1;
    288                 goto out;       
    289         }
    290        
    291         if ( (machine_name = ads_get_samaccountname( ads, ctx, global_myname())) == NULL ) {
    292                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's short name in AD!\n"));
    293                 ret = -1;
    294                 goto out;       
     310        tmpctx = talloc_init(__location__);
     311        if (!tmpctx) {
     312                DEBUG(0, (__location__ ": talloc_init() failed!\n"));
     313                ret = -1;
     314                goto out;
     315        }
     316
     317        my_fqdn = ads_get_dnshostname(ads, tmpctx, global_myname());
     318        if (!my_fqdn) {
     319                DEBUG(0, (__location__ ": unable to determine machine "
     320                          "account's dns name in AD!\n"));
     321                ret = -1;
     322                goto out;
     323        }
     324
     325        machine_name = ads_get_samaccountname(ads, tmpctx, global_myname());
     326        if (!machine_name) {
     327                DEBUG(0, (__location__ ": unable to determine machine "
     328                          "account's short name in AD!\n"));
     329                ret = -1;
     330                goto out;
    295331        }
    296332        /*strip the trailing '$' */
    297333        machine_name[strlen(machine_name)-1] = '\0';
    298                
     334
    299335        /* Construct our principal */
    300 
    301336        if (strchr_m(srvPrinc, '@')) {
    302337                /* It's a fully-named principal. */
    303                 if (asprintf(&princ_s, "%s", srvPrinc) == -1) {
     338                princ_s = talloc_asprintf(tmpctx, "%s", srvPrinc);
     339                if (!princ_s) {
    304340                        ret = -1;
    305341                        goto out;
     
    307343        } else if (srvPrinc[strlen(srvPrinc)-1] == '$') {
    308344                /* It's the machine account, as used by smbclient clients. */
    309                 if (asprintf(&princ_s, "%s@%s", srvPrinc, lp_realm()) == -1) {
     345                princ_s = talloc_asprintf(tmpctx, "%s@%s",
     346                                          srvPrinc, lp_realm());
     347                if (!princ_s) {
    310348                        ret = -1;
    311349                        goto out;
     
    315353                 * can obtain credentials for it and double-check the salt value
    316354                 * used to generate the service's keys. */
    317                  
    318                 if (asprintf(&princ_s, "%s/%s@%s", srvPrinc, my_fqdn, lp_realm()) == -1) {
     355
     356                princ_s = talloc_asprintf(tmpctx, "%s/%s@%s",
     357                                          srvPrinc, my_fqdn, lp_realm());
     358                if (!princ_s) {
    319359                        ret = -1;
    320360                        goto out;
    321361                }
    322                 if (asprintf(&short_princ_s, "%s/%s@%s", srvPrinc, machine_name, lp_realm()) == -1) {
     362                short_princ_s = talloc_asprintf(tmpctx, "%s/%s@%s",
     363                                                srvPrinc, machine_name,
     364                                                lp_realm());
     365                if (!princ_s) {
    323366                        ret = -1;
    324367                        goto out;
    325368                }
    326                
    327                 /* According to http://support.microsoft.com/kb/326985/en-us,
    328                    certain principal names are automatically mapped to the host/...
    329                    principal in the AD account.  So only create these in the
    330                    keytab, not in AD.  --jerry */
    331                    
    332                 if ( !strequal( srvPrinc, "cifs" ) && !strequal(srvPrinc, "host" ) ) {
    333                         DEBUG(3,("ads_keytab_add_entry: Attempting to add/update '%s'\n", princ_s));
    334                        
    335                         if (!ADS_ERR_OK(ads_add_service_principal_name(ads, global_myname(), my_fqdn, srvPrinc))) {
    336                                 DEBUG(1,("ads_keytab_add_entry: ads_add_service_principal_name failed.\n"));
     369
     370                /* According to http://support.microsoft.com/kb/326985/en-us,
     371                   certain principal names are automatically mapped to the
     372                   host/... principal in the AD account.
     373                   So only create these in the keytab, not in AD.  --jerry */
     374
     375                if (!strequal(srvPrinc, "cifs") &&
     376                    !strequal(srvPrinc, "host")) {
     377                        DEBUG(3, (__location__ ": Attempting to add/update "
     378                                  "'%s'\n", princ_s));
     379
     380                        aderr = ads_add_service_principal_name(ads,
     381                                        global_myname(), my_fqdn, srvPrinc);
     382                        if (!ADS_ERR_OK(aderr)) {
     383                                DEBUG(1, (__location__ ": failed to "
     384                                         "ads_add_service_principal_name.\n"));
    337385                                goto out;
    338386                        }
     
    340388        }
    341389
    342         kvno = (krb5_kvno) ads_get_machine_kvno(ads, global_myname());
    343         if (kvno == -1) {       /* -1 indicates failure, everything else is OK */
    344                 DEBUG(1,("ads_keytab_add_entry: ads_get_machine_kvno failed to determine the system's kvno.\n"));
    345                 ret = -1;
    346                 goto out;
    347         }
    348        
     390        kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());
     391        if (kvno == -1) {
     392                /* -1 indicates failure, everything else is OK */
     393                DEBUG(1, (__location__ ": ads_get_machine_kvno failed to "
     394                         "determine the system's kvno.\n"));
     395                ret = -1;
     396                goto out;
     397        }
     398
    349399        /* add the fqdn principal to the keytab */
    350        
    351         ret = smb_krb5_kt_add_entry( context, keytab, kvno, princ_s, enctypes, password );
    352         if ( ret ) {
    353                 DEBUG(1,("ads_keytab_add_entry: Failed to add entry to keytab file\n"));
    354                 goto out;
    355         }
    356        
     400        ret = smb_krb5_kt_add_entry(context, keytab, kvno,
     401                                    princ_s, enctypes, password,
     402                                    false, false);
     403        if (ret) {
     404                DEBUG(1, (__location__ ": Failed to add entry to keytab\n"));
     405                goto out;
     406        }
     407
    357408        /* add the short principal name if we have one */
    358        
    359         if ( short_princ_s ) {
    360                 ret = smb_krb5_kt_add_entry( context, keytab, kvno, short_princ_s, enctypes, password );
    361                 if ( ret ) {
    362                         DEBUG(1,("ads_keytab_add_entry: Failed to add short entry to keytab file\n"));
     409        if (short_princ_s) {
     410                ret = smb_krb5_kt_add_entry(context, keytab, kvno,
     411                                            short_princ_s, enctypes, password,
     412                                            false, false);
     413                if (ret) {
     414                        DEBUG(1, (__location__
     415                                  ": Failed to add short entry to keytab\n"));
    363416                        goto out;
    364417                }
     
    366419
    367420out:
    368         SAFE_FREE( princ_s );
    369         SAFE_FREE( short_princ_s );
    370         TALLOC_FREE( ctx );
    371        
     421        TALLOC_FREE(tmpctx);
     422
    372423        if (keytab) {
    373424                krb5_kt_close(context, keytab);
     
    388439        krb5_context context = NULL;
    389440        krb5_keytab keytab = NULL;
    390         krb5_kt_cursor cursor;
    391         krb5_keytab_entry kt_entry;
    392441        krb5_kvno kvno;
    393 
    394         ZERO_STRUCT(kt_entry);
    395         ZERO_STRUCT(cursor);
     442        ADS_STATUS aderr;
    396443
    397444        initialize_krb5_error_table();
    398445        ret = krb5_init_context(&context);
    399446        if (ret) {
    400                 DEBUG(1,("ads_keytab_flush: could not krb5_init_context: %s\n",error_message(ret)));
     447                DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
     448                          error_message(ret)));
    401449                return ret;
    402450        }
     
    404452        ret = smb_krb5_open_keytab(context, NULL, True, &keytab);
    405453        if (ret) {
    406                 DEBUG(1,("ads_keytab_flush: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
    407                 goto out;
    408         }
    409 
    410         kvno = (krb5_kvno) ads_get_machine_kvno(ads, global_myname());
    411         if (kvno == -1) {       /* -1 indicates a failure */
    412                 DEBUG(1,("ads_keytab_flush: Error determining the system's kvno.\n"));
    413                 goto out;
    414         }
    415 
    416         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    417         if (ret != KRB5_KT_END && ret != ENOENT) {
    418                 while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
    419                         ret = krb5_kt_end_seq_get(context, keytab, &cursor);
    420                         ZERO_STRUCT(cursor);
    421                         if (ret) {
    422                                 DEBUG(1,("ads_keytab_flush: krb5_kt_end_seq_get() failed (%s)\n",error_message(ret)));
    423                                 goto out;
    424                         }
    425                         ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
    426                         if (ret) {
    427                                 DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
    428                                 goto out;
    429                         }
    430                         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    431                         if (ret) {
    432                                 DEBUG(1,("ads_keytab_flush: krb5_kt_start_seq failed (%s)\n",error_message(ret)));
    433                                 goto out;
    434                         }
    435                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
    436                         ZERO_STRUCT(kt_entry);
    437                         if (ret) {
    438                                 DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
    439                                 goto out;
    440                         }
    441                 }
    442         }
    443 
    444         /* Ensure we don't double free. */
    445         ZERO_STRUCT(kt_entry);
    446         ZERO_STRUCT(cursor);
    447 
    448         if (!ADS_ERR_OK(ads_clear_service_principal_names(ads, global_myname()))) {
    449                 DEBUG(1,("ads_keytab_flush: Error while clearing service principal listings in LDAP.\n"));
     454                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     455                          error_message(ret)));
     456                goto out;
     457        }
     458
     459        kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());
     460        if (kvno == -1) {
     461                /* -1 indicates a failure */
     462                DEBUG(1, (__location__ ": Error determining the kvno.\n"));
     463                goto out;
     464        }
     465
     466        /* Seek and delete old keytab entries */
     467        ret = seek_and_delete_old_entries(context, keytab, kvno,
     468                                          NULL, NULL, true, false);
     469        if (ret) {
     470                goto out;
     471        }
     472
     473        aderr = ads_clear_service_principal_names(ads, global_myname());
     474        if (!ADS_ERR_OK(aderr)) {
     475                DEBUG(1, (__location__ ": Error while clearing service "
     476                          "principal listings in LDAP.\n"));
    450477                goto out;
    451478        }
    452479
    453480out:
    454 
    455         {
    456                 krb5_keytab_entry zero_kt_entry;
    457                 ZERO_STRUCT(zero_kt_entry);
    458                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
    459                         smb_krb5_kt_free_entry(context, &kt_entry);
    460                 }
    461         }
    462         {
    463                 krb5_kt_cursor zero_csr;
    464                 ZERO_STRUCT(zero_csr);
    465                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
    466                         krb5_kt_end_seq_get(context, keytab, &cursor); 
    467                 }
    468         }
    469481        if (keytab) {
    470482                krb5_kt_close(context, keytab);
     
    491503        char *sam_account_name, *upn;
    492504        char **oldEntries = NULL, *princ_s[26];
    493         TALLOC_CTX *ctx = NULL;
    494         fstring machine_name;
     505        TALLOC_CTX *tmpctx = NULL;
     506        char *machine_name;
     507
     508        /* these are the main ones we need */
     509        ret = ads_keytab_add_entry(ads, "host");
     510        if (ret != 0) {
     511                DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
     512                          "adding 'host' principal.\n"));
     513                return ret;
     514        }
     515
     516
     517#if 0   /* don't create the CIFS/... keytab entries since no one except smbd
     518           really needs them and we will fall back to verifying against
     519           secrets.tdb */
     520
     521        ret = ads_keytab_add_entry(ads, "cifs"));
     522        if (ret != 0 ) {
     523                DEBUG(1, (__location__ ": ads_keytab_add_entry failed while "
     524                          "adding 'cifs'.\n"));
     525                return ret;
     526        }
     527#endif
    495528
    496529        memset(princ_s, '\0', sizeof(princ_s));
    497 
    498         fstrcpy( machine_name, global_myname() );
    499 
    500         /* these are the main ones we need */
    501        
    502         if ( (ret = ads_keytab_add_entry(ads, "host") ) != 0 ) {
    503                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'host'.\n"));
    504                 return ret;
    505         }
    506 
    507 
    508 #if 0   /* don't create the CIFS/... keytab entries since no one except smbd
    509            really needs them and we will fall back to verifying against secrets.tdb */
    510            
    511         if ( (ret = ads_keytab_add_entry(ads, "cifs")) != 0 ) {
    512                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'cifs'.\n"));
    513                 return ret;
    514         }
    515 #endif
    516 
    517         if ( (ctx = talloc_init("ads_keytab_create_default")) == NULL ) {
    518                 DEBUG(0,("ads_keytab_create_default: talloc() failed!\n"));
    519                 return -1;
    520         }
    521 
    522         /* now add the userPrincipalName and sAMAccountName entries */
    523 
    524         if ( (sam_account_name = ads_get_samaccountname( ads, ctx, machine_name)) == NULL ) {
    525                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's name in AD!\n"));
    526                 TALLOC_FREE( ctx );
    527                 return -1;     
    528         }
    529 
    530         /* upper case the sAMAccountName to make it easier for apps to
    531            know what case to use in the keytab file */
    532 
    533         strupper_m( sam_account_name );
    534 
    535         if ( (ret = ads_keytab_add_entry(ads, sam_account_name )) != 0 ) {
    536                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding sAMAccountName (%s)\n",
    537                         sam_account_name));
    538                 return ret;
    539         }
    540        
    541         /* remember that not every machine account will have a upn */
    542                
    543         upn = ads_get_upn( ads, ctx, machine_name);
    544         if ( upn ) {
    545                 if ( (ret = ads_keytab_add_entry(ads, upn)) != 0 ) {
    546                         DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding UPN (%s)\n",
    547                                 upn));
    548                         TALLOC_FREE( ctx );
    549                         return ret;
    550                 }
    551         }
    552 
    553         /* Now loop through the keytab and update any other existing entries... */
    554        
    555         kvno = (krb5_kvno) ads_get_machine_kvno(ads, machine_name);
    556         if (kvno == -1) {
    557                 DEBUG(1,("ads_keytab_create_default: ads_get_machine_kvno failed to determine the system's kvno.\n"));
    558                 TALLOC_FREE(ctx);
    559                 return -1;
    560         }
    561        
    562         DEBUG(3,("ads_keytab_create_default: Searching for keytab entries to "
    563                 "preserve and update.\n"));
    564 
    565530        ZERO_STRUCT(kt_entry);
    566531        ZERO_STRUCT(cursor);
     
    569534        ret = krb5_init_context(&context);
    570535        if (ret) {
    571                 DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret)));
    572                 TALLOC_FREE(ctx);
     536                DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
     537                          error_message(ret)));
    573538                return ret;
    574539        }
    575540
     541        tmpctx = talloc_init(__location__);
     542        if (!tmpctx) {
     543                DEBUG(0, (__location__ ": talloc_init() failed!\n"));
     544                ret = -1;
     545                goto done;
     546        }
     547
     548        machine_name = talloc_strdup(tmpctx, global_myname());
     549        if (!machine_name) {
     550                ret = -1;
     551                goto done;
     552        }
     553
     554        /* now add the userPrincipalName and sAMAccountName entries */
     555        sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);
     556        if (!sam_account_name) {
     557                DEBUG(0, (__location__ ": unable to determine machine "
     558                          "account's name in AD!\n"));
     559                ret = -1;
     560                goto done;
     561        }
     562
     563        /* upper case the sAMAccountName to make it easier for apps to
     564           know what case to use in the keytab file */
     565        strupper_m(sam_account_name);
     566
     567        ret = ads_keytab_add_entry(ads, sam_account_name);
     568        if (ret != 0) {
     569                DEBUG(1, (__location__ ": ads_keytab_add_entry() failed "
     570                          "while adding sAMAccountName (%s)\n",
     571                          sam_account_name));
     572                goto done;
     573        }
     574
     575        /* remember that not every machine account will have a upn */
     576        upn = ads_get_upn(ads, tmpctx, machine_name);
     577        if (upn) {
     578                ret = ads_keytab_add_entry(ads, upn);
     579                if (ret != 0) {
     580                        DEBUG(1, (__location__ ": ads_keytab_add_entry() "
     581                                  "failed while adding UPN (%s)\n", upn));
     582                        goto done;
     583                }
     584        }
     585
     586        /* Now loop through the keytab and update any other existing entries */
     587        kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name);
     588        if (kvno == -1) {
     589                DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to "
     590                          "determine the system's kvno.\n"));
     591                goto done;
     592        }
     593
     594        DEBUG(3, (__location__ ": Searching for keytab entries to preserve "
     595                  "and update.\n"));
     596
    576597        ret = smb_krb5_open_keytab(context, NULL, True, &keytab);
    577598        if (ret) {
    578                 DEBUG(1,("ads_keytab_create_default: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
     599                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     600                          error_message(ret)));
    579601                goto done;
    580602        }
     
    582604        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    583605        if (ret != KRB5_KT_END && ret != ENOENT ) {
    584                 while ((ret = krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) == 0) {
     606                while ((ret = krb5_kt_next_entry(context, keytab,
     607                                                 &kt_entry, &cursor)) == 0) {
    585608                        smb_krb5_kt_free_entry(context, &kt_entry);
    586609                        ZERO_STRUCT(kt_entry);
     
    592615
    593616        /*
    594          * Hmmm. There is no "rewind" function for the keytab. This means we have a race condition
    595          * where someone else could add entries after we've counted them. Re-open asap to minimise
    596          * the race. JRA.
     617         * Hmmm. There is no "rewind" function for the keytab. This means we
     618         * have a race condition where someone else could add entries after
     619         * we've counted them. Re-open asap to minimise the race. JRA.
    597620         */
    598        
    599         DEBUG(3, ("ads_keytab_create_default: Found %d entries in the keytab.\n", found));
     621        DEBUG(3, (__location__ ": Found %d entries in the keytab.\n", found));
    600622        if (!found) {
    601623                goto done;
    602624        }
    603         oldEntries = talloc_array(ctx, char *, found );
     625
     626        oldEntries = talloc_array(tmpctx, char *, found);
    604627        if (!oldEntries) {
    605                 DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n"));
     628                DEBUG(1, (__location__ ": Failed to allocate space to store "
     629                          "the old keytab entries (talloc failed?).\n"));
    606630                ret = -1;
    607631                goto done;
     
    610634
    611635        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    612         if (ret != KRB5_KT_END && ret != ENOENT ) {
    613                 while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
    614                         if (kt_entry.vno != kvno) {
    615                                 char *ktprinc = NULL;
    616                                 char *p;
    617 
    618                                 /* This returns a malloc'ed string in ktprinc. */
    619                                 ret = smb_krb5_unparse_name(oldEntries, context, kt_entry.principal, &ktprinc);
    620                                 if (ret) {
    621                                         DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret)));
    622                                         goto done;
     636        if (ret == KRB5_KT_END || ret == ENOENT) {
     637                krb5_kt_end_seq_get(context, keytab, &cursor);
     638                ZERO_STRUCT(cursor);
     639                goto done;
     640        }
     641
     642        while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
     643                if (kt_entry.vno != kvno) {
     644                        char *ktprinc = NULL;
     645                        char *p;
     646
     647                        /* This returns a malloc'ed string in ktprinc. */
     648                        ret = smb_krb5_unparse_name(oldEntries, context,
     649                                                    kt_entry.principal,
     650                                                    &ktprinc);
     651                        if (ret) {
     652                                DEBUG(1, (__location__
     653                                         ": smb_krb5_unparse_name failed "
     654                                         "(%s)\n", error_message(ret)));
     655                                goto done;
     656                        }
     657                        /*
     658                         * From looking at the krb5 source they don't seem to
     659                         * take locale or mb strings into account.
     660                         * Maybe this is because they assume utf8 ?
     661                         * In this case we may need to convert from utf8 to
     662                         * mb charset here ? JRA.
     663                         */
     664                        p = strchr_m(ktprinc, '@');
     665                        if (p) {
     666                                *p = '\0';
     667                        }
     668
     669                        p = strchr_m(ktprinc, '/');
     670                        if (p) {
     671                                *p = '\0';
     672                        }
     673                        for (i = 0; i < found; i++) {
     674                                if (!oldEntries[i]) {
     675                                        oldEntries[i] = ktprinc;
     676                                        break;
    623677                                }
    624                                 /*
    625                                  * From looking at the krb5 source they don't seem to take locale
    626                                  * or mb strings into account. Maybe this is because they assume utf8 ?
    627                                  * In this case we may need to convert from utf8 to mb charset here ? JRA.
    628                                  */
    629                                 p = strchr_m(ktprinc, '@');
    630                                 if (p) {
    631                                         *p = '\0';
    632                                 }
    633 
    634                                 p = strchr_m(ktprinc, '/');
    635                                 if (p) {
    636                                         *p = '\0';
    637                                 }
    638                                 for (i = 0; i < found; i++) {
    639                                         if (!oldEntries[i]) {
    640                                                 oldEntries[i] = ktprinc;
    641                                                 break;
    642                                         }
    643                                         if (!strcmp(oldEntries[i], ktprinc)) {
    644                                                 TALLOC_FREE(ktprinc);
    645                                                 break;
    646                                         }
    647                                 }
    648                                 if (i == found) {
     678                                if (!strcmp(oldEntries[i], ktprinc)) {
    649679                                        TALLOC_FREE(ktprinc);
     680                                        break;
    650681                                }
    651682                        }
    652                         smb_krb5_kt_free_entry(context, &kt_entry);
    653                         ZERO_STRUCT(kt_entry);
    654                 }
    655                 ret = 0;
    656                 for (i = 0; oldEntries[i]; i++) {
    657                         ret |= ads_keytab_add_entry(ads, oldEntries[i]);
    658                         TALLOC_FREE(oldEntries[i]);
    659                 }
    660                 krb5_kt_end_seq_get(context, keytab, &cursor);
    661         }
     683                        if (i == found) {
     684                                TALLOC_FREE(ktprinc);
     685                        }
     686                }
     687                smb_krb5_kt_free_entry(context, &kt_entry);
     688                ZERO_STRUCT(kt_entry);
     689        }
     690        ret = 0;
     691        for (i = 0; oldEntries[i]; i++) {
     692                ret |= ads_keytab_add_entry(ads, oldEntries[i]);
     693                TALLOC_FREE(oldEntries[i]);
     694        }
     695        krb5_kt_end_seq_get(context, keytab, &cursor);
    662696        ZERO_STRUCT(cursor);
    663697
    664698done:
    665 
    666699        TALLOC_FREE(oldEntries);
    667         TALLOC_FREE(ctx);
     700        TALLOC_FREE(tmpctx);
    668701
    669702        {
    670703                krb5_keytab_entry zero_kt_entry;
    671704                ZERO_STRUCT(zero_kt_entry);
    672                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
     705                if (memcmp(&zero_kt_entry, &kt_entry,
     706                                sizeof(krb5_keytab_entry))) {
    673707                        smb_krb5_kt_free_entry(context, &kt_entry);
    674708                }
     
    677711                krb5_kt_cursor zero_csr;
    678712                ZERO_STRUCT(zero_csr);
    679                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
    680                         krb5_kt_end_seq_get(context, keytab, &cursor); 
     713                if ((memcmp(&cursor, &zero_csr,
     714                                sizeof(krb5_kt_cursor)) != 0) && keytab) {
     715                        krb5_kt_end_seq_get(context, keytab, &cursor);
    681716                }
    682717        }
     
    708743        ret = krb5_init_context(&context);
    709744        if (ret) {
    710                 DEBUG(1,("ads_keytab_list: could not krb5_init_context: %s\n",error_message(ret)));
     745                DEBUG(1, (__location__ ": could not krb5_init_context: %s\n",
     746                          error_message(ret)));
    711747                return ret;
    712748        }
     
    714750        ret = smb_krb5_open_keytab(context, keytab_name, False, &keytab);
    715751        if (ret) {
    716                 DEBUG(1,("ads_keytab_list: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
     752                DEBUG(1, (__location__ ": smb_krb5_open_keytab failed (%s)\n",
     753                          error_message(ret)));
    717754                goto out;
    718755        }
     
    720757        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    721758        if (ret) {
     759                ZERO_STRUCT(cursor);
    722760                goto out;
    723761        }
     
    726764
    727765        while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
    728        
     766
    729767                char *princ_s = NULL;
    730768                char *etype_s = NULL;
    731769                krb5_enctype enctype = 0;
    732770
    733                 ret = smb_krb5_unparse_name(talloc_tos(), context, kt_entry.principal, &princ_s);
     771                ret = smb_krb5_unparse_name(talloc_tos(), context,
     772                                            kt_entry.principal, &princ_s);
    734773                if (ret) {
    735774                        goto out;
     
    739778
    740779                ret = smb_krb5_enctype_to_string(context, enctype, &etype_s);
    741                 if (ret) {
    742                         if (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1)
    743                         {
    744                                 TALLOC_FREE(princ_s);
    745                                 goto out;
    746                         }
     780                if (ret &&
     781                    (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1)) {
     782                        TALLOC_FREE(princ_s);
     783                        goto out;
    747784                }
    748785
     
    771808                krb5_keytab_entry zero_kt_entry;
    772809                ZERO_STRUCT(zero_kt_entry);
    773                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
     810                if (memcmp(&zero_kt_entry, &kt_entry,
     811                                sizeof(krb5_keytab_entry))) {
    774812                        smb_krb5_kt_free_entry(context, &kt_entry);
    775813                }
     
    778816                krb5_kt_cursor zero_csr;
    779817                ZERO_STRUCT(zero_csr);
    780                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
    781                         krb5_kt_end_seq_get(context, keytab, &cursor); 
     818                if ((memcmp(&cursor, &zero_csr,
     819                                sizeof(krb5_kt_cursor)) != 0) && keytab) {
     820                        krb5_kt_end_seq_get(context, keytab, &cursor);
    782821                }
    783822        }
Note: See TracChangeset for help on using the changeset viewer.