Beispiel #1
0
/* Handle the creation of a keyring or a keybox if it does not yet
   exist.  Take into acount that other processes might have the
   keyring/keybox already locked.  This lock check does not work if
   the directory itself is not yet available. */
static int
maybe_create_keyring_or_box (char *filename, int is_box, int force)
{
  dotlock_t lockhd = NULL;
  IOBUF iobuf;
  int rc;
  mode_t oldmask;
  char *last_slash_in_filename;
  int save_slash;

  /* A quick test whether the filename already exists. */
  if (!access (filename, F_OK))
    return 0;

  /* If we don't want to create a new file at all, there is no need to
     go any further - bail out right here.  */
  if (!force)
    return gpg_error (GPG_ERR_ENOENT);

  /* First of all we try to create the home directory.  Note, that we
     don't do any locking here because any sane application of gpg
     would create the home directory by itself and not rely on gpg's
     tricky auto-creation which is anyway only done for some home
     directory name patterns. */
  last_slash_in_filename = strrchr (filename, DIRSEP_C);
#if HAVE_W32_SYSTEM
  {
    /* Windows may either have a slash or a backslash.  Take care of it.  */
    char *p = strrchr (filename, '/');
    if (!last_slash_in_filename || p > last_slash_in_filename)
      last_slash_in_filename = p;
  }
#endif /*HAVE_W32_SYSTEM*/
  if (!last_slash_in_filename)
    return gpg_error (GPG_ERR_ENOENT);  /* No slash at all - should
                                           not happen though.  */
  save_slash = *last_slash_in_filename;
  *last_slash_in_filename = 0;
  if (access(filename, F_OK))
    {
      static int tried;

      if (!tried)
        {
          tried = 1;
          try_make_homedir (filename);
        }
      if (access (filename, F_OK))
        {
          rc = gpg_error_from_syserror ();
          *last_slash_in_filename = save_slash;
          goto leave;
        }
    }
  *last_slash_in_filename = save_slash;

  /* To avoid races with other instances of gpg trying to create or
     update the keyring (it is removed during an update for a short
     time), we do the next stuff in a locked state. */
  lockhd = dotlock_create (filename, 0);
  if (!lockhd)
    {
      rc = gpg_error_from_syserror ();
      /* A reason for this to fail is that the directory is not
         writable. However, this whole locking stuff does not make
         sense if this is the case. An empty non-writable directory
         with no keyring is not really useful at all. */
      if (opt.verbose)
        log_info ("can't allocate lock for '%s': %s\n",
                  filename, gpg_strerror (rc));

      if (!force)
        return gpg_error (GPG_ERR_ENOENT);
      else
        return rc;
    }

  if ( dotlock_take (lockhd, -1) )
    {
      rc = gpg_error_from_syserror ();
      /* This is something bad.  Probably a stale lockfile.  */
      log_info ("can't lock '%s': %s\n", filename, gpg_strerror (rc));
      goto leave;
    }

  /* Now the real test while we are locked. */
  if (!access (filename, F_OK))
    {
      rc = 0;  /* Okay, we may access the file now.  */
      goto leave;
    }

  /* The file does not yet exist, create it now. */
  oldmask = umask (077);
  if (is_secured_filename (filename))
    {
      iobuf = NULL;
      gpg_err_set_errno (EPERM);
    }
  else
    iobuf = iobuf_create (filename);
  umask (oldmask);
  if (!iobuf)
    {
      rc = gpg_error_from_syserror ();
      if (is_box)
        log_error (_("error creating keybox '%s': %s\n"),
                   filename, gpg_strerror (rc));
      else
        log_error (_("error creating keyring '%s': %s\n"),
                   filename, gpg_strerror (rc));
      goto leave;
    }

  iobuf_close (iobuf);
  /* Must invalidate that ugly cache */
  iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, filename);

  /* Make sure that at least one record is in a new keybox file, so
     that the detection magic will work the next time it is used.  */
  if (is_box)
    {
      FILE *fp = fopen (filename, "w");
      if (!fp)
        rc = gpg_error_from_syserror ();
      else
        {
          rc = _keybox_write_header_blob (fp);
          fclose (fp);
        }
      if (rc)
        {
          if (is_box)
            log_error (_("error creating keybox '%s': %s\n"),
                       filename, gpg_strerror (rc));
          else
            log_error (_("error creating keyring '%s': %s\n"),
                       filename, gpg_strerror (rc));
          goto leave;
        }
    }

  if (!opt.quiet)
    {
      if (is_box)
        log_info (_("keybox '%s' created\n"), filename);
      else
        log_info (_("keyring '%s' created\n"), filename);
    }

  rc = 0;

 leave:
  if (lockhd)
    {
      dotlock_release (lockhd);
      dotlock_destroy (lockhd);
    }
  return rc;
}
int
tdbio_set_dbname( const char *new_dbname, int create )
{
    char *fname;
    static int initialized = 0;

    if( !initialized ) {
	atexit( cleanup );
	initialized = 1;
    }

    if(new_dbname==NULL)
      fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "gpg", NULL);
    else if (*new_dbname != DIRSEP_C )
      {
	if (strchr(new_dbname, DIRSEP_C) )
	  fname = make_filename (new_dbname, NULL);
	else
	  fname = make_filename (opt.homedir, new_dbname, NULL);
      }
    else
      fname = xstrdup (new_dbname);

    if( access( fname, R_OK ) ) {
	if( errno != ENOENT ) {
	    log_error( _("can't access `%s': %s\n"), fname, strerror(errno) );
	    xfree(fname);
	    return G10ERR_TRUSTDB;
	}
	if( create ) {
	    FILE *fp;
	    TRUSTREC rec;
	    int rc;
	    char *p = strrchr( fname, DIRSEP_C );
	    mode_t oldmask;

	    assert(p);
	    *p = 0;
	    if( access( fname, F_OK ) ) {
		try_make_homedir( fname );
		log_fatal( _("%s: directory does not exist!\n"), fname );
	    }
	    *p = DIRSEP_C;

	    xfree(db_name);
	    db_name = fname;
#ifdef __riscos__
	    if( !lockhandle )
		lockhandle = create_dotlock( db_name );
	    if( !lockhandle )
		log_fatal( _("can't create lock for `%s'\n"), db_name );
            if( make_dotlock( lockhandle, -1 ) )
                log_fatal( _("can't lock `%s'\n"), db_name );
#endif /* __riscos__ */
	    oldmask=umask(077);
            if (is_secured_filename (fname)) {
                fp = NULL;
                errno = EPERM;
            }
            else
                fp =fopen( fname, "wb" );
	    umask(oldmask);
	    if( !fp )
		log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
	    fclose(fp);
	    db_fd = open( db_name, O_RDWR | MY_O_BINARY );
	    if( db_fd == -1 )
		log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );

#ifndef __riscos__
	    if( !lockhandle )
		lockhandle = create_dotlock( db_name );
	    if( !lockhandle )
		log_fatal( _("can't create lock for `%s'\n"), db_name );
#endif /* !__riscos__ */

            rc = create_version_record ();
	    if( rc )
		log_fatal( _("%s: failed to create version record: %s"),
						   fname, g10_errstr(rc));
	    /* and read again to check that we are okay */
	    if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
		log_fatal( _("%s: invalid trustdb created\n"), db_name );

	    if( !opt.quiet )
		log_info(_("%s: trustdb created\n"), db_name);

	    return 0;
	}
    }
    xfree(db_name);
    db_name = fname;
    return 0;
}
/* Handle the creation of a keyring if it does not yet exist.  Take
   into acount that other processes might have the keyring already
   locked.  This lock check does not work if the directory itself is
   not yet available. */
