Exemple #1
0
/*
 * Register a resource (keyring or aeybox).  The first keyring or
 * keybox which is added by this function is created if it does not
 * exist.  FLAGS are a combination of the KEYDB_RESOURCE_FLAG_
 * constants as defined in keydb.h.
 */
gpg_error_t
keydb_add_resource (const char *url, unsigned int flags)
{
  static int any_registered;
  const char *resname = url;
  char *filename = NULL;
  int create;
  int read_only = !!(flags&KEYDB_RESOURCE_FLAG_READONLY);
  int rc = 0;
  KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
  void *token;

  /* Create the resource if it is the first registered one.  */
  create = (!read_only && !any_registered);

  /* Do we have an URL?
   *	gnupg-ring:filename  := this is a plain keyring.
   *	gnupg-kbx:filename   := this is a keybox file.
   *	filename := See what is is, but create as plain keyring.
   */
  if (strlen (resname) > 11 && !strncmp( resname, "gnupg-ring:", 11) )
    {
      rt = KEYDB_RESOURCE_TYPE_KEYRING;
      resname += 11;
    }
  else if (strlen (resname) > 10 && !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);

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

      if (fp)
        {
          u32 magic;

          if (fread (&magic, 4, 1, fp) == 1 )
            {
              if (magic == 0x13579ace || magic == 0xce9a5713)
                ; /* GDBM magic - not anymore supported. */
              else if (fread (&magic, 4, 1, fp) == 1
                       && !memcmp (&magic, "\x01", 1)
                       && fread (&magic, 4, 1, fp) == 1
                       && !memcmp (&magic, "KBXf", 4))
                rt = KEYDB_RESOURCE_TYPE_KEYBOX;
              else
                rt = KEYDB_RESOURCE_TYPE_KEYRING;
	    }
          else /* Maybe empty: assume keyring. */
            rt = KEYDB_RESOURCE_TYPE_KEYRING;

          fclose (fp);
	}
      else /* No file yet: create keybox. */
        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_KEYRING:
      rc = maybe_create_keyring_or_box (filename, create, 0);
      if (rc)
        goto leave;

      if (keyring_register_filename (filename, read_only, &token))
        {
          if (used_resources >= MAX_KEYDB_RESOURCES)
            rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
          else
            {
              if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
                primary_keyring = token;
              all_resources[used_resources].type = rt;
              all_resources[used_resources].u.kr = NULL; /* Not used here */
              all_resources[used_resources].token = token;
              used_resources++;
            }
        }
      else
        {
          /* This keyring was already registered, so ignore it.
             However, we can still mark it as primary even if it was
             already registered.  */
          if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY))
            primary_keyring = token;
        }
      break;

    case KEYDB_RESOURCE_TYPE_KEYBOX:
      {
        rc = maybe_create_keyring_or_box (filename, create, 1);
        if (rc)
          goto leave;

        /* FIXME: How do we register a read-only keybox?  */
        token = keybox_register_file (filename, 0);
        if (token)
          {
            if (used_resources >= MAX_KEYDB_RESOURCES)
              rc = gpg_error (GPG_ERR_RESOURCE_LIMIT);
            else
              {
                /* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
                /*   primary_keyring = token; */
                all_resources[used_resources].type = rt;
                all_resources[used_resources].u.kb = NULL; /* Not used here */
                all_resources[used_resources].token = token;

                /* FIXME: Do a compress run if needed and no other
                   user is currently using the keybox. */

                used_resources++;
              }
          }
        else
          {
            /* Already registered.  We will mark it as the primary key
               if requested.  */
            /* FIXME: How to do that?  Change the keybox interface?  */
            /* if ((flags & KEYDB_RESOURCE_FLAG_PRIMARY)) */
            /*   primary_keyring = token; */
          }
      }
      break;

      default:
	log_error ("resource type of '%s' not supported\n", url);
	rc = gpg_error (GPG_ERR_GENERAL);
	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
    any_registered = 1;
  xfree (filename);
  return rc;
}
/*
 * Register a resource (which currently may only be a keyring file).
 * The first keyring which is added by this function is
 * created if it does not exist.
 * Note: this function may be called before secure memory is
 * available.
 * Flag 1 == force
 * Flag 2 == mark resource as primary
 * Flag 4 == This is a default resources
 */
int
keydb_add_resource (const char *url, int flags, int secret)
{
    static int any_secret, any_public;
    const char *resname = url;
    char *filename = NULL;
    int force=(flags&1);
    int rc = 0;
    KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE;
    void *token;

    /* Do we have an URL?
     *	gnupg-ring:filename  := this is a plain keyring
     *	filename := See what is is, but create as plain keyring.
     */
    if (strlen (resname) > 11) {
	if (!strncmp( resname, "gnupg-ring:", 11) ) {
	    rt = KEYDB_RESOURCE_TYPE_KEYRING;
	    resname += 11;
	}
#if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__)
	else if (strchr (resname, ':')) {
	    log_error ("invalid key resource URL `%s'\n", url );
	    rc = G10ERR_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 *fp = fopen( filename, "rb" );

	if (fp) {
	    u32 magic;

	    if (fread( &magic, 4, 1, fp) == 1 ) {
		if (magic == 0x13579ace || magic == 0xce9a5713)
		    ; /* GDBM magic - no more support */
		else
		    rt = KEYDB_RESOURCE_TYPE_KEYRING;
	    }
	    else /* maybe empty: assume ring */
		rt = KEYDB_RESOURCE_TYPE_KEYRING;
	    fclose( fp );
	}
	else /* no file yet: create ring */
	    rt = KEYDB_RESOURCE_TYPE_KEYRING;
    }

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

      case KEYDB_RESOURCE_TYPE_KEYRING:
        rc = maybe_create_keyring (filename, force);
        if (rc)
          goto leave;

        if(keyring_register_filename (filename, secret, &token))
	  {
	    if (used_resources >= MAX_KEYDB_RESOURCES)
	      rc = G10ERR_RESOURCE_LIMIT;
	    else 
	      {
		if(flags&2)
		  primary_keyring=token;
		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;
		used_resources++;
	      }
	  }
	else
	  {
	    /* This keyring was already registered, so ignore it.
	       However, we can still mark it as primary even if it was
	       already registered. */
	    if(flags&2)
	      primary_keyring=token;
	  }
	break;

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

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

  leave:
    if (rc)
      {
        /* Secret keyrings are not required in all cases.  To avoid
           having gpg return failure we use log_info here if the
           rewsource is a secret one and marked as default
           resource.  */
        if ((flags&4) && secret)
          log_info (_("keyblock resource `%s': %s\n"),
                    filename, g10_errstr(rc));
        else
          log_error (_("keyblock resource `%s': %s\n"),
                     filename, g10_errstr(rc));
      }
    else if (secret)
	any_secret = 1;
    else
	any_public = 1;
    xfree (filename);
    return rc;
}