00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026
00027 #ifdef HAVE_KRB5
00028
00029 #define LIBADS_CCACHE_NAME "MEMORY:libads"
00030
00031
00032
00033
00034
00035
00036 static krb5_error_code
00037 kerb_prompter(krb5_context ctx, void *data,
00038 const char *name,
00039 const char *banner,
00040 int num_prompts,
00041 krb5_prompt prompts[])
00042 {
00043 if (num_prompts == 0) return 0;
00044
00045 memset(prompts[0].reply->data, '\0', prompts[0].reply->length);
00046 if (prompts[0].reply->length > 0) {
00047 if (data) {
00048 strncpy(prompts[0].reply->data, (const char *)data,
00049 prompts[0].reply->length-1);
00050 prompts[0].reply->length = strlen(prompts[0].reply->data);
00051 } else {
00052 prompts[0].reply->length = 0;
00053 }
00054 }
00055 return 0;
00056 }
00057
00058
00059
00060
00061
00062
00063 int kerberos_kinit_password_ext(const char *principal,
00064 const char *password,
00065 int time_offset,
00066 time_t *expire_time,
00067 time_t *renew_till_time,
00068 const char *cache_name,
00069 BOOL request_pac,
00070 BOOL add_netbios_addr,
00071 time_t renewable_time)
00072 {
00073 krb5_context ctx = NULL;
00074 krb5_error_code code = 0;
00075 krb5_ccache cc = NULL;
00076 krb5_principal me;
00077 krb5_creds my_creds;
00078 krb5_get_init_creds_opt *opt = NULL;
00079 smb_krb5_addresses *addr = NULL;
00080
00081 initialize_krb5_error_table();
00082 if ((code = krb5_init_context(&ctx)))
00083 return code;
00084
00085 if (time_offset != 0) {
00086 krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
00087 }
00088
00089 DEBUG(10,("kerberos_kinit_password: using [%s] as ccache and config [%s]\n",
00090 cache_name ? cache_name: krb5_cc_default_name(ctx),
00091 getenv("KRB5_CONFIG")));
00092
00093 if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) {
00094 krb5_free_context(ctx);
00095 return code;
00096 }
00097
00098 if ((code = smb_krb5_parse_name(ctx, principal, &me))) {
00099 krb5_cc_close(ctx, cc);
00100 krb5_free_context(ctx);
00101 return code;
00102 }
00103
00104 code = smb_krb5_get_init_creds_opt_alloc(ctx, &opt);
00105 if (code) {
00106 krb5_cc_close(ctx, cc);
00107 krb5_free_context(ctx);
00108 return code;
00109 }
00110
00111 krb5_get_init_creds_opt_set_renew_life(opt, renewable_time);
00112 krb5_get_init_creds_opt_set_forwardable(opt, True);
00113 #if 0
00114
00115 krb5_get_init_creds_opt_set_tkt_life(opt, 60);
00116 #endif
00117
00118 #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
00119 if (request_pac) {
00120 code = krb5_get_init_creds_opt_set_pac_request(ctx, opt, (krb5_boolean)request_pac);
00121 if (code) {
00122 krb5_cc_close(ctx, cc);
00123 krb5_free_principal(ctx, me);
00124 krb5_free_context(ctx);
00125 return code;
00126 }
00127 }
00128 #endif
00129 if (add_netbios_addr) {
00130 code = smb_krb5_gen_netbios_krb5_address(&addr);
00131 if (code) {
00132 krb5_cc_close(ctx, cc);
00133 krb5_free_principal(ctx, me);
00134 krb5_free_context(ctx);
00135 return code;
00136 }
00137 krb5_get_init_creds_opt_set_address_list(opt, addr->addrs);
00138 }
00139
00140 if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),
00141 kerb_prompter, CONST_DISCARD(char *,password),
00142 0, NULL, opt)))
00143 {
00144 smb_krb5_get_init_creds_opt_free(ctx, opt);
00145 smb_krb5_free_addresses(ctx, addr);
00146 krb5_cc_close(ctx, cc);
00147 krb5_free_principal(ctx, me);
00148 krb5_free_context(ctx);
00149 return code;
00150 }
00151
00152 smb_krb5_get_init_creds_opt_free(ctx, opt);
00153
00154 if ((code = krb5_cc_initialize(ctx, cc, me))) {
00155 smb_krb5_free_addresses(ctx, addr);
00156 krb5_free_cred_contents(ctx, &my_creds);
00157 krb5_cc_close(ctx, cc);
00158 krb5_free_principal(ctx, me);
00159 krb5_free_context(ctx);
00160 return code;
00161 }
00162
00163 if ((code = krb5_cc_store_cred(ctx, cc, &my_creds))) {
00164 krb5_cc_close(ctx, cc);
00165 smb_krb5_free_addresses(ctx, addr);
00166 krb5_free_cred_contents(ctx, &my_creds);
00167 krb5_free_principal(ctx, me);
00168 krb5_free_context(ctx);
00169 return code;
00170 }
00171
00172 if (expire_time) {
00173 *expire_time = (time_t) my_creds.times.endtime;
00174 }
00175
00176 if (renew_till_time) {
00177 *renew_till_time = (time_t) my_creds.times.renew_till;
00178 }
00179
00180 krb5_cc_close(ctx, cc);
00181 smb_krb5_free_addresses(ctx, addr);
00182 krb5_free_cred_contents(ctx, &my_creds);
00183 krb5_free_principal(ctx, me);
00184 krb5_free_context(ctx);
00185
00186 return 0;
00187 }
00188
00189
00190
00191
00192 int ads_kinit_password(ADS_STRUCT *ads)
00193 {
00194 char *s;
00195 int ret;
00196 const char *account_name;
00197 fstring acct_name;
00198
00199 if ( IS_DC ) {
00200
00201 account_name = lp_workgroup();
00202 } else {
00203
00204
00205 if ( lp_security() == SEC_DOMAIN ) {
00206 fstr_sprintf( acct_name, "%s$", global_myname() );
00207 account_name = acct_name;
00208 }
00209 else
00210
00211 account_name = ads->auth.user_name;
00212 }
00213
00214 if (asprintf(&s, "%s@%s", account_name, ads->auth.realm) == -1) {
00215 return KRB5_CC_NOMEM;
00216 }
00217
00218 if (!ads->auth.password) {
00219 SAFE_FREE(s);
00220 return KRB5_LIBOS_CANTREADPWD;
00221 }
00222
00223 ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset,
00224 &ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable);
00225
00226 if (ret) {
00227 DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
00228 s, error_message(ret)));
00229 }
00230 SAFE_FREE(s);
00231 return ret;
00232 }
00233
00234 int ads_kdestroy(const char *cc_name)
00235 {
00236 krb5_error_code code;
00237 krb5_context ctx = NULL;
00238 krb5_ccache cc = NULL;
00239
00240 initialize_krb5_error_table();
00241 if ((code = krb5_init_context (&ctx))) {
00242 DEBUG(3, ("ads_kdestroy: kdb5_init_context failed: %s\n",
00243 error_message(code)));
00244 return code;
00245 }
00246
00247 if (!cc_name) {
00248 if ((code = krb5_cc_default(ctx, &cc))) {
00249 krb5_free_context(ctx);
00250 return code;
00251 }
00252 } else {
00253 if ((code = krb5_cc_resolve(ctx, cc_name, &cc))) {
00254 DEBUG(3, ("ads_kdestroy: krb5_cc_resolve failed: %s\n",
00255 error_message(code)));
00256 krb5_free_context(ctx);
00257 return code;
00258 }
00259 }
00260
00261 if ((code = krb5_cc_destroy (ctx, cc))) {
00262 DEBUG(3, ("ads_kdestroy: krb5_cc_destroy failed: %s\n",
00263 error_message(code)));
00264 }
00265
00266 krb5_free_context (ctx);
00267 return code;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 static char *kerberos_secrets_fetch_salting_principal(const char *service, int enctype)
00278 {
00279 char *key = NULL;
00280 char *ret = NULL;
00281
00282 asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, service, enctype);
00283 if (!key) {
00284 return NULL;
00285 }
00286 ret = (char *)secrets_fetch(key, NULL);
00287 SAFE_FREE(key);
00288 return ret;
00289 }
00290
00291
00292
00293
00294
00295 char* kerberos_standard_des_salt( void )
00296 {
00297 fstring salt;
00298
00299 fstr_sprintf( salt, "host/%s.%s@", global_myname(), lp_realm() );
00300 strlower_m( salt );
00301 fstrcat( salt, lp_realm() );
00302
00303 return SMB_STRDUP( salt );
00304 }
00305
00306
00307
00308
00309 static char* des_salt_key( void )
00310 {
00311 char *key;
00312
00313 asprintf(&key, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, lp_realm());
00314
00315 return key;
00316 }
00317
00318
00319
00320
00321 BOOL kerberos_secrets_store_des_salt( const char* salt )
00322 {
00323 char* key;
00324 BOOL ret;
00325
00326 if ( (key = des_salt_key()) == NULL ) {
00327 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
00328 return False;
00329 }
00330
00331 if ( !salt ) {
00332 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
00333 secrets_delete( key );
00334 return True;
00335 }
00336
00337 DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt));
00338
00339 ret = secrets_store( key, salt, strlen(salt)+1 );
00340
00341 SAFE_FREE( key );
00342
00343 return ret;
00344 }
00345
00346
00347
00348
00349 char* kerberos_secrets_fetch_des_salt( void )
00350 {
00351 char *salt, *key;
00352
00353 if ( (key = des_salt_key()) == NULL ) {
00354 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
00355 return False;
00356 }
00357
00358 salt = (char*)secrets_fetch( key, NULL );
00359
00360 SAFE_FREE( key );
00361
00362 return salt;
00363 }
00364
00365
00366
00367
00368
00369
00370 char *kerberos_get_default_realm_from_ccache( void )
00371 {
00372 char *realm = NULL;
00373 krb5_context ctx = NULL;
00374 krb5_ccache cc = NULL;
00375 krb5_principal princ = NULL;
00376
00377 initialize_krb5_error_table();
00378 if (krb5_init_context(&ctx)) {
00379 return NULL;
00380 }
00381
00382 DEBUG(5,("kerberos_get_default_realm_from_ccache: "
00383 "Trying to read krb5 cache: %s\n",
00384 krb5_cc_default_name(ctx)));
00385 if (krb5_cc_default(ctx, &cc)) {
00386 DEBUG(0,("kerberos_get_default_realm_from_ccache: "
00387 "failed to read default cache\n"));
00388 goto out;
00389 }
00390 if (krb5_cc_get_principal(ctx, cc, &princ)) {
00391 DEBUG(0,("kerberos_get_default_realm_from_ccache: "
00392 "failed to get default principal\n"));
00393 goto out;
00394 }
00395
00396 #if defined(HAVE_KRB5_PRINCIPAL_GET_REALM)
00397 realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ));
00398 #elif defined(HAVE_KRB5_PRINC_REALM)
00399 {
00400 krb5_data *realm_data = krb5_princ_realm(ctx, princ);
00401 realm = SMB_STRNDUP(realm_data->data, realm_data->length);
00402 }
00403 #endif
00404
00405 out:
00406
00407 if (princ) {
00408 krb5_free_principal(ctx, princ);
00409 }
00410 if (cc) {
00411 krb5_cc_close(ctx, cc);
00412 }
00413 if (ctx) {
00414 krb5_free_context(ctx);
00415 }
00416
00417 return realm;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context,
00429 krb5_principal host_princ,
00430 int enctype)
00431 {
00432 char *unparsed_name = NULL, *salt_princ_s = NULL;
00433 krb5_principal ret_princ = NULL;
00434
00435
00436
00437 if ( (salt_princ_s = kerberos_secrets_fetch_des_salt()) == NULL ) {
00438
00439
00440
00441 if (smb_krb5_unparse_name(context, host_princ, &unparsed_name) != 0) {
00442 return (krb5_principal)NULL;
00443 }
00444 if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) {
00445
00446 salt_princ_s = kerberos_standard_des_salt();
00447 }
00448 }
00449
00450 if (smb_krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) {
00451 ret_princ = NULL;
00452 }
00453
00454 SAFE_FREE(unparsed_name);
00455 SAFE_FREE(salt_princ_s);
00456
00457 return ret_princ;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 BOOL kerberos_secrets_store_salting_principal(const char *service,
00469 int enctype,
00470 const char *principal)
00471 {
00472 char *key = NULL;
00473 BOOL ret = False;
00474 krb5_context context = NULL;
00475 krb5_principal princ = NULL;
00476 char *princ_s = NULL;
00477 char *unparsed_name = NULL;
00478
00479 krb5_init_context(&context);
00480 if (!context) {
00481 return False;
00482 }
00483 if (strchr_m(service, '@')) {
00484 asprintf(&princ_s, "%s", service);
00485 } else {
00486 asprintf(&princ_s, "%s@%s", service, lp_realm());
00487 }
00488
00489 if (smb_krb5_parse_name(context, princ_s, &princ) != 0) {
00490 goto out;
00491
00492 }
00493 if (smb_krb5_unparse_name(context, princ, &unparsed_name) != 0) {
00494 goto out;
00495 }
00496
00497 asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, unparsed_name, enctype);
00498 if (!key) {
00499 goto out;
00500 }
00501
00502 if ((principal != NULL) && (strlen(principal) > 0)) {
00503 ret = secrets_store(key, principal, strlen(principal) + 1);
00504 } else {
00505 ret = secrets_delete(key);
00506 }
00507
00508 out:
00509
00510 SAFE_FREE(key);
00511 SAFE_FREE(princ_s);
00512 SAFE_FREE(unparsed_name);
00513
00514 if (princ) {
00515 krb5_free_principal(context, princ);
00516 }
00517
00518 if (context) {
00519 krb5_free_context(context);
00520 }
00521
00522 return ret;
00523 }
00524
00525
00526
00527
00528
00529 int kerberos_kinit_password(const char *principal,
00530 const char *password,
00531 int time_offset,
00532 const char *cache_name)
00533 {
00534 return kerberos_kinit_password_ext(principal,
00535 password,
00536 time_offset,
00537 0,
00538 0,
00539 cache_name,
00540 False,
00541 False,
00542 0);
00543 }
00544
00545
00546
00547
00548
00549
00550 static char *get_kdc_ip_string(char *mem_ctx, const char *realm, const char *sitename, struct in_addr primary_ip)
00551 {
00552 int i;
00553 struct ip_service *ip_srv_site = NULL;
00554 struct ip_service *ip_srv_nonsite;
00555 int count_site = 0;
00556 int count_nonsite;
00557 char *kdc_str = talloc_asprintf(mem_ctx, "\tkdc = %s\n",
00558 inet_ntoa(primary_ip));
00559
00560 if (kdc_str == NULL) {
00561 return NULL;
00562 }
00563
00564
00565
00566 if (sitename) {
00567
00568 get_kdc_list(realm, sitename, &ip_srv_site, &count_site);
00569
00570 for (i = 0; i < count_site; i++) {
00571 if (ip_equal(ip_srv_site[i].ip, primary_ip)) {
00572 continue;
00573 }
00574
00575 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
00576 kdc_str, inet_ntoa(ip_srv_site[i].ip));
00577 if (!kdc_str) {
00578 SAFE_FREE(ip_srv_site);
00579 return NULL;
00580 }
00581 }
00582 }
00583
00584
00585
00586 get_kdc_list(realm, NULL, &ip_srv_nonsite, &count_nonsite);
00587
00588 for (i = 0; i < count_nonsite; i++) {
00589 int j;
00590
00591 if (ip_equal(ip_srv_nonsite[i].ip, primary_ip)) {
00592 continue;
00593 }
00594
00595
00596 for (j = 0; j < count_site; j++) {
00597 if (ip_equal(ip_srv_nonsite[i].ip, ip_srv_site[j].ip)) {
00598 break;
00599 }
00600
00601 if (ip_service_compare(&ip_srv_nonsite[i], &ip_srv_site[j]) > 0) {
00602 break;
00603 }
00604 }
00605 if (j != i) {
00606 continue;
00607 }
00608
00609
00610 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",
00611 kdc_str, inet_ntoa(ip_srv_nonsite[i].ip));
00612 if (!kdc_str) {
00613 SAFE_FREE(ip_srv_site);
00614 SAFE_FREE(ip_srv_nonsite);
00615 return NULL;
00616 }
00617 }
00618
00619
00620 SAFE_FREE(ip_srv_site);
00621 SAFE_FREE(ip_srv_nonsite);
00622
00623 DEBUG(10,("get_kdc_ip_string: Returning %s\n",
00624 kdc_str ));
00625
00626 return kdc_str;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636 BOOL create_local_private_krb5_conf_for_domain(const char *realm, const char *domain,
00637 const char *sitename, struct in_addr ip)
00638 {
00639 char *dname = talloc_asprintf(NULL, "%s/smb_krb5", lp_lockdir());
00640 char *tmpname = NULL;
00641 char *fname = NULL;
00642 char *file_contents = NULL;
00643 char *kdc_ip_string = NULL;
00644 size_t flen = 0;
00645 ssize_t ret;
00646 int fd;
00647 char *realm_upper = NULL;
00648
00649 if (!dname) {
00650 return False;
00651 }
00652 if ((mkdir(dname, 0755)==-1) && (errno != EEXIST)) {
00653 DEBUG(0,("create_local_private_krb5_conf_for_domain: "
00654 "failed to create directory %s. Error was %s\n",
00655 dname, strerror(errno) ));
00656 TALLOC_FREE(dname);
00657 return False;
00658 }
00659
00660 tmpname = talloc_asprintf(dname, "%s/smb_tmp_krb5.XXXXXX", lp_lockdir());
00661 if (!tmpname) {
00662 TALLOC_FREE(dname);
00663 return False;
00664 }
00665
00666 fname = talloc_asprintf(dname, "%s/krb5.conf.%s", dname, domain);
00667 if (!fname) {
00668 TALLOC_FREE(dname);
00669 return False;
00670 }
00671
00672 DEBUG(10,("create_local_private_krb5_conf_for_domain: fname = %s, realm = %s, domain = %s\n",
00673 fname, realm, domain ));
00674
00675 realm_upper = talloc_strdup(fname, realm);
00676 strupper_m(realm_upper);
00677
00678 kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, ip);
00679 if (!kdc_ip_string) {
00680 TALLOC_FREE(dname);
00681 return False;
00682 }
00683
00684 file_contents = talloc_asprintf(fname,
00685 "[libdefaults]\n\tdefault_realm = %s\n"
00686 "default_tgs_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
00687 "default_tkt_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n"
00688 "preferred_enctypes = RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n"
00689 "[realms]\n\t%s = {\n"
00690 "\t%s\t}\n",
00691 realm_upper, realm_upper, kdc_ip_string);
00692
00693 if (!file_contents) {
00694 TALLOC_FREE(dname);
00695 return False;
00696 }
00697
00698 flen = strlen(file_contents);
00699
00700 fd = smb_mkstemp(tmpname);
00701 if (fd == -1) {
00702 DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed,"
00703 " for file %s. Errno %s\n",
00704 tmpname, strerror(errno) ));
00705 }
00706
00707 if (fchmod(fd, 0644)==-1) {
00708 DEBUG(0,("create_local_private_krb5_conf_for_domain: fchmod failed for %s."
00709 " Errno %s\n",
00710 tmpname, strerror(errno) ));
00711 unlink(tmpname);
00712 close(fd);
00713 TALLOC_FREE(dname);
00714 return False;
00715 }
00716
00717 ret = write(fd, file_contents, flen);
00718 if (flen != ret) {
00719 DEBUG(0,("create_local_private_krb5_conf_for_domain: write failed,"
00720 " returned %d (should be %u). Errno %s\n",
00721 (int)ret, (unsigned int)flen, strerror(errno) ));
00722 unlink(tmpname);
00723 close(fd);
00724 TALLOC_FREE(dname);
00725 return False;
00726 }
00727 if (close(fd)==-1) {
00728 DEBUG(0,("create_local_private_krb5_conf_for_domain: close failed."
00729 " Errno %s\n", strerror(errno) ));
00730 unlink(tmpname);
00731 TALLOC_FREE(dname);
00732 return False;
00733 }
00734
00735 if (rename(tmpname, fname) == -1) {
00736 DEBUG(0,("create_local_private_krb5_conf_for_domain: rename "
00737 "of %s to %s failed. Errno %s\n",
00738 tmpname, fname, strerror(errno) ));
00739 unlink(tmpname);
00740 TALLOC_FREE(dname);
00741 return False;
00742 }
00743
00744 DEBUG(5,("create_local_private_krb5_conf_for_domain: wrote "
00745 "file %s with realm %s KDC = %s\n",
00746 fname, realm_upper, inet_ntoa(ip) ));
00747
00748
00749 setenv("KRB5_CONFIG", fname, 1);
00750
00751 #if defined(OVERWRITE_SYSTEM_KRB5_CONF)
00752
00753 #define SYSTEM_KRB5_CONF_PATH "/etc/krb5.conf"
00754
00755
00756 if (strequal(realm, lp_realm())) {
00757 pstring linkpath;
00758 int lret;
00759
00760 lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath, sizeof(linkpath)-1);
00761 linkpath[sizeof(pstring)-1] = '\0';
00762
00763 if (lret == 0 || strcmp(linkpath, fname) == 0) {
00764
00765 TALLOC_FREE(dname);
00766 return True;
00767 }
00768
00769
00770 if (symlink(fname, SYSTEM_KRB5_CONF_PATH) == -1) {
00771 if (errno != EEXIST) {
00772 DEBUG(0,("create_local_private_krb5_conf_for_domain: symlink "
00773 "of %s to %s failed. Errno %s\n",
00774 fname, SYSTEM_KRB5_CONF_PATH, strerror(errno) ));
00775 TALLOC_FREE(dname);
00776 return True;
00777 }
00778
00779 pstrcpy(linkpath, SYSTEM_KRB5_CONF_PATH);
00780 pstrcat(linkpath, ".saved");
00781
00782
00783 if (rename(SYSTEM_KRB5_CONF_PATH, linkpath) == -1) {
00784 DEBUG(0,("create_local_private_krb5_conf_for_domain: rename "
00785 "of %s to %s failed. Errno %s\n",
00786 SYSTEM_KRB5_CONF_PATH, linkpath,
00787 strerror(errno) ));
00788 TALLOC_FREE(dname);
00789 return True;
00790 }
00791
00792 if (symlink(fname, "/etc/krb5.conf") == -1) {
00793 DEBUG(0,("create_local_private_krb5_conf_for_domain: "
00794 "forced symlink of %s to /etc/krb5.conf failed. Errno %s\n",
00795 fname, strerror(errno) ));
00796 TALLOC_FREE(dname);
00797 return True;
00798 }
00799 }
00800 }
00801 #endif
00802
00803 TALLOC_FREE(dname);
00804
00805 return True;
00806 }
00807 #endif