libads/kerberos_keytab.c

ソースコードを見る。

関数

static int smb_krb5_kt_add_entry (krb5_context context, krb5_keytab keytab, krb5_kvno kvno, const char *princ_s, krb5_enctype *enctypes, krb5_data password)
int ads_keytab_add_entry (ADS_STRUCT *ads, const char *srvPrinc)
int ads_keytab_flush (ADS_STRUCT *ads)
int ads_keytab_create_default (ADS_STRUCT *ads)


関数

static int smb_krb5_kt_add_entry ( krb5_context  context,
krb5_keytab  keytab,
krb5_kvno  kvno,
const char *  princ_s,
krb5_enctype *  enctypes,
krb5_data  password 
) [static]

kerberos_keytab.c42 行で定義されています。

参照先 create_kerberos_key_from_string()smb_krb5_kt_free_entry()smb_krb5_parse_name()smb_krb5_unparse_name().

参照元 ads_keytab_add_entry().

00045 {
00046         krb5_error_code ret = 0;
00047         krb5_kt_cursor cursor;
00048         krb5_keytab_entry kt_entry;
00049         krb5_principal princ = NULL;
00050         int i;
00051         char *ktprinc = NULL;
00052 
00053         ZERO_STRUCT(kt_entry);
00054         ZERO_STRUCT(cursor);
00055         
00056         ret = smb_krb5_parse_name(context, princ_s, &princ);
00057         if (ret) {
00058                 DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
00059                 goto out;
00060         }
00061 
00062         /* Seek and delete old keytab entries */
00063         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00064         if (ret != KRB5_KT_END && ret != ENOENT ) {
00065                 DEBUG(3,("smb_krb5_kt_add_entry: Will try to delete old keytab entries\n"));
00066                 while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
00067                         BOOL compare_name_ok = False;
00068 
00069                         ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
00070                         if (ret) {
00071                                 DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_unparse_name failed (%s)\n",
00072                                         error_message(ret)));
00073                                 goto out;
00074                         }
00075 
00076                         /*---------------------------------------------------------------------------
00077                          * Save the entries with kvno - 1.   This is what microsoft does
00078                          * to allow people with existing sessions that have kvno - 1 to still
00079                          * work.   Otherwise, when the password for the machine changes, all
00080                          * kerberizied sessions will 'break' until either the client reboots or
00081                          * the client's session key expires and they get a new session ticket
00082                          * with the new kvno.
00083                          */
00084 
00085 #ifdef HAVE_KRB5_KT_COMPARE
00086                         compare_name_ok = (krb5_kt_compare(context, &kt_entry, princ, 0, 0) == True);
00087 #else
00088                         compare_name_ok = (strcmp(ktprinc, princ_s) == 0);
00089 #endif
00090 
00091                         if (!compare_name_ok) {
00092                                 DEBUG(10,("smb_krb5_kt_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
00093                                         ktprinc, kt_entry.vno));
00094                         }
00095 
00096                         SAFE_FREE(ktprinc);
00097 
00098                         if (compare_name_ok) {
00099                                 if (kt_entry.vno == kvno - 1) {
00100                                         DEBUG(5,("smb_krb5_kt_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
00101                                                 kvno - 1, princ_s));
00102                                 } else {
00103 
00104                                         DEBUG(5,("smb_krb5_kt_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
00105                                                 princ_s, kt_entry.vno));
00106                                         ret = krb5_kt_end_seq_get(context, keytab, &cursor);
00107                                         ZERO_STRUCT(cursor);
00108                                         if (ret) {
00109                                                 DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
00110                                                         error_message(ret)));
00111                                                 goto out;
00112                                         }
00113                                         ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
00114                                         if (ret) {
00115                                                 DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
00116                                                         error_message(ret)));
00117                                                 goto out;
00118                                         }
00119 
00120                                         DEBUG(5,("smb_krb5_kt_add_entry: removed old entry for principal: %s (kvno %d).\n",
00121                                                 princ_s, kt_entry.vno));
00122 
00123                                         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00124                                         if (ret) {
00125                                                 DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_start_seq failed (%s)\n",
00126                                                         error_message(ret)));
00127                                                 goto out;
00128                                         }
00129                                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
00130                                         ZERO_STRUCT(kt_entry);
00131                                         if (ret) {
00132                                                 DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
00133                                                         error_message(ret)));
00134                                                 goto out;
00135                                         }
00136                                         continue;
00137                                 }
00138                         }
00139 
00140                         /* Not a match, just free this entry and continue. */
00141                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
00142                         ZERO_STRUCT(kt_entry);
00143                         if (ret) {
00144                                 DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
00145                                 goto out;
00146                         }
00147                 }
00148 
00149                 ret = krb5_kt_end_seq_get(context, keytab, &cursor);
00150                 ZERO_STRUCT(cursor);
00151                 if (ret) {
00152                         DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
00153                         goto out;
00154                 }
00155         }
00156 
00157         /* Ensure we don't double free. */
00158         ZERO_STRUCT(kt_entry);
00159         ZERO_STRUCT(cursor);
00160 
00161         /* If we get here, we have deleted all the old entries with kvno's not equal to the current kvno-1. */
00162 
00163         /* Now add keytab entries for all encryption types */
00164         for (i = 0; enctypes[i]; i++) {
00165                 krb5_keyblock *keyp;
00166 
00167 #if !defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) && !defined(HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK)
00168 #error krb5_keytab_entry has no key or keyblock member
00169 #endif
00170 #ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY               /* MIT */
00171                 keyp = &kt_entry.key;
00172 #endif
00173 #ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK          /* Heimdal */
00174                 keyp = &kt_entry.keyblock;
00175 #endif
00176                 if (create_kerberos_key_from_string(context, princ, &password, keyp, enctypes[i])) {
00177                         continue;
00178                 }
00179 
00180                 kt_entry.principal = princ;
00181                 kt_entry.vno       = kvno;
00182 
00183                 DEBUG(3,("smb_krb5_kt_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
00184                         princ_s, enctypes[i], kt_entry.vno));
00185                 ret = krb5_kt_add_entry(context, keytab, &kt_entry);
00186                 krb5_free_keyblock_contents(context, keyp);
00187                 ZERO_STRUCT(kt_entry);
00188                 if (ret) {
00189                         DEBUG(1,("smb_krb5_kt_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
00190                         goto out;
00191                 }
00192         }
00193 
00194 
00195 out:
00196         {
00197                 krb5_keytab_entry zero_kt_entry;
00198                 ZERO_STRUCT(zero_kt_entry);
00199                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
00200                         smb_krb5_kt_free_entry(context, &kt_entry);
00201                 }
00202         }
00203         if (princ) {
00204                 krb5_free_principal(context, princ);
00205         }
00206         
00207         {
00208                 krb5_kt_cursor zero_csr;
00209                 ZERO_STRUCT(zero_csr);
00210                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
00211                         krb5_kt_end_seq_get(context, keytab, &cursor);  
00212                 }
00213         }
00214         
00215         return (int)ret;
00216 }