static int
maybe_create_keyring (char *filename, int force)
{
  DOTLOCK lockhd = NULL;
  IOBUF iobuf;
  int rc;
  mode_t oldmask;
  char *last_slash_in_filename;

  /* A quick test whether the filename already exists. */
  if (!access (filename, F_OK))
    return 0;

  /* If we don't want to create a new file at all, there is no need to
     go any further - bail out right here.  */
  if (!force) 
    return G10ERR_OPEN_FILE;

  /* First of all we try to create the home directory.  Note, that we
     don't do any locking here because any sane application of gpg
     would create the home directory by itself and not rely on gpg's
     tricky auto-creation which is anyway only done for some home
     directory name patterns. */
  last_slash_in_filename = strrchr (filename, DIRSEP_C);
  *last_slash_in_filename = 0;
  if (access(filename, F_OK))
    { 
      static int tried;
      
      if (!tried)
        {
          tried = 1;
          try_make_homedir (filename);
        }
      if (access (filename, F_OK))
        {
          rc = G10ERR_OPEN_FILE;
          *last_slash_in_filename = DIRSEP_C;
          goto leave;
        }
    }
  *last_slash_in_filename = DIRSEP_C;


  /* To avoid races with other instances of gpg trying to create or
     update the keyring (it is removed during an update for a short
     time), we do the next stuff in a locked state. */
  lockhd = create_dotlock (filename);
  if (!lockhd)
    {
      /* A reason for this to fail is that the directory is not
         writable. However, this whole locking stuff does not make
         sense if this is the case. An empty non-writable directory
         with no keyring is not really useful at all. */
      if (opt.verbose)
        log_info ("can't allocate lock for `%s'\n", filename );

      if (!force) 
        return G10ERR_OPEN_FILE; 
      else
        return G10ERR_GENERAL;
    }

  if ( make_dotlock (lockhd, -1) )
    {
      /* This is something bad.  Probably a stale lockfile.  */
      log_info ("can't lock `%s'\n", filename );
      rc = G10ERR_GENERAL;
      goto leave;
    }

  /* Now the real test while we are locked. */
  if (!access(filename, F_OK))
    {
      rc = 0;  /* Okay, we may access the file now.  */
      goto leave;
    }

  /* The file does not yet exist, create it now. */
  oldmask = umask (077);
  if (is_secured_filename (filename))
    {
      iobuf = NULL;
      errno = EPERM;
    }
  else
    iobuf = iobuf_create (filename);
  umask (oldmask);
  if (!iobuf) 
    {
      log_error ( _("error creating keyring `%s': %s\n"),
                  filename, strerror(errno));
      rc = G10ERR_OPEN_FILE;
      goto leave;
    }

  if (!opt.quiet)
    log_info (_("keyring `%s' created\n"), filename);

  iobuf_close (iobuf);
  /* Must invalidate that ugly cache */
  iobuf_ioctl (NULL, 2, 0, filename);
  rc = 0;

 leave:
  if (lockhd)
    {
      release_dotlock (lockhd);
      destroy_dotlock (lockhd);
    }
  return rc;
}
int
tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile)
{
    char *fname;
    struct stat statbuf;
    static int initialized = 0;

    if( !initialized ) {
	atexit( cleanup );
	initialized = 1;
    }

    *r_nofile = 0;

    if(new_dbname==NULL)
      fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "gpg", NULL);
    else if (*new_dbname != DIRSEP_C )
      {
	if (strchr(new_dbname, DIRSEP_C) )
	  fname = make_filename (new_dbname, NULL);
	else
	  fname = make_filename (opt.homedir, new_dbname, NULL);
      }
    else
      fname = xstrdup (new_dbname);

    xfree (db_name);
    db_name = fname;

    /*
     * Quick check for (likely) case where there is trustdb.gpg
     * already.  This check is not required in theory, but it helps in
     * practice, avoiding costly operations of preparing and taking
     * the lock.
     */
    if (stat (fname, &statbuf) == 0 && statbuf.st_size > 0)
      /* OK, we have the valid trustdb.gpg already.  */
      return 0;

    take_write_lock ();

    if( access( fname, R_OK ) ) {
        if( errno != ENOENT )
            log_fatal( _("can't access `%s': %s\n"), fname, strerror(errno) );

	if (!create)
          *r_nofile = 1;
        else {
	    FILE *fp;
	    TRUSTREC rec;
	    int rc;
	    char *p = strrchr( fname, DIRSEP_C );
	    mode_t oldmask;
            int save_slash;

#if HAVE_W32_SYSTEM
            {
              /* Windows may either have a slash or a backslash.  Take
                 care of it.  */
              char *pp = strrchr (fname, '/');
              if (!p || pp > p)
                p = pp;
            }
#endif /*HAVE_W32_SYSTEM*/
	    assert (p);
            save_slash = *p;
	    *p = 0;
	    if( access( fname, F_OK ) ) {
		try_make_homedir( fname );
                if (access (fname, F_OK ))
                  log_fatal (_("%s: directory does not exist!\n"), fname);
	    }
	    *p = save_slash;

	    oldmask=umask(077);
            if (is_secured_filename (fname)) {
                fp = NULL;
                errno = EPERM;
            }
            else
                fp =fopen( fname, "wb" );
	    umask(oldmask);
	    if( !fp )
		log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
	    fclose(fp);
	    db_fd = open( db_name, O_RDWR | MY_O_BINARY );
	    if( db_fd == -1 )
		log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );

            rc = create_version_record ();
	    if( rc )
		log_fatal( _("%s: failed to create version record: %s"),
						   fname, g10_errstr(rc));
	    /* and read again to check that we are okay */
	    if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
		log_fatal( _("%s: invalid trustdb created\n"), db_name );

	    if( !opt.quiet )
		log_info(_("%s: trustdb created\n"), db_name);
	}
    }

    release_write_lock ();
    return 0;
}
Beispiel #5
0
/*
 * Register a resource (which currently may only be a keybox file).
 * The first keybox which is added by this function is created if it
 * does not exist.  If AUTO_CREATED is not NULL it will be set to true
 * if the function has created a a new keybox.
 */
