Пример #1
0
static void
test_storagedir_empty(void *arg)
{
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  (void)arg;

  tt_int_op(FN_NOENT, OP_EQ, file_status(dirname));

  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tt_int_op(FN_DIR, OP_EQ, file_status(dirname));

  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

  storage_dir_free(d);
  d = storage_dir_new(dirname, 10);
  tt_assert(d);

  tt_int_op(FN_DIR, OP_EQ, file_status(dirname));

  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

 done:
  storage_dir_free(d);
  tor_free(dirname);
}
Пример #2
0
static void
test_storagedir_deletion(void *arg)
{
  (void)arg;
  char *dirname = tor_strdup(get_fname_rnd("store_dir"));
  storage_dir_t *d = NULL;
  char *fn1 = NULL, *fn2 = NULL;
  char *bytes = NULL;
  int r;
  const char str1[] = "There are nine and sixty ways to disguise communiques";
  const char str2[] = "And rather more than one of them is right";

  // Make sure the directory is there. */
  d = storage_dir_new(dirname, 10);
  storage_dir_free(d);
  d = NULL;

  tor_asprintf(&fn1, "%s/1007", dirname);
  r = write_str_to_file(fn1, str1, 0);
  tt_int_op(r, OP_EQ, 0);

  tor_asprintf(&fn2, "%s/1003.tmp", dirname);
  r = write_str_to_file(fn2, str2, 0);
  tt_int_op(r, OP_EQ, 0);

  // The tempfile should be deleted the next time we list the directory.
  d = storage_dir_new(dirname, 10);
  tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));
  tt_int_op(FN_FILE, OP_EQ, file_status(fn1));
  tt_int_op(FN_NOENT, OP_EQ, file_status(fn2));

  bytes = (char*) storage_dir_read(d, "1007", 1, NULL);
  tt_str_op(bytes, OP_EQ, str1);

  // Should have no effect; file already gone.
  storage_dir_remove_file(d, "1003.tmp");
  tt_int_op(1, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(strlen(str1), OP_EQ, storage_dir_get_usage(d));

  // Actually remove a file.
  storage_dir_remove_file(d, "1007");
  tt_int_op(FN_NOENT, OP_EQ, file_status(fn1));
  tt_int_op(0, OP_EQ, smartlist_len(storage_dir_list(d)));
  tt_u64_op(0, OP_EQ, storage_dir_get_usage(d));

 done:
  tor_free(dirname);
  tor_free(fn1);
  tor_free(fn2);
  storage_dir_free(d);
  tor_free(bytes);
}
Пример #3
0
/**
 * Save a broken state file to a backup location.
 */
static void
or_state_save_broken(char *fname)
{
  int i;
  file_status_t status;
  char *fname2 = NULL;
  for (i = 0; i < 100; ++i) {
    tor_asprintf(&fname2, "%s.%d", fname, i);
    status = file_status(fname2);
    if (status == FN_NOENT)
      break;
    tor_free(fname2);
  }
  if (i == 100) {
    log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
             "state files to move aside. Discarding the old state file.",
             fname);
    unlink(fname);
  } else {
    log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
             "to \"%s\".  This could be a bug in Tor; please tell "
             "the developers.", fname, fname2);
    if (rename(fname, fname2) < 0) {
      log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The "
               "OS gave an error of %s", strerror(errno));
    }
  }
  tor_free(fname2);
}
Пример #4
0
file_status path<Traits>::status (path const & p)
{
	struct stat st;
	int rc = lstat(traits::c_str(p.str())(), & st);

	if (rc != 0) { // error
		if (errno == ENOENT || errno == ENOTDIR)
			return file_status(file_not_found);

		return file_status(status_error);
	}

	switch (st.st_mode & S_IFMT) {
	case S_IFREG : return file_status(regular_file);
	case S_IFDIR : return file_status(directory_file);
	case S_IFLNK : return file_status(symlink_file);
	case S_IFBLK : return file_status(block_file);
	case S_IFCHR : return file_status(character_file);
	case S_IFIFO : return file_status(fifo_file);
	case S_IFSOCK: return file_status(socket_file);
	}

	return file_status(type_unknown);
}
Пример #5
0
int simple_copyfile(const char* input_file_path,const char* output_file_path)   //执行相关拷贝动作
{
	int n;
	int filehand_src,filehand_dst;
	char buf[BUFFSIZE];
	char lf[MAX_PATH_LENGTH];
	struct stat info;
	
	file_status(input_file_path, &info);
	if(ga.need_interactive)
	{
		if(!interactivity_method(output_file_path))
		{
			return  true;
		}						
  	}else{
		overwrite = O_EXCL;
	}	
	if(ga.need_preserve == true)
	{
		if((filehand_dst = preserve_method(info,input_file_path,output_file_path)) == SUCCESS_LINK)
			return true;
	}else if(ga.need_no_deference == true){
		if(ENUM_SYMLINK == it)
		{
			input_file_path = realpath(input_file_path,lf);
			link_file(input_file_path, output_file_path);
			return true;
		}	
			
	}else if(ENUM_SYMLINK == it)
	{
		input_file_path = realpath(input_file_path,lf);
		filehand_dst = open_file(output_file_path,O_WRONLY|O_CREAT|overwrite, 0775);
	}else{
		filehand_dst = open_file(output_file_path,O_WRONLY|O_CREAT|overwrite, 0775);
	}
	filehand_src = open_file(input_file_path,O_RDONLY);
        while((n = read_file(filehand_src,buf,BUFFSIZE,input_file_path)) > 0)
		write_file(filehand_dst,buf,n,output_file_path);
	close(filehand_src);
	close(filehand_dst);		
        return true;
}
Пример #6
0
/** Try to read the identity key from <b>identity_key_file</b>.  If no such
 * file exists and create_identity_key is set, make a new identity key and
 * store it.  Return 0 on success, nonzero on failure.
 */