int ads_keytab_add_entry ( ADS_STRUCT ads,
const char *  srvPrinc 
)

kerberos_keytab.c223 行で定義されています。

参照先 ads_add_service_principal_name()ads_get_dnshostname()ads_get_kvno()ads_get_samaccountname()asprintf()ctxglobal_mynamelp_workgroup()passwordsecrets_fetch_machine_password()secrets_init()smb_krb5_kt_add_entry()strchr_m()strequal()talloc_init().

参照元 ads_keytab_create_default()net_ads_keytab_add().

00224 {
00225         krb5_error_code ret = 0;
00226         krb5_context context = NULL;
00227         krb5_keytab keytab = NULL;
00228         krb5_data password;
00229         krb5_kvno kvno;
00230         krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, 0, 0 };
00231         char *princ_s = NULL, *short_princ_s = NULL;
00232         char *password_s = NULL;
00233         char *my_fqdn;
00234         char keytab_name[MAX_KEYTAB_NAME_LEN];          
00235         TALLOC_CTX *ctx = NULL;
00236         char *machine_name;
00237 
00238 #if defined(ENCTYPE_ARCFOUR_HMAC)
00239         enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
00240 #endif
00241 
00242         initialize_krb5_error_table();
00243         ret = krb5_init_context(&context);
00244         if (ret) {
00245                 DEBUG(1,("ads_keytab_add_entry: could not krb5_init_context: %s\n",error_message(ret)));
00246                 return -1;
00247         }
00248         
00249 #ifdef HAVE_WRFILE_KEYTAB       /* MIT */
00250         keytab_name[0] = 'W';
00251         keytab_name[1] = 'R';
00252         ret = krb5_kt_default_name(context, (char *) &keytab_name[2], MAX_KEYTAB_NAME_LEN - 4);
00253 #else                           /* Heimdal */
00254         ret = krb5_kt_default_name(context, (char *) &keytab_name[0], MAX_KEYTAB_NAME_LEN - 2);
00255 #endif
00256         if (ret) {
00257                 DEBUG(1,("ads_keytab_add_entry: krb5_kt_default_name failed (%s)\n", error_message(ret)));
00258                 goto out;
00259         }
00260         DEBUG(2,("ads_keytab_add_entry: Using default system keytab: %s\n", (char *) &keytab_name));
00261         ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
00262         if (ret) {
00263                 DEBUG(1,("ads_keytab_add_entry: krb5_kt_resolve failed (%s)\n", error_message(ret)));
00264                 goto out;
00265         }
00266 
00267         /* retrieve the password */
00268         if (!secrets_init()) {
00269                 DEBUG(1,("ads_keytab_add_entry: secrets_init failed\n"));
00270                 ret = -1;
00271                 goto out;
00272         }
00273         password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
00274         if (!password_s) {
00275                 DEBUG(1,("ads_keytab_add_entry: failed to fetch machine password\n"));
00276                 ret = -1;
00277                 goto out;
00278         }
00279         password.data = password_s;
00280         password.length = strlen(password_s);
00281 
00282         /* we need the dNSHostName value here */
00283         
00284         if ( (ctx = talloc_init("ads_keytab_add_entry")) == NULL ) {
00285                 DEBUG(0,("ads_keytab_add_entry: talloc() failed!\n"));
00286                 ret = -1;
00287                 goto out;
00288         }
00289         
00290         if ( (my_fqdn = ads_get_dnshostname( ads, ctx, global_myname())) == NULL ) {
00291                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's dns name in AD!\n"));
00292                 ret = -1;
00293                 goto out;       
00294         }
00295         
00296         if ( (machine_name = ads_get_samaccountname( ads, ctx, global_myname())) == NULL ) {
00297                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's short name in AD!\n"));
00298                 ret = -1;
00299                 goto out;       
00300         }
00301         /*strip the trailing '$' */
00302         machine_name[strlen(machine_name)-1] = '\0';
00303                 
00304         /* Construct our principal */
00305 
00306         if (strchr_m(srvPrinc, '@')) {
00307                 /* It's a fully-named principal. */
00308                 asprintf(&princ_s, "%s", srvPrinc);
00309         } else if (srvPrinc[strlen(srvPrinc)-1] == '$') {
00310                 /* It's the machine account, as used by smbclient clients. */
00311                 asprintf(&princ_s, "%s@%s", srvPrinc, lp_realm());
00312         } else {
00313                 /* It's a normal service principal.  Add the SPN now so that we
00314                  * can obtain credentials for it and double-check the salt value
00315                  * used to generate the service's keys. */
00316                  
00317                 asprintf(&princ_s, "%s/%s@%s", srvPrinc, my_fqdn, lp_realm());
00318                 asprintf(&short_princ_s, "%s/%s@%s", srvPrinc, machine_name, lp_realm());
00319                 
00320                 /* According to http://support.microsoft.com/kb/326985/en-us, 
00321                    certain principal names are automatically mapped to the host/...
00322                    principal in the AD account.  So only create these in the 
00323                    keytab, not in AD.  --jerry */
00324                    
00325                 if ( !strequal( srvPrinc, "cifs" ) && !strequal(srvPrinc, "host" ) ) {
00326                         DEBUG(3,("ads_keytab_add_entry: Attempting to add/update '%s'\n", princ_s));
00327                         
00328                         if (!ADS_ERR_OK(ads_add_service_principal_name(ads, global_myname(), my_fqdn, srvPrinc))) {
00329                                 DEBUG(1,("ads_keytab_add_entry: ads_add_service_principal_name failed.\n"));
00330                                 goto out;
00331                         }
00332                 }
00333         }
00334 
00335         kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
00336         if (kvno == -1) {       /* -1 indicates failure, everything else is OK */
00337                 DEBUG(1,("ads_keytab_add_entry: ads_get_kvno failed to determine the system's kvno.\n"));
00338                 ret = -1;
00339                 goto out;
00340         }
00341         
00342         /* add the fqdn principal to the keytab */
00343         
00344         ret = smb_krb5_kt_add_entry( context, keytab, kvno, princ_s, enctypes, password );
00345         if ( ret ) {
00346                 DEBUG(1,("ads_keytab_add_entry: Failed to add entry to keytab file\n"));
00347                 goto out;
00348         }
00349         
00350         /* add the short principal name if we have one */
00351         
00352         if ( short_princ_s ) {
00353                 ret = smb_krb5_kt_add_entry( context, keytab, kvno, short_princ_s, enctypes, password );
00354                 if ( ret ) {
00355                         DEBUG(1,("ads_keytab_add_entry: Failed to add short entry to keytab file\n"));
00356                         goto out;
00357                 }
00358         }
00359 
00360 out:
00361         SAFE_FREE( princ_s );
00362         SAFE_FREE( short_princ_s );
00363         TALLOC_FREE( ctx );
00364         
00365         if (keytab) {
00366                 krb5_kt_close(context, keytab);
00367         }
00368         if (context) {
00369                 krb5_free_context(context);
00370         }
00371         return (int)ret;
00372 }