int
keydb_add_resource (const char *url, int force, int secret, int *auto_created)
{
  static int any_secret, any_public;
  const char *resname = url;
  char *filename = NULL;
  int rc = 0;
  FILE *fp;
  KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;

  if (auto_created)
    *auto_created = 0;

  /* Do we have an URL?
     gnupg-kbx:filename := this is a plain keybox
     filename := See what is is, but create as plain keybox.
  */
  if (strlen (resname) > 10)
    {
      if (!strncmp (resname, "gnupg-kbx:", 10) )
        {
          rt = KEYDB_RESOURCE_TYPE_KEYBOX;
          resname += 10;
	}
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
      else if (strchr (resname, ':'))
        {
          log_error ("invalid key resource URL `%s'\n", url );
          rc = gpg_error (GPG_ERR_GENERAL);
          goto leave;
	}
#endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */
    }

  if (*resname != DIRSEP_C )
    { /* do tilde expansion etc */
      if (strchr(resname, DIRSEP_C) )
        filename = make_filename (resname, NULL);
      else
        filename = make_filename (opt.homedir, resname, NULL);
    }
  else
    filename = xstrdup (resname);

  if (!force)
    force = secret? !any_secret : !any_public;

  /* see whether we can determine the filetype */
  if (rt == KEYDB_RESOURCE_TYPE_NONE)
    {
      FILE *fp2 = fopen( filename, "rb" );

      if (fp2) {
        u32 magic;

        /* FIXME: check for the keybox magic */
        if (fread( &magic, 4, 1, fp2) == 1 )
          {
            if (magic == 0x13579ace || magic == 0xce9a5713)
              ; /* GDBM magic - no more support */
            else
              rt = KEYDB_RESOURCE_TYPE_KEYBOX;
          }
        else /* maybe empty: assume ring */
          rt = KEYDB_RESOURCE_TYPE_KEYBOX;
        fclose (fp2);
      }
      else /* no file yet: create ring */
        rt = KEYDB_RESOURCE_TYPE_KEYBOX;
    }

  switch (rt)
    {
    case KEYDB_RESOURCE_TYPE_NONE:
      log_error ("unknown type of key resource `%s'\n", url );
      rc = gpg_error (GPG_ERR_GENERAL);
      goto leave;

    case KEYDB_RESOURCE_TYPE_KEYBOX:
      fp = fopen (filename, "rb");
      if (!fp && !force)
        {
          rc = gpg_error (gpg_err_code_from_errno (errno));
          goto leave;
        }

      if (!fp)
        { /* no file */
#if 0 /* no autocreate of the homedirectory yet */
          {
            char *last_slash_in_filename;

            last_slash_in_filename = strrchr (filename, DIRSEP_C);
            *last_slash_in_filename = 0;
            if (access (filename, F_OK))
              { /* on the first time we try to create the default
                   homedir and in this case the process will be
                   terminated, so that on the next invocation can
                   read the options file in on startup */
                try_make_homedir (filename);
                rc = gpg_error (GPG_ERR_FILE_OPEN_ERROR);
                *last_slash_in_filename = DIRSEP_C;
                goto leave;
              }
            *last_slash_in_filename = DIRSEP_C;
          }
#endif
          fp = fopen (filename, "w");
          if (!fp)
            {
              rc = gpg_error (gpg_err_code_from_errno (errno));
              log_error (_("error creating keybox `%s': %s\n"),
                         filename, strerror(errno));
              if (errno == ENOENT)
                log_info (_("you may want to start the gpg-agent first\n"));
              goto leave;
	    }

          if (!opt.quiet)
            log_info (_("keybox `%s' created\n"), filename);
          if (auto_created)
            *auto_created = 1;
	}
	fclose (fp);
	fp = NULL;
        /* now register the file */
        {

          void *token = keybox_register_file (filename, secret);
          if (!token)
            ; /* already registered - ignore it */
          else if (used_resources >= MAX_KEYDB_RESOURCES)
            rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
          else
            {
              all_resources[used_resources].type = rt;
              all_resources[used_resources].u.kr = NULL; /* Not used here */
              all_resources[used_resources].token = token;
              all_resources[used_resources].secret = secret;

              all_resources[used_resources].lockhandle
                = create_dotlock (filename);
              if (!all_resources[used_resources].lockhandle)
                log_fatal ( _("can't create lock for `%s'\n"), filename);

              /* Do a compress run if needed and the file is not locked. */
              if (!make_dotlock (all_resources[used_resources].lockhandle, 0))
                {
                  KEYBOX_HANDLE kbxhd = keybox_new (token, secret);

                  if (kbxhd)
                    {
                      keybox_compress (kbxhd);
                      keybox_release (kbxhd);
                    }
                  release_dotlock (all_resources[used_resources].lockhandle);
                }

              used_resources++;
            }
        }


	break;
    default:
      log_error ("resource type of `%s' not supported\n", url);
      rc = gpg_error (GPG_ERR_NOT_SUPPORTED);
      goto leave;
    }

  /* fixme: check directory permissions and print a warning */

 leave:
  if (rc)
    log_error ("keyblock resource `%s': %s\n", filename, gpg_strerror(rc));
  else if (secret)
    any_secret = 1;
  else
    any_public = 1;
  xfree (filename);
  return rc;
}
Beispiel #6
0
/*
 * Set the file name for the trustdb to NEW_DBNAME and if CREATE is
 * true create that file.  If NEW_DBNAME is NULL a default name is
 * used, if the it does not contain a path component separator ('/')
 * the global GnuPG home directory is used.
 *
 * Returns: 0 on success or an error code.
 *
 * On the first call this function registers an atexit handler.
 *
 */
