Ejemplo n.º 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;
}
Ejemplo n.º 2
0
/*
 * Make an output filename for the inputfile INAME.
 * Returns an IOBUF and an errorcode
 * Mode 0 = use ".gpg"
 *	1 = use ".asc"
 *	2 = use ".sig"
 *      3 = use ".rev"
 *
 * If INP_FD is not -1 the function simply creates an IOBUF for that
 * file descriptor and ignore INAME and MODE.  Note that INP_FD won't
 * be closed if the returned IOBUF is closed.  With RESTRICTEDPERM a
 * file will be created with mode 700 if possible.
 */
int
open_outfile (int inp_fd, const char *iname, int mode, int restrictedperm,
              iobuf_t *a)
{
  int rc = 0;

  *a = NULL;
  if (inp_fd != -1)
    {
      char xname[64];

      *a = iobuf_fdopen_nc (inp_fd, "wb");
      if (!*a)
        {
          rc = gpg_error_from_syserror ();
          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
          log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (rc));
        }
      else if (opt.verbose)
        {
          snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
          log_info (_("writing to '%s'\n"), xname);
        }
    }
  else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
    {
      *a = iobuf_create (NULL, 0);
      if ( !*a )
        {
          rc = gpg_error_from_syserror ();
          log_error (_("can't open '%s': %s\n"), "[stdout]", strerror(errno) );
        }
      else if ( opt.verbose )
        log_info (_("writing to stdout\n"));
    }
  else
    {
      char *buf = NULL;
      const char *name;

      if (opt.dry_run)
        name = NAME_OF_DEV_NULL;
      else if (opt.outfile)
        name = opt.outfile;
      else
        {
#ifdef USE_ONLY_8DOT3
          if (opt.mangle_dos_filenames)
            {
              /* It is quite common for DOS systems to have only one
                 dot in a filename.  If we have something like this,
                 we simple replace the suffix except in cases where
                 the suffix is larger than 3 characters and not the
                 same as the new one.  We don't map the filenames to
                 8.3 because this is a duty of the file system.  */
              char *dot;
              const char *newsfx;

              newsfx = (mode==1 ? ".asc" :
                        mode==2 ? ".sig" :
                        mode==3 ? ".rev" : ".gpg");

              buf = xmalloc (strlen(iname)+4+1);
              strcpy (buf, iname);
              dot = strchr (buf, '.' );
              if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
                   && CMP_FILENAME (newsfx, dot) )
                strcpy (dot, newsfx);
              else if (dot && !dot[1]) /* Do not duplicate a dot.  */
                strcpy (dot, newsfx+1);
              else
                strcat (buf, newsfx);
            }
          if (!buf)
#endif /* USE_ONLY_8DOT3 */
            {
              buf = xstrconcat (iname,
                                (mode==1 ? EXTSEP_S "asc" :
                                 mode==2 ? EXTSEP_S "sig" :
                                 mode==3 ? EXTSEP_S "rev" :
                                 /*     */ EXTSEP_S GPGEXT_GPG),
                                NULL);
            }
          name = buf;
        }

      rc = 0;
      while ( !overwrite_filep (name) )
        {
          char *tmp = ask_outfile_name (NULL, 0);
          if ( !tmp || !*tmp )
            {
              xfree (tmp);
              rc = gpg_error (GPG_ERR_EEXIST);
              break;
            }
          xfree (buf);
          name = buf = tmp;
        }

      if ( !rc )
        {
          if (is_secured_filename (name) )
            {
              *a = NULL;
              gpg_err_set_errno (EPERM);
            }
          else
            *a = iobuf_create (name, restrictedperm);
          if (!*a)
            {
              rc = gpg_error_from_syserror ();
              log_error(_("can't create '%s': %s\n"), name, strerror(errno) );
            }
          else if( opt.verbose )
            log_info (_("writing to '%s'\n"), name );
        }
      xfree(buf);
    }

  if (*a)
    iobuf_ioctl (*a, IOBUF_IOCTL_NO_CACHE, 1, NULL);

  return rc;
}
Ejemplo n.º 3
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;
}
/****************
 * Make an output filename for the inputfile INAME.
 * Returns an IOBUF and an errorcode
 * Mode 0 = use ".gpg"
 *	1 = use ".asc"
 *	2 = use ".sig"
 */
int
open_outfile( const char *iname, int mode, IOBUF *a )
{
  int rc = 0;

  *a = NULL;
  if( iobuf_is_pipe_filename (iname) && !opt.outfile ) {
    *a = iobuf_create(NULL);
    if( !*a ) {
      rc = gpg_error_from_syserror ();
      log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
    }
    else if( opt.verbose )
      log_info(_("writing to stdout\n"));
  }
  else {
    char *buf = NULL;
    const char *name;

    if ( opt.dry_run )
      {
#ifdef HAVE_W32_SYSTEM
        name = "nul";
#else
        name = "/dev/null";
#endif
      }
    else if( opt.outfile )
      name = opt.outfile;
    else {
#ifdef USE_ONLY_8DOT3
      if (opt.mangle_dos_filenames)
        {
          /* It is quite common DOS system to have only one dot in a
           * a filename So if we have something like this, we simple
           * replace the suffix execpt in cases where the suffix is
           * larger than 3 characters and not the same as.
           * We should really map the filenames to 8.3 but this tends to
           * be more complicated and is probaly a duty of the filesystem
           */
          char *dot;
          const char *newsfx = mode==1 ? ".asc" :
                               mode==2 ? ".sig" : ".gpg";

          buf = xmalloc(strlen(iname)+4+1);
          strcpy(buf,iname);
          dot = strchr(buf, '.' );
          if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
				  && CMP_FILENAME(newsfx, dot) )
            {
              strcpy(dot, newsfx );
            }
          else if ( dot && !dot[1] ) /* don't duplicate a dot */
            strcpy( dot, newsfx+1 );
          else
            strcat ( buf, newsfx );
        }
      if (!buf)
#endif /* USE_ONLY_8DOT3 */
        {
          buf = xmalloc(strlen(iname)+4+1);
          strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
		                   mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
        }
      name = buf;
    }

    rc = 0;
    while( !overwrite_filep (name) )
      {
        char *tmp = ask_outfile_name (NULL, 0);
        if ( !tmp || !*tmp )
          {
            xfree (tmp);
            rc = gpg_error (GPG_ERR_EEXIST);
            break;
          }
        xfree (buf);
        name = buf = tmp;
      }

    if( !rc )
      {
        if (is_secured_filename (name) )
          {
            *a = NULL;
            errno = EPERM;
          }
        else
          *a = iobuf_create( name );
        if( !*a )
          {
            rc = gpg_error_from_syserror ();
            log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
          }
        else if( opt.verbose )
          log_info(_("writing to `%s'\n"), name );
      }
    xfree(buf);
  }

  if (*a)
    iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */

  return rc;
}