static int
load_identity_key(void)
{
  file_status_t status = file_status(identity_key_file);
  FILE *f;

  if (make_new_id) {
    open_file_t *open_file = NULL;
    RSA *key;
    if (status != FN_NOENT) {
      log_err(LD_GENERAL, "--create-identity-key was specified, but %s "
              "already exists.", identity_key_file);
      return 1;
    }
    log_notice(LD_GENERAL, "Generating %d-bit RSA identity key.",
               IDENTITY_KEY_BITS);
    if (!(key = generate_key(IDENTITY_KEY_BITS))) {
      log_err(LD_GENERAL, "Couldn't generate identity key.");
      crypto_log_errors(LOG_ERR, "Generating identity key");
      return 1;
    }
    identity_key = EVP_PKEY_new();
    if (!(EVP_PKEY_assign_RSA(identity_key, key))) {
      log_err(LD_GENERAL, "Couldn't assign identity key.");
      return 1;
    }

    if (!(f = start_writing_to_stdio_file(identity_key_file,
                                          OPEN_FLAGS_REPLACE | O_TEXT, 0400,
                                          &open_file)))
      return 1;

    /* Write the key to the file.  If passphrase is not set, takes it from
     * the terminal. */
    if (!PEM_write_PKCS8PrivateKey_nid(f, identity_key,
                                       NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
                                       passphrase, (int)passphrase_len,
                                       NULL, NULL)) {
      log_err(LD_GENERAL, "Couldn't write identity key to %s",
              identity_key_file);
      crypto_log_errors(LOG_ERR, "Writing identity key");
      abort_writing_to_file(open_file);
      return 1;
    }
    finish_writing_to_file(open_file);
  } else {
    if (status != FN_FILE) {
      log_err(LD_GENERAL,
              "No identity key found in %s.  To specify a location "
              "for an identity key, use -i.  To generate a new identity key, "
              "use --create-identity-key.", identity_key_file);
      return 1;
    }

    if (!(f = fopen(identity_key_file, "r"))) {
      log_err(LD_GENERAL, "Couldn't open %s for reading: %s",
              identity_key_file, strerror(errno));
      return 1;
    }

    /* Read the key.  If passphrase is not set, takes it from the terminal. */
    identity_key = PEM_read_PrivateKey(f, NULL, NULL, passphrase);
    if (!identity_key) {
      log_err(LD_GENERAL, "Couldn't read identity key from %s",
              identity_key_file);
      return 1;
    }
    fclose(f);
  }
  return 0;
}
Пример #7
0
/**
 * Read an ed25519 key and associated certificates from files beginning with
 * <b>fname</b>, with certificate type <b>cert_type</b>.  On failure, return
 * NULL; on success return the keypair.
 *
 * If INIT_ED_KEY_CREATE is set in <b>flags</b>, then create the key (and
 * certificate if requested) if it doesn't exist, and save it to disk.
 *
 * If INIT_ED_KEY_NEEDCERT is set in <b>flags</b>, load/create a certificate
 * too and store it in *<b>cert_out</b>.  Fail if the cert can't be
 * found/created.  To create a certificate, <b>signing_key</b> must be set to
 * the key that should sign it; <b>now</b> to the current time, and
 * <b>lifetime</b> to the lifetime of the key.
 *
 * If INIT_ED_KEY_REPLACE is set in <b>flags</b>, then create and save new key
 * whether we can read the old one or not.
 *
 * If INIT_ED_KEY_EXTRA_STRONG is set in <b>flags</b>, set the extra_strong
 * flag when creating the secret key.
 *
 * If INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT is set in <b>flags</b>, and
 * we create a new certificate, create it with the signing key embedded.
 *
 * If INIT_ED_KEY_SPLIT is set in <b>flags</b>, and we create a new key,
 * store the public key in a separate file from the secret key.
 *
 * If INIT_ED_KEY_MISSING_SECRET_OK is set in <b>flags</b>, and we find a
 * public key file but no secret key file, return successfully anyway.
 *
 * If INIT_ED_KEY_OMIT_SECRET is set in <b>flags</b>, do not try to load a
 * secret key unless no public key is found.  Do not return a secret key. (but
 * create and save one if needed).
 *
 * If INIT_ED_KEY_NO_LOAD_SECRET is set in <b>flags</b>, don't try to load
 * a secret key, no matter what.
 *
 * If INIT_ED_KEY_TRY_ENCRYPTED is set, we look for an encrypted secret key
 * and consider encrypting any new secret key.
 *
 * If INIT_ED_KEY_NO_REPAIR is set, and there is any issue loading the keys
 * from disk _other than their absence_ (full or partial), we do not try to
 * replace them.
 *
 * If INIT_ED_KEY_SUGGEST_KEYGEN is set, have log messages about failures
 * refer to the --keygen option.
 *
 * If INIT_ED_KEY_EXPLICIT_FNAME is set, use the provided file name for the
 * secret key file, encrypted or not.
 */