int ads_keytab_flush ( ADS_STRUCT ads  ) 

kerberos_keytab.c378 行で定義されています。

参照先 ads_clear_service_principal_names()ads_get_kvno()global_mynamesmb_krb5_kt_free_entry().

参照元 net_ads_keytab_flush().

00379 {
00380         krb5_error_code ret = 0;
00381         krb5_context context = NULL;
00382         krb5_keytab keytab = NULL;
00383         krb5_kt_cursor cursor;
00384         krb5_keytab_entry kt_entry;
00385         krb5_kvno kvno;
00386         char keytab_name[MAX_KEYTAB_NAME_LEN];
00387 
00388         ZERO_STRUCT(kt_entry);
00389         ZERO_STRUCT(cursor);
00390 
00391         initialize_krb5_error_table();
00392         ret = krb5_init_context(&context);
00393         if (ret) {
00394                 DEBUG(1,("ads_keytab_flush: could not krb5_init_context: %s\n",error_message(ret)));
00395                 return ret;
00396         }
00397 #ifdef HAVE_WRFILE_KEYTAB
00398         keytab_name[0] = 'W';
00399         keytab_name[1] = 'R';
00400         ret = krb5_kt_default_name(context, (char *) &keytab_name[2], MAX_KEYTAB_NAME_LEN - 4);
00401 #else
00402         ret = krb5_kt_default_name(context, (char *) &keytab_name[0], MAX_KEYTAB_NAME_LEN - 2);
00403 #endif
00404         if (ret) {
00405                 DEBUG(1,("ads_keytab_flush: krb5_kt_default failed (%s)\n", error_message(ret)));
00406                 goto out;
00407         }
00408         DEBUG(3,("ads_keytab_flush: Using default keytab: %s\n", (char *) &keytab_name));
00409         ret = krb5_kt_resolve(context, (char *) &keytab_name, &keytab);
00410         if (ret) {
00411                 DEBUG(1,("ads_keytab_flush: krb5_kt_resolve failed (%s)\n", error_message(ret)));
00412                 goto out;
00413         }
00414 
00415         kvno = (krb5_kvno) ads_get_kvno(ads, global_myname());
00416         if (kvno == -1) {       /* -1 indicates a failure */
00417                 DEBUG(1,("ads_keytab_flush: Error determining the system's kvno.\n"));
00418                 goto out;
00419         }
00420 
00421         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00422         if (ret != KRB5_KT_END && ret != ENOENT) {
00423                 while (!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
00424                         ret = krb5_kt_end_seq_get(context, keytab, &cursor);
00425                         ZERO_STRUCT(cursor);
00426                         if (ret) {
00427                                 DEBUG(1,("ads_keytab_flush: krb5_kt_end_seq_get() failed (%s)\n",error_message(ret)));
00428                                 goto out;
00429                         }
00430                         ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
00431                         if (ret) {
00432                                 DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
00433                                 goto out;
00434                         }
00435                         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00436                         if (ret) {
00437                                 DEBUG(1,("ads_keytab_flush: krb5_kt_start_seq failed (%s)\n",error_message(ret)));
00438                                 goto out;
00439                         }
00440                         ret = smb_krb5_kt_free_entry(context, &kt_entry);
00441                         ZERO_STRUCT(kt_entry);
00442                         if (ret) {
00443                                 DEBUG(1,("ads_keytab_flush: krb5_kt_remove_entry failed (%s)\n",error_message(ret)));
00444                                 goto out;
00445                         }
00446                 }
00447         }
00448 
00449         /* Ensure we don't double free. */
00450         ZERO_STRUCT(kt_entry);
00451         ZERO_STRUCT(cursor);
00452 
00453         if (!ADS_ERR_OK(ads_clear_service_principal_names(ads, global_myname()))) {
00454                 DEBUG(1,("ads_keytab_flush: Error while clearing service principal listings in LDAP.\n"));
00455                 goto out;
00456         }
00457 
00458 out:
00459 
00460         {
00461                 krb5_keytab_entry zero_kt_entry;
00462                 ZERO_STRUCT(zero_kt_entry);
00463                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
00464                         smb_krb5_kt_free_entry(context, &kt_entry);
00465                 }
00466         }
00467         {
00468                 krb5_kt_cursor zero_csr;
00469                 ZERO_STRUCT(zero_csr);
00470                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
00471                         krb5_kt_end_seq_get(context, keytab, &cursor);  
00472                 }
00473         }
00474         if (keytab) {
00475                 krb5_kt_close(context, keytab);
00476         }
00477         if (context) {
00478                 krb5_free_context(context);
00479         }
00480         return ret;
00481 }

