示例#1
0
int rhizome_manifest_check_file(rhizome_manifest *m_in)
{
  long long gotfile = 0;
  if (sqlite_exec_int64(&gotfile, "SELECT COUNT(*) FROM FILES WHERE ID='%s' and datavalid=1;", m_in->fileHexHash) != 1) {
    WHYF("Failed to count files");
    return 0;
  }
  if (gotfile) {
    DEBUGF("Skipping file checks for bundle, as file is already in the database");
    return 0;
  }

  /* Find out whether the payload is expected to be encrypted or not */
  m_in->payloadEncryption=rhizome_manifest_get_ll(m_in, "crypt");
  
  /* Check payload file is accessible and discover its length, then check that it matches
     the file size stored in the manifest */
  long long mfilesize = rhizome_manifest_get_ll(m_in, "filesize");
  m_in->fileLength = 0;
  if (m_in->dataFileName[0]) {
    struct stat stat;
    if (lstat(m_in->dataFileName,&stat) == -1) {
      if (errno != ENOENT || mfilesize != 0)
	return WHYF_perror("stat(%s)", m_in->dataFileName);
    } else {
      m_in->fileLength = stat.st_size;
    }
  }
  if (debug & DEBUG_RHIZOME)
    DEBUGF("filename=%s, fileLength=%lld", m_in->dataFileName, m_in->fileLength);
  if (mfilesize != -1 && mfilesize != m_in->fileLength) {
    WHYF("Manifest.filesize (%lld) != actual file size (%lld)", mfilesize, m_in->fileLength);
    return -1;
  }

  /* If payload is empty, ensure manifest has not file hash, otherwis compute the hash of the
     payload and check that it matches manifest. */
  const char *mhexhash = rhizome_manifest_get(m_in, "filehash", NULL, 0);
  if (m_in->fileLength != 0) {
    char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
    if (rhizome_hash_file(m_in,m_in->dataFileName, hexhashbuf))
      return WHY("Could not hash file.");
    memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
    m_in->fileHashedP = 1;
    if (!mhexhash) return WHY("manifest contains no file hash");
    if (mhexhash && strcmp(m_in->fileHexHash, mhexhash)) {
      WHYF("Manifest.filehash (%s) does not match payload hash (%s)", mhexhash, m_in->fileHexHash);
      return -1;
    }
  } else {
    if (mhexhash != NULL) {
      WHYF("Manifest.filehash (%s) should be absent for empty payload", mhexhash);
      return -1;
    }
  }

  return 0;
}
示例#2
0
int rhizome_manifest_bind_file(rhizome_manifest *m_in,const char *filename,int encryptP)
{
  /* Keep payload file name handy for later */
  m_in->dataFileName = strdup(filename);

  /* Keep note as to whether we are supposed to be encrypting this file or not */
  m_in->payloadEncryption=encryptP;
  if (encryptP) rhizome_manifest_set_ll(m_in,"crypt",1); 
  else rhizome_manifest_set_ll(m_in,"crypt",0);

  /* Get length of payload.  An empty filename means empty payload. */
  if (filename[0]) {
    struct stat stat;
    if (lstat(filename,&stat))
      return WHYF("Could not stat() payload file '%s'",filename);
    m_in->fileLength = stat.st_size;
  } else
    m_in->fileLength = 0;
  if (debug & DEBUG_RHIZOME)
    DEBUGF("filename=%s, fileLength=%lld", filename, m_in->fileLength);
  rhizome_manifest_set_ll(m_in,"filesize",m_in->fileLength);

  /* Compute hash of non-empty payload */
  if (m_in->fileLength != 0) {
    char hexhashbuf[RHIZOME_FILEHASH_STRLEN + 1];
    if (rhizome_hash_file(m_in,filename, hexhashbuf))
      return WHY("Could not hash file.");
    memcpy(&m_in->fileHexHash[0], &hexhashbuf[0], sizeof hexhashbuf);
    rhizome_manifest_set(m_in, "filehash", m_in->fileHexHash);
    m_in->fileHashedP = 1;
  } else {
    m_in->fileHexHash[0] = '\0';
    rhizome_manifest_del(m_in, "filehash");
    m_in->fileHashedP = 0;
  }
  
  return 0;
}
示例#3
0
/* Import a bundle from the inbox folder.
   Check that the manifest prototype is valid, and if so, complete it, and sign it if required and possible.

   Note that bundles can either be an ordinary bundle, or a group description.
   Group specifications are simply manifests that have the "isagroup" variable set.
   Groups get stored in the manifests table AND a reference included in the 
   grouplist table.
   Groups are allowed to be listed as being members of other groups.
   This allows a nested, i.e., multi-level group heirarchy where sub-groups will only
   typically be discovered by joining the parent group.  Probably not a bad way to do
   things.

   The file should be included in the specified rhizome groups, if possible.
   (some groups may be closed groups that we do not have the private key for.)
*/
int rhizome_bundle_import(char *bundle,char *groups[], int ttl,
			  int verifyP, int checkFileP, int signP)
{
  char filename[1024];
  char manifestname[1024];
  char *buffer;
  
  snprintf(filename,1024,"%s/import/file.%s",rhizome_datastore_path,bundle); filename[1023]=0;
  snprintf(manifestname,1024,"%s/import/manifest.%s",rhizome_datastore_path,bundle); manifestname[1023]=0;

  /* Open files */
  rhizome_manifest *m=rhizome_read_manifest_file(manifestname,0 /* file not buffer */,
						 RHIZOME_VERIFY);
  if (!m) return WHY("Could not read manifest file.");
  char hexhash[SHA512_DIGEST_STRING_LENGTH];

  /* work out time to live */
  if (ttl<0) ttl=0; if (ttl>254) ttl=254; m->ttl=ttl;

  /* Keep associated file name handy for later */
  m->dataFileName=strdup(filename);
  struct stat stat;
  if (lstat(filename,&stat)) {
    return WHY("Could not stat() associated file");
    m->fileLength=stat.st_size;
  }

  if (checkFileP||signP) {
    if (rhizome_hash_file(filename,hexhash))
      { rhizome_manifest_free(m); return WHY("Could not hash file."); }
    bcopy(&hexhash[0],&m->fileHexHash[0],SHA512_DIGEST_STRING_LENGTH);
    m->fileHashedP=1;
  }

  if (verifyP)
    {
      /* Make sure hashes match.
	 Make sure that no signature verification errors were spotted on loading. */
      int verifyErrors=0;
      char *mhexhash;
      if (checkFileP) {
	if ((mhexhash=rhizome_manifest_get(m,"filehash",NULL,0))!=NULL)
	  if (strcmp(hexhash,mhexhash)) verifyErrors++; }
      if (m->errors) verifyErrors+=m->errors;
      if (verifyErrors) {
	rhizome_manifest_free(m);
	unlink(manifestname);
	unlink(filename);
	return WHY("Errors encountered verifying bundle manifest");
      }
    }

  if (!verifyP) {
    if ((buffer=rhizome_manifest_get(m,"id",NULL,0))!=NULL) {
      /* No bundle id (256 bit random string being a public key in the NaCl CryptoSign crypto system),
	 so create one, and keep the private key handy. */
      printf("manifest does not have an id\n");
      rhizome_manifest_createid(m);
      /* The ID is implicit in transit, but we need to store it in the file,
	 so that reimporting manifests on receiver nodes works easily.
	 We might implement something that strips the id variable out of the
	 manifest when sending it, or some other scheme to avoid sending all 
	 the extra bytes. */	
      rhizome_manifest_set(m,"id",rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES));
    } else {
      /* An ID was specified, so remember it, and look for the private key if
	 we have it stowed away */
      rhizome_hex_to_bytes(buffer,m->cryptoSignPublic,
			   crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2); 
      if (!rhizome_find_keypair_bytes(m->cryptoSignPublic,m->cryptoSignSecret))
	m->haveSecret=1;
    }

    rhizome_manifest_set(m,"filehash",hexhash);
    if (rhizome_manifest_get(m,"version",NULL,0)==NULL)
      /* Version not set, so set one */
      rhizome_manifest_set_ll(m,"version",overlay_gettime_ms());
    rhizome_manifest_set_ll(m,"first_byte",0);
    rhizome_manifest_set_ll(m,"last_byte",rhizome_file_size(filename));
  }
   
  /* Discard if it is older than the most recent known version */
  long long storedversion = sqlite_exec_int64("SELECT version from manifests where id='%s';",rhizome_bytes_to_hex(m->cryptoSignPublic,crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES));
  if (storedversion>rhizome_manifest_get_ll(m,"version"))
    {
      rhizome_manifest_free(m);
      return WHY("Newer version exists");
    }
					      
  /* Add group memberships */
					      
int i;
  if (groups) for(i=0;groups[i];i++) rhizome_manifest_add_group(m,groups[i]);

  if (rhizome_manifest_finalise(m,signP)) {
    return WHY("Failed to finalise manifest.\n");
  }

  /* Write manifest back to disk */
  if (rhizome_write_manifest_file(m,manifestname)) {
    rhizome_manifest_free(m);
    return WHY("Could not write manifest file.");
  }

  /* Okay, it is written, and can be put directly into the rhizome database now */
  int r=rhizome_store_bundle(m,filename);
  if (!r) {
    // XXX For testing   unlink(manifestname);
    unlink(filename);
    return 0;
  }

  return WHY("rhizome_store_bundle() failed.");
}