ed25519_keypair_t *
ed_key_init_from_file(const char *fname, uint32_t flags,
                      int severity,
                      const ed25519_keypair_t *signing_key,
                      time_t now,
                      time_t lifetime,
                      uint8_t cert_type,
                      struct tor_cert_st **cert_out)
{
  char *secret_fname = NULL;
  char *encrypted_secret_fname = NULL;
  char *public_fname = NULL;
  char *cert_fname = NULL;
  const char *loaded_secret_fname = NULL;
  int created_pk = 0, created_sk = 0, created_cert = 0;
  const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE);
  const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED);
  const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR);
  const int split = !! (flags & INIT_ED_KEY_SPLIT);
  const int omit_secret = !! (flags & INIT_ED_KEY_OMIT_SECRET);
  const int offline_secret = !! (flags & INIT_ED_KEY_OFFLINE_SECRET);
  const int explicit_fname = !! (flags & INIT_ED_KEY_EXPLICIT_FNAME);

  /* we don't support setting both of these flags at once. */
  tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) !=
                      (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT));

  char tag[8];
  tor_snprintf(tag, sizeof(tag), "type%d", (int)cert_type);

  tor_cert_t *cert = NULL;
  char *got_tag = NULL;
  ed25519_keypair_t *keypair = tor_malloc_zero(sizeof(ed25519_keypair_t));

  if (explicit_fname) {
    secret_fname = tor_strdup(fname);
    encrypted_secret_fname = tor_strdup(fname);
  } else {
    tor_asprintf(&secret_fname, "%s_secret_key", fname);
    tor_asprintf(&encrypted_secret_fname, "%s_secret_key_encrypted", fname);
  }
  tor_asprintf(&public_fname, "%s_public_key", fname);
  tor_asprintf(&cert_fname, "%s_cert", fname);

  /* Try to read the secret key. */
  int have_secret = 0;
  int load_secret = try_to_load &&
    !offline_secret &&
    (!omit_secret || file_status(public_fname)==FN_NOENT);
  if (load_secret) {
    int rv = ed25519_seckey_read_from_file(&keypair->seckey,
                                           &got_tag, secret_fname);
    if (rv == 0) {
      have_secret = 1;
      loaded_secret_fname = secret_fname;
      tor_assert(got_tag);
    } else {
      if (errno != ENOENT && norepair) {
        tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname,
                strerror(errno));
        goto err;
      }
    }
  }

  /* Should we try for an encrypted key? */
  int have_encrypted_secret_file = 0;
  if (!have_secret && try_to_load && encrypt_key) {
    int r = read_encrypted_secret_key(&keypair->seckey,
                                      encrypted_secret_fname);
    if (r > 0) {
      have_secret = 1;
      have_encrypted_secret_file = 1;
      tor_free(got_tag); /* convince coverity we aren't leaking */
      got_tag = tor_strdup(tag);
      loaded_secret_fname = encrypted_secret_fname;
    } else if (errno != ENOENT && norepair) {
      tor_log(severity, LD_OR, "Unable to read %s: %s",
              encrypted_secret_fname, strerror(errno));
      goto err;
    }
  } else {
    if (try_to_load) {
      /* Check if it's there anyway, so we don't replace it. */
      if (file_status(encrypted_secret_fname) != FN_NOENT)
        have_encrypted_secret_file = 1;
    }
  }

  if (have_secret) {
    if (strcmp(got_tag, tag)) {
      tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname);
      goto err;
    }
    /* Derive the public key */
    if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) {
      tor_log(severity, LD_OR, "%s can't produce a public key",
              loaded_secret_fname);
      goto err;
    }
  }

  /* If we do split keys here, try to read the pubkey. */
  int found_public = 0;
  if (try_to_load && (!have_secret || split)) {
    ed25519_public_key_t pubkey_tmp;
    tor_free(got_tag);
    found_public = ed25519_pubkey_read_from_file(&pubkey_tmp,
                                                 &got_tag, public_fname) == 0;
    if (!found_public && errno != ENOENT && norepair) {
      tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname,
              strerror(errno));
      goto err;
    }
    if (found_public && strcmp(got_tag, tag)) {
      tor_log(severity, LD_OR, "%s has wrong tag", public_fname);
      goto err;
    }
    if (found_public) {
      if (have_secret) {
        /* If we have a secret key and we're reloading the public key,
         * the key must match! */
        if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) {
          tor_log(severity, LD_OR, "%s does not match %s!  If you are trying "
                  "to restore from backup, make sure you didn't mix up the "
                  "key files. If you are absolutely sure that %s is the right "
                  "key for this relay, delete %s or move it out of the way.",
                  public_fname, loaded_secret_fname,
                  loaded_secret_fname, public_fname);
          goto err;
        }
      } else {
        /* We only have the public key; better use that. */
        tor_assert(split);
        memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp));
      }
    } else {
      /* We have no public key file, but we do have a secret key, make the
       * public key file! */
      if (have_secret) {
        if (ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag)
            < 0) {
          tor_log(severity, LD_OR, "Couldn't repair %s", public_fname);
          goto err;
        } else {
          tor_log(LOG_NOTICE, LD_OR,
                  "Found secret key but not %s. Regenerating.",
                  public_fname);
        }
      }
    }
  }

  /* If the secret key is absent and it's not allowed to be, fail. */
  if (!have_secret && found_public &&
      !(flags & INIT_ED_KEY_MISSING_SECRET_OK)) {
    if (have_encrypted_secret_file) {
      tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
              "but it was encrypted. Try 'tor --keygen' instead, so you "
              "can enter the passphrase.",
              secret_fname);
    } else {
      tor_log(severity, LD_OR, "We needed to load a secret key from %s, "
              "but couldn't find it. %s", secret_fname,
              (flags & INIT_ED_KEY_SUGGEST_KEYGEN) ?
              "If you're keeping your master secret key offline, you will "
              "need to run 'tor --keygen' to generate new signing keys." :
              "Did you forget to copy it over when you copied the rest of the "
              "signing key material?");
    }
    goto err;
  }

  /* If it's absent, and we're not supposed to make a new keypair, fail. */
  if (!have_secret && !found_public && !(flags & INIT_ED_KEY_CREATE)) {
    if (split) {
      tor_log(severity, LD_OR, "No key found in %s or %s.",
              secret_fname, public_fname);
    } else {
      tor_log(severity, LD_OR, "No key found in %s.", secret_fname);
    }
    goto err;
  }

  /* If the secret key is absent, but the encrypted key would be present,
   * that's an error */
  if (!have_secret && !found_public && have_encrypted_secret_file) {
    tor_assert(!encrypt_key);
    tor_log(severity, LD_OR, "Found an encrypted secret key, "
            "but not public key file %s!", public_fname);
    goto err;
  }

  /* if it's absent, make a new keypair... */
  if (!have_secret && !found_public) {
    tor_free(keypair);
    keypair = ed_key_new(signing_key, flags, now, lifetime,
                         cert_type, &cert);
    if (!keypair) {
      tor_log(severity, LD_OR, "Couldn't create keypair");
      goto err;
    }
    created_pk = created_sk = created_cert = 1;
  }

  /* Write it to disk if we're supposed to do with a new passphrase, or if
   * we just created it. */
  if (created_sk || (have_secret && get_options()->change_key_passphrase)) {
    if (write_secret_key(&keypair->seckey,
                         encrypt_key,
                         secret_fname, tag, encrypted_secret_fname) < 0
        ||
        (split &&
         ed25519_pubkey_write_to_file(&keypair->pubkey, public_fname, tag) < 0)
        ||
        (cert &&
         crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
                                 tag, cert->encoded, cert->encoded_len) < 0)) {
      tor_log(severity, LD_OR, "Couldn't write keys or cert to file.");
      goto err;
    }
    goto done;
  }

  /* If we're not supposed to get a cert, we're done. */
  if (! (flags & INIT_ED_KEY_NEEDCERT))
    goto done;

  /* Read a cert. */
  tor_free(got_tag);
  uint8_t certbuf[256];
  ssize_t cert_body_len = crypto_read_tagged_contents_from_file(
                 cert_fname, "ed25519v1-cert",
                 &got_tag, certbuf, sizeof(certbuf));
  if (cert_body_len >= 0 && !strcmp(got_tag, tag))
    cert = tor_cert_parse(certbuf, cert_body_len);

  /* If we got it, check it to the extent we can. */
  int bad_cert = 0;

  if (! cert) {
    tor_log(severity, LD_OR, "Cert was unparseable");
    bad_cert = 1;
  } else if (!tor_memeq(cert->signed_key.pubkey, keypair->pubkey.pubkey,
                        ED25519_PUBKEY_LEN)) {
    tor_log(severity, LD_OR, "Cert was for wrong key");
    bad_cert = 1;
  } else if (signing_key &&
             tor_cert_checksig(cert, &signing_key->pubkey, now) < 0) {
    tor_log(severity, LD_OR, "Can't check certificate");
    bad_cert = 1;
  } else if (cert->cert_expired) {
    tor_log(severity, LD_OR, "Certificate is expired");
    bad_cert = 1;
  } else if (signing_key && cert->signing_key_included &&
             ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) {
    tor_log(severity, LD_OR, "Certificate signed by unexpectd key!");
    bad_cert = 1;
  }

  if (bad_cert) {
    tor_cert_free(cert);
    cert = NULL;
  }

  /* If we got a cert, we're done. */
  if (cert)
    goto done;

  /* If we didn't get a cert, and we're not supposed to make one, fail. */
  if (!signing_key || !(flags & INIT_ED_KEY_CREATE)) {
    tor_log(severity, LD_OR, "Without signing key, can't create certificate");
    goto err;
  }

  /* We have keys but not a certificate, so make one. */
  uint32_t cert_flags = 0;
  if (flags & INIT_ED_KEY_INCLUDE_SIGNING_KEY_IN_CERT)
    cert_flags |= CERT_FLAG_INCLUDE_SIGNING_KEY;
  cert = tor_cert_create(signing_key, cert_type,
                         &keypair->pubkey,
                         now, lifetime,
                         cert_flags);

  if (! cert) {
    tor_log(severity, LD_OR, "Couldn't create certificate");
    goto err;
  }

  /* Write it to disk. */
  created_cert = 1;
  if (crypto_write_tagged_contents_to_file(cert_fname, "ed25519v1-cert",
                             tag, cert->encoded, cert->encoded_len) < 0) {
    tor_log(severity, LD_OR, "Couldn't write cert to disk.");
    goto err;
  }

 done:
  if (cert_out)
    *cert_out = cert;
  else
    tor_cert_free(cert);

  goto cleanup;

 err:
  if (keypair)
    memwipe(keypair, 0, sizeof(*keypair));
  tor_free(keypair);
  tor_cert_free(cert);
  if (cert_out)
    *cert_out = NULL;
  if (created_sk)
    unlink(secret_fname);
  if (created_pk)
    unlink(public_fname);
  if (created_cert)
    unlink(cert_fname);

 cleanup:
  tor_free(encrypted_secret_fname);
  tor_free(secret_fname);
  tor_free(public_fname);
  tor_free(cert_fname);
  tor_free(got_tag);

  return keypair;
}
Пример #8
0
/** Reload the persistent state from disk, generating a new state as needed.
 * Return 0 on success, less than 0 on failure.
 */
