/* * 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; }