関数 | |
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.c の 42 行で定義されています。
参照先 create_kerberos_key_from_string()・smb_krb5_kt_free_entry()・smb_krb5_parse_name()・smb_krb5_unparse_name().
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.c の 223 行で定義されています。
参照先 ads_add_service_principal_name()・ads_get_dnshostname()・ads_get_kvno()・ads_get_samaccountname()・asprintf()・ctx・global_myname・lp_workgroup()・password・secrets_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.c の 378 行で定義されています。
参照先 ads_clear_service_principal_names()・ads_get_kvno()・global_myname・smb_krb5_kt_free_entry().
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.c の 487 行で定義されています。
参照先 ads_get_kvno()・ads_get_samaccountname()・ads_get_upn()・ads_keytab_add_entry()・ctx・global_myname・smb_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 }