libads/kerberos.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    kerberos utility library
00004    Copyright (C) Andrew Tridgell 2001
00005    Copyright (C) Remus Koos 2001
00006    Copyright (C) Nalin Dahyabhai <nalin@redhat.com> 2004.
00007    Copyright (C) Jeremy Allison 2004.
00008    Copyright (C) Gerald Carter 2006.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 
00027 #ifdef HAVE_KRB5
00028 
00029 #define LIBADS_CCACHE_NAME "MEMORY:libads"
00030 
00031 /*
00032   we use a prompter to avoid a crash bug in the kerberos libs when 
00033   dealing with empty passwords
00034   this prompter is just a string copy ...
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   simulate a kinit, putting the tgt in the given cache location. If cache_name == NULL
00060   place in default cache location.
00061   remus@snapserver.com
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         /* insane testing */
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 /* run kinit to setup our ccache */
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                 /* this will end up getting a ticket for DOMAIN@RUSTED.REA.LM */
00201                 account_name = lp_workgroup();
00202         } else {
00203                 /* always use the sAMAccountName for security = domain */
00204                 /* global_myname()$@REA.LM */
00205                 if ( lp_security() == SEC_DOMAIN ) {
00206                         fstr_sprintf( acct_name, "%s$", global_myname() );
00207                         account_name = acct_name;
00208                 }
00209                 else 
00210                         /* This looks like host/global_myname()@REA.LM */
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  Routine to fetch the salting principal for a service.  Active
00272  Directory may use a non-obvious principal name to generate the salt
00273  when it determines the key to use for encrypting tickets for a service,
00274  and hopefully we detected that when we joined the domain.
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  Return the standard DES salt key
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  Routine to get the default realm from the kerberos credentials cache.
00367  Caller must free if the return value is not NULL.
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  Routine to get the salting principal for this service.  This is 
00423  maintained for backwards compatibilty with releases prior to 3.0.24.
00424  Since we store the salting principal string only at join, we may have 
00425  to look for the older tdb keys.  Caller must free if return is not null.
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         /* lookup new key first */
00436 
00437         if ( (salt_princ_s = kerberos_secrets_fetch_des_salt()) == NULL ) {
00438         
00439                 /* look under the old key.  If this fails, just use the standard key */
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                         /* fall back to host/machine.realm@REALM */
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  Routine to set the salting principal for this service.  Active
00462  Directory may use a non-obvious principal name to generate the salt
00463  when it determines the key to use for encrypting tickets for a service,
00464  and hopefully we detected that when we joined the domain.
00465  Setting principal to NULL deletes this entry.
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  Create a string list of available kdc's, possibly searching by sitename.
00547  Does DNS queries.
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         /* Get the KDC's only in this site. */
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                         /* Append to the string - inefficient but not done often. */
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         /* Get all KDC's. */
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                 /* Ensure this isn't an IP already seen (YUK! this is n*n....) */
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                         /* As the lists are sorted we can break early if nonsite > site. */
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                 /* Append to the string - inefficient but not done often. */
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  Create  a specific krb5.conf file in the private directory pointing
00631  at a specific kdc for a realm. Keyed off domain name. Sets
00632  KRB5_CONFIG environment variable to point to this file. Must be
00633  run as root or will fail (which is a good thing :-).
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         /* Set the environment variable to this file. */
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         /* Insanity, sheer insanity..... */
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                         /* Symlink already exists. */
00765                         TALLOC_FREE(dname);
00766                         return True;
00767                 }
00768 
00769                 /* Try and replace with a symlink. */
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; /* Not a fatal error. */
00777                         }
00778 
00779                         pstrcpy(linkpath, SYSTEM_KRB5_CONF_PATH);
00780                         pstrcat(linkpath, ".saved");
00781 
00782                         /* Yes, this is a race conditon... too bad. */
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; /* Not a fatal error. */
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; /* Not a fatal error. */
00798                         }
00799                 }
00800         }
00801 #endif
00802 
00803         TALLOC_FREE(dname);
00804 
00805         return True;
00806 }
00807 #endif

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