int
or_state_load(void)
{
  or_state_t *new_state = NULL;
  char *contents = NULL, *fname;
  char *errmsg = NULL;
  int r = -1, badstate = 0;

  fname = get_datadir_fname("state");
  switch (file_status(fname)) {
    case FN_FILE:
      if (!(contents = read_file_to_str(fname, 0, NULL))) {
        log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
        goto done;
      }
      break;
    case FN_NOENT:
      break;
    case FN_ERROR:
    case FN_DIR:
    default:
      log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
      goto done;
  }
  new_state = tor_malloc_zero(sizeof(or_state_t));
  new_state->_magic = OR_STATE_MAGIC;
  config_init(&state_format, new_state);
  if (contents) {
    config_line_t *lines=NULL;
    int assign_retval;
    if (config_get_lines(contents, &lines, 0)<0)
      goto done;
    assign_retval = config_assign(&state_format, new_state,
                                  lines, 0, 0, &errmsg);
    config_free_lines(lines);
    if (assign_retval<0)
      badstate = 1;
    if (errmsg) {
      log_warn(LD_GENERAL, "%s", errmsg);
      tor_free(errmsg);
    }
  }

  if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
    badstate = 1;

  if (errmsg) {
    log_warn(LD_GENERAL, "%s", errmsg);
    tor_free(errmsg);
  }

  if (badstate && !contents) {
    log_warn(LD_BUG, "Uh oh.  We couldn't even validate our own default state."
             " This is a bug in Tor.");
    goto done;
  } else if (badstate && contents) {
    or_state_save_broken(fname);

    tor_free(contents);
    config_free(&state_format, new_state);

    new_state = tor_malloc_zero(sizeof(or_state_t));
    new_state->_magic = OR_STATE_MAGIC;
    config_init(&state_format, new_state);
  } else if (contents) {
    log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
  } else {
    log_info(LD_GENERAL, "Initialized state");
  }
  if (or_state_set(new_state) == -1) {
    or_state_save_broken(fname);
  }
  new_state = NULL;
  if (!contents) {
    global_state->next_write = 0;
    or_state_save(time(NULL));
  }
  r = 0;

 done:
  tor_free(fname);
  tor_free(contents);
  if (new_state)
    config_free(&state_format, new_state);

  return r;
}
Пример #9
0
static char *find_command_in_path(const char *name, const char *path_list, int *path_index)
{
    char *found = NULL, *full_path;
    int status, name_len;

    name_len = strlen(name);

    if (!absolute_program(name))
        absolute_path_given = 0;
    else
    {
        char *p;
        absolute_path_given = 1;

        if (abs_path)
            free(abs_path);

        if (*name != '.' && *name != DIRSEP && *name != '~')
        {
            abs_path = (char *)xmalloc(3 + name_len);
            strcpy(abs_path, "./");
            strcat(abs_path, name);
        }
        else
        {
            abs_path = (char *)xmalloc(1 + name_len);
            strcpy(abs_path, name);
        }

        path_list = abs_path;
        p = strrchr(abs_path, DIRSEP);
        *p++ = 0;
        name = p;
    }

    while (path_list && path_list[*path_index])
    {
        char *path;

        if (absolute_path_given)
        {
            path = savestring(path_list);
            *path_index = strlen(path);
        }
        else
            path = get_next_path_element(path_list, path_index);

        if (!path)
            break;

        if (*path == '~')
        {
            char *t = tilde_expand(path);
            free(path);
            path = t;

            if (skip_tilde)
            {
                free(path);
                continue;
            }
        }

        if (skip_dot && *path != DIRSEP)
        {
            free(path);
            continue;
        }

        found_path_starts_with_dot = (*path == '.');

        full_path = make_full_pathname(path, name, name_len);
        free(path);

        status = file_status(full_path);

        if ((status & FS_EXISTS) && (status & FS_EXECABLE))
        {
            found = full_path;
            break;
        }

        free(full_path);
    }

    return (found);
}