int ads_keytab_create_default ( ADS_STRUCT ads  ) 

kerberos_keytab.c487 行で定義されています。

参照先 ads_get_kvno()ads_get_samaccountname()ads_get_upn()ads_keytab_add_entry()ctxglobal_mynamesmb_krb5_kt_free_entry()smb_krb5_unparse_name()strchr_m()strupper_m()talloc_init().

参照元 net_ads_changetrustpw()net_ads_join()net_ads_keytab_create().

00488 {
00489         krb5_error_code ret = 0;
00490         krb5_context context = NULL;
00491         krb5_keytab keytab = NULL;
00492         krb5_kt_cursor cursor;
00493         krb5_keytab_entry kt_entry;
00494         krb5_kvno kvno;
00495         int i, found = 0;
00496         char *sam_account_name, *upn;
00497         char **oldEntries = NULL, *princ_s[26];
00498         TALLOC_CTX *ctx = NULL;
00499         fstring machine_name;
00500 
00501         memset(princ_s, '\0', sizeof(princ_s));
00502 
00503         fstrcpy( machine_name, global_myname() );
00504 
00505         /* these are the main ones we need */
00506         
00507         if ( (ret = ads_keytab_add_entry(ads, "host") ) != 0 ) {
00508                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'host'.\n"));
00509                 return ret;
00510         }
00511 
00512 
00513 #if 0   /* don't create the CIFS/... keytab entries since no one except smbd 
00514            really needs them and we will fall back to verifying against secrets.tdb */
00515            
00516         if ( (ret = ads_keytab_add_entry(ads, "cifs")) != 0 ) {
00517                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding 'cifs'.\n"));
00518                 return ret;
00519         }
00520 #endif
00521 
00522         if ( (ctx = talloc_init("ads_keytab_create_default")) == NULL ) {
00523                 DEBUG(0,("ads_keytab_create_default: talloc() failed!\n"));
00524                 return -1;
00525         }
00526 
00527         /* now add the userPrincipalName and sAMAccountName entries */
00528 
00529         if ( (sam_account_name = ads_get_samaccountname( ads, ctx, machine_name)) == NULL ) {
00530                 DEBUG(0,("ads_keytab_add_entry: unable to determine machine account's name in AD!\n"));
00531                 TALLOC_FREE( ctx );
00532                 return -1;      
00533         }
00534 
00535         /* upper case the sAMAccountName to make it easier for apps to 
00536            know what case to use in the keytab file */
00537 
00538         strupper_m( sam_account_name ); 
00539 
00540         if ( (ret = ads_keytab_add_entry(ads, sam_account_name )) != 0 ) {
00541                 DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding sAMAccountName (%s)\n",
00542                         sam_account_name));
00543                 return ret;
00544         }
00545         
00546         /* remember that not every machine account will have a upn */
00547                 
00548         upn = ads_get_upn( ads, ctx, machine_name);
00549         if ( upn ) {
00550                 if ( (ret = ads_keytab_add_entry(ads, upn)) != 0 ) {
00551                         DEBUG(1,("ads_keytab_create_default: ads_keytab_add_entry failed while adding UPN (%s)\n",
00552                                 upn));
00553                         TALLOC_FREE( ctx );
00554                         return ret;
00555                 }
00556         }
00557 
00558         TALLOC_FREE( ctx );
00559 
00560         /* Now loop through the keytab and update any other existing entries... */
00561         
00562         kvno = (krb5_kvno) ads_get_kvno(ads, machine_name);
00563         if (kvno == -1) {
00564                 DEBUG(1,("ads_keytab_create_default: ads_get_kvno failed to determine the system's kvno.\n"));
00565                 return -1;
00566         }
00567         
00568         DEBUG(3,("ads_keytab_create_default: Searching for keytab entries to "
00569                 "preserve and update.\n"));
00570 
00571         ZERO_STRUCT(kt_entry);
00572         ZERO_STRUCT(cursor);
00573 
00574         initialize_krb5_error_table();
00575         ret = krb5_init_context(&context);
00576         if (ret) {
00577                 DEBUG(1,("ads_keytab_create_default: could not krb5_init_context: %s\n",error_message(ret)));
00578                 return ret;
00579         }
00580         ret = krb5_kt_default(context, &keytab);
00581         if (ret) {
00582                 DEBUG(1,("ads_keytab_create_default: krb5_kt_default failed (%s)\n",error_message(ret)));
00583                 goto done;
00584         }
00585 
00586         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00587         if (ret != KRB5_KT_END && ret != ENOENT ) {
00588                 while ((ret = krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) == 0) {
00589                         smb_krb5_kt_free_entry(context, &kt_entry);
00590                         ZERO_STRUCT(kt_entry);
00591                         found++;
00592                 }
00593         }
00594         krb5_kt_end_seq_get(context, keytab, &cursor);
00595         ZERO_STRUCT(cursor);
00596 
00597         /*
00598          * Hmmm. There is no "rewind" function for the keytab. This means we have a race condition
00599          * where someone else could add entries after we've counted them. Re-open asap to minimise
00600          * the race. JRA.
00601          */
00602         
00603         DEBUG(3, ("ads_keytab_create_default: Found %d entries in the keytab.\n", found));
00604         if (!found) {
00605                 goto done;
00606         }
00607         oldEntries = SMB_MALLOC_ARRAY(char *, found );
00608         if (!oldEntries) {
00609                 DEBUG(1,("ads_keytab_create_default: Failed to allocate space to store the old keytab entries (malloc failed?).\n"));
00610                 ret = -1;
00611                 goto done;
00612         }
00613         memset(oldEntries, '\0', found * sizeof(char *));
00614 
00615         ret = krb5_kt_start_seq_get(context, keytab, &cursor);
00616         if (ret != KRB5_KT_END && ret != ENOENT ) {
00617                 while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) {
00618                         if (kt_entry.vno != kvno) {
00619                                 char *ktprinc = NULL;
00620                                 char *p;
00621 
00622                                 /* This returns a malloc'ed string in ktprinc. */
00623                                 ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
00624                                 if (ret) {
00625                                         DEBUG(1,("smb_krb5_unparse_name failed (%s)\n", error_message(ret)));
00626                                         goto done;
00627                                 }
00628                                 /*
00629                                  * From looking at the krb5 source they don't seem to take locale
00630                                  * or mb strings into account. Maybe this is because they assume utf8 ?
00631                                  * In this case we may need to convert from utf8 to mb charset here ? JRA.
00632                                  */
00633                                 p = strchr_m(ktprinc, '@');
00634                                 if (p) {
00635                                         *p = '\0';
00636                                 }
00637 
00638                                 p = strchr_m(ktprinc, '/');
00639                                 if (p) {
00640                                         *p = '\0';
00641                                 }
00642                                 for (i = 0; i < found; i++) {
00643                                         if (!oldEntries[i]) {
00644                                                 oldEntries[i] = ktprinc;
00645                                                 break;
00646                                         }
00647                                         if (!strcmp(oldEntries[i], ktprinc)) {
00648                                                 SAFE_FREE(ktprinc);
00649                                                 break;
00650                                         }
00651                                 }
00652                                 if (i == found) {
00653                                         SAFE_FREE(ktprinc);
00654                                 }
00655                         }
00656                         smb_krb5_kt_free_entry(context, &kt_entry);
00657                         ZERO_STRUCT(kt_entry);
00658                 }
00659                 ret = 0;
00660                 for (i = 0; oldEntries[i]; i++) {
00661                         ret |= ads_keytab_add_entry(ads, oldEntries[i]);
00662                         SAFE_FREE(oldEntries[i]);
00663                 }
00664                 krb5_kt_end_seq_get(context, keytab, &cursor);
00665         }
00666         ZERO_STRUCT(cursor);
00667 
00668 done:
00669 
00670         SAFE_FREE(oldEntries);
00671 
00672         {
00673                 krb5_keytab_entry zero_kt_entry;
00674                 ZERO_STRUCT(zero_kt_entry);
00675                 if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
00676                         smb_krb5_kt_free_entry(context, &kt_entry);
00677                 }
00678         }
00679         {
00680                 krb5_kt_cursor zero_csr;
00681                 ZERO_STRUCT(zero_csr);
00682                 if ((memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
00683                         krb5_kt_end_seq_get(context, keytab, &cursor);  
00684                 }
00685         }
00686         if (keytab) {
00687                 krb5_kt_close(context, keytab);
00688         }
00689         if (context) {
00690                 krb5_free_context(context);
00691         }
00692         return ret;
00693 }


Sambaに対してSat Aug 29 21:23:42 2009に生成されました。  doxygen 1.4.7