Changeset 745 for trunk/server/source3/libads/kerberos_keytab.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/libads/kerberos_keytab.c
r414 r745 28 28 #include "includes.h" 29 29 #include "smb_krb5.h" 30 #include "ads.h" 31 #include "secrets.h" 30 32 31 33 #ifdef HAVE_KRB5 … … 34 36 **********************************************************************/ 35 37 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) 38 static 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) 44 45 { 45 krb5_error_code ret = 0;46 krb5_error_code ret; 46 47 krb5_kt_cursor cursor; 48 krb5_kt_cursor zero_csr; 47 49 krb5_keytab_entry kt_entry; 48 krb5_principal princ = NULL; 49 int i; 50 krb5_keytab_entry zero_kt_entry; 50 51 char *ktprinc = NULL; 51 52 53 ZERO_STRUCT(cursor); 54 ZERO_STRUCT(zero_csr); 52 55 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 62 58 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); 69 72 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))); 72 76 goto out; 73 77 } 74 78 75 /*---------------------------------------------------------------------------76 * Save the entries with kvno - 1. This is what microsoft does77 * to allow people with existing sessions that have kvno - 1 to still78 * work. Otherwise, when the password for the machine changes, all79 * kerberizied sessions will 'break' until either the client reboots or80 * the client's session key expires and they get a new session ticket81 * with the new kvno.82 */83 84 79 #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); 86 82 #else 87 compare_name_ok = (strcmp(ktprinc, princ_s) == 0);83 name_ok = (strcmp(ktprinc, princ_s) == 0); 88 84 #endif 89 85 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; 93 106 } 94 107 95 108 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)); 146 137 147 138 ret = krb5_kt_end_seq_get(context, keytab, &cursor); 148 139 ZERO_STRUCT(cursor); 149 140 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); 178 162 ZERO_STRUCT(kt_entry); 179 163 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 } 185 169 186 170 out: 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; 207 181 } 208 182 … … 212 186 const char *princ_s, 213 187 krb5_enctype *enctypes, 214 krb5_data password) 188 krb5_data password, 189 bool no_salt, 190 bool keep_old_entries) 215 191 { 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 245 out: 246 if (princ) { 247 krb5_free_principal(context, princ); 248 } 249 250 return (int)ret; 224 251 } 225 252 … … 235 262 krb5_data password; 236 263 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; 239 272 char *password_s = NULL; 240 273 char *my_fqdn; 241 TALLOC_CTX * ctx = NULL;274 TALLOC_CTX *tmpctx = NULL; 242 275 char *machine_name; 243 244 #if defined(ENCTYPE_ARCFOUR_HMAC) 245 enctypes[2] = ENCTYPE_ARCFOUR_HMAC; 246 #endif 276 ADS_STATUS aderr; 247 277 248 278 initialize_krb5_error_table(); 249 279 ret = krb5_init_context(&context); 250 280 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))); 252 283 return -1; 253 284 } … … 255 286 ret = smb_krb5_open_keytab(context, NULL, True, &keytab); 256 287 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))); 258 290 goto out; 259 291 } … … 261 293 /* retrieve the password */ 262 294 if (!secrets_init()) { 263 DEBUG(1, ("ads_keytab_add_entry: secrets_init failed\n"));295 DEBUG(1, (__location__ ": secrets_init failed\n")); 264 296 ret = -1; 265 297 goto out; … … 267 299 password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); 268 300 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")); 270 302 ret = -1; 271 303 goto out; … … 276 308 277 309 /* 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; 295 331 } 296 332 /*strip the trailing '$' */ 297 333 machine_name[strlen(machine_name)-1] = '\0'; 298 334 299 335 /* Construct our principal */ 300 301 336 if (strchr_m(srvPrinc, '@')) { 302 337 /* 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) { 304 340 ret = -1; 305 341 goto out; … … 307 343 } else if (srvPrinc[strlen(srvPrinc)-1] == '$') { 308 344 /* 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) { 310 348 ret = -1; 311 349 goto out; … … 315 353 * can obtain credentials for it and double-check the salt value 316 354 * 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) { 319 359 ret = -1; 320 360 goto out; 321 361 } 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) { 323 366 ret = -1; 324 367 goto out; 325 368 } 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")); 337 385 goto out; 338 386 } … … 340 388 } 341 389 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 349 399 /* 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 357 408 /* 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")); 363 416 goto out; 364 417 } … … 366 419 367 420 out: 368 SAFE_FREE( princ_s ); 369 SAFE_FREE( short_princ_s ); 370 TALLOC_FREE( ctx ); 371 421 TALLOC_FREE(tmpctx); 422 372 423 if (keytab) { 373 424 krb5_kt_close(context, keytab); … … 388 439 krb5_context context = NULL; 389 440 krb5_keytab keytab = NULL; 390 krb5_kt_cursor cursor;391 krb5_keytab_entry kt_entry;392 441 krb5_kvno kvno; 393 394 ZERO_STRUCT(kt_entry); 395 ZERO_STRUCT(cursor); 442 ADS_STATUS aderr; 396 443 397 444 initialize_krb5_error_table(); 398 445 ret = krb5_init_context(&context); 399 446 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))); 401 449 return ret; 402 450 } … … 404 452 ret = smb_krb5_open_keytab(context, NULL, True, &keytab); 405 453 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")); 450 477 goto out; 451 478 } 452 479 453 480 out: 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 }469 481 if (keytab) { 470 482 krb5_kt_close(context, keytab); … … 491 503 char *sam_account_name, *upn; 492 504 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 495 528 496 529 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 smbd509 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 #endif516 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 to531 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 565 530 ZERO_STRUCT(kt_entry); 566 531 ZERO_STRUCT(cursor); … … 569 534 ret = krb5_init_context(&context); 570 535 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))); 573 538 return ret; 574 539 } 575 540 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 576 597 ret = smb_krb5_open_keytab(context, NULL, True, &keytab); 577 598 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))); 579 601 goto done; 580 602 } … … 582 604 ret = krb5_kt_start_seq_get(context, keytab, &cursor); 583 605 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) { 585 608 smb_krb5_kt_free_entry(context, &kt_entry); 586 609 ZERO_STRUCT(kt_entry); … … 592 615 593 616 /* 594 * Hmmm. There is no "rewind" function for the keytab. This means we have a race condition595 * where someone else could add entries after we've counted them. Re-open asap to minimise596 * 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. 597 620 */ 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)); 600 622 if (!found) { 601 623 goto done; 602 624 } 603 oldEntries = talloc_array(ctx, char *, found ); 625 626 oldEntries = talloc_array(tmpctx, char *, found); 604 627 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")); 606 630 ret = -1; 607 631 goto done; … … 610 634 611 635 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; 623 677 } 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)) { 649 679 TALLOC_FREE(ktprinc); 680 break; 650 681 } 651 682 } 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); 662 696 ZERO_STRUCT(cursor); 663 697 664 698 done: 665 666 699 TALLOC_FREE(oldEntries); 667 TALLOC_FREE( ctx);700 TALLOC_FREE(tmpctx); 668 701 669 702 { 670 703 krb5_keytab_entry zero_kt_entry; 671 704 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))) { 673 707 smb_krb5_kt_free_entry(context, &kt_entry); 674 708 } … … 677 711 krb5_kt_cursor zero_csr; 678 712 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); 681 716 } 682 717 } … … 708 743 ret = krb5_init_context(&context); 709 744 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))); 711 747 return ret; 712 748 } … … 714 750 ret = smb_krb5_open_keytab(context, keytab_name, False, &keytab); 715 751 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))); 717 754 goto out; 718 755 } … … 720 757 ret = krb5_kt_start_seq_get(context, keytab, &cursor); 721 758 if (ret) { 759 ZERO_STRUCT(cursor); 722 760 goto out; 723 761 } … … 726 764 727 765 while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) { 728 766 729 767 char *princ_s = NULL; 730 768 char *etype_s = NULL; 731 769 krb5_enctype enctype = 0; 732 770 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); 734 773 if (ret) { 735 774 goto out; … … 739 778 740 779 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; 747 784 } 748 785 … … 771 808 krb5_keytab_entry zero_kt_entry; 772 809 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))) { 774 812 smb_krb5_kt_free_entry(context, &kt_entry); 775 813 } … … 778 816 krb5_kt_cursor zero_csr; 779 817 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); 782 821 } 783 822 }
Note:
See TracChangeset
for help on using the changeset viewer.