int
tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
{
  char *fname, *p;
  struct stat statbuf;
  static int initialized = 0;
  int save_slash;

  if (!initialized)
    {
      atexit (cleanup);
      initialized = 1;
    }

  *r_nofile = 0;

  if (!new_dbname)
    {
      fname = make_filename (opt.homedir, "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
    }
  else if (*new_dbname != DIRSEP_C )
    {
      if (strchr (new_dbname, DIRSEP_C))
        fname = make_filename (new_dbname, NULL);
      else
        fname = make_filename (opt.homedir, new_dbname, NULL);
    }
  else
    {
      fname = xstrdup (new_dbname);
    }

  xfree (db_name);
  db_name = fname;

  /* Quick check for (likely) case where there already is a
   * trustdb.gpg.  This check is not required in theory, but it helps
   * in practice avoiding costly operations of preparing and taking
   * the lock.  */
  if (!stat (fname, &statbuf) && statbuf.st_size > 0)
    {
      /* OK, we have the valid trustdb.gpg already.  */
      return 0;
    }
  else if (!create)
    {
      *r_nofile = 1;
      return 0;
    }

  /* Here comes: No valid trustdb.gpg AND CREATE==1 */

  /*
   * Make sure the directory exists.  This should be done before
   * acquiring the lock, which assumes the existence of the directory.
   */
  p = strrchr (fname, DIRSEP_C);
#if HAVE_W32_SYSTEM
  {
    /* Windows may either have a slash or a backslash.  Take
       care of it.  */
    char *pp = strrchr (fname, '/');
    if (!p || pp > p)
      p = pp;
  }
#endif /*HAVE_W32_SYSTEM*/
  assert (p);
  save_slash = *p;
  *p = 0;
  if (access (fname, F_OK))
    {
      try_make_homedir (fname);
      if (access (fname, F_OK))
        log_fatal (_("%s: directory does not exist!\n"), fname);
    }
  *p = save_slash;

  take_write_lock ();

  if (access (fname, R_OK))
    {
      FILE *fp;
      TRUSTREC rec;
      int rc;
      mode_t oldmask;

#ifdef HAVE_W32CE_SYSTEM
      /* We know how the cegcc implementation of access works ;-). */
      if (GetLastError () == ERROR_FILE_NOT_FOUND)
        gpg_err_set_errno (ENOENT);
      else
        gpg_err_set_errno (EIO);
#endif /*HAVE_W32CE_SYSTEM*/
      if (errno != ENOENT)
        log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno));

      oldmask = umask (077);
      if (is_secured_filename (fname))
        {
          fp = NULL;
          gpg_err_set_errno (EPERM);
        }
      else
        fp = fopen (fname, "wb");
      umask(oldmask);
      if (!fp)
        log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
      fclose (fp);

      db_fd = open (db_name, O_RDWR | MY_O_BINARY);
      if (db_fd == -1)
        log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));

      rc = create_version_record ();
      if (rc)
        log_fatal (_("%s: failed to create version record: %s"),
                   fname, gpg_strerror (rc));

      /* Read again to check that we are okay. */
      if (tdbio_read_record (0, &rec, RECTYPE_VER))
        log_fatal (_("%s: invalid trustdb created\n"), db_name);

      if (!opt.quiet)
        log_info (_("%s: trustdb created\n"), db_name);
    }

  release_write_lock ();
  return 0;
}