/* * 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 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; 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 *fp = fopen( filename, "rb" ); if (fp) { u32 magic; /* FIXME: check for the keybox magic */ if (fread (&magic, 4, 1, fp) == 1 ) { if (magic == 0x13579ace || magic == 0xce9a5713) ; /* GDBM magic - no more support */ else rt = KEYDB_RESOURCE_TYPE_KEYBOX; } else /* maybe empty: assume keybox */ rt = KEYDB_RESOURCE_TYPE_KEYBOX; 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_KEYBOX: rc = maybe_create_keybox (filename, force, auto_created); if (rc) goto leave; /* 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 = dotlock_create (filename, 0); 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 (!dotlock_take (all_resources[used_resources].lockhandle, 0)) { KEYBOX_HANDLE kbxhd = keybox_new_x509 (token, secret); if (kbxhd) { keybox_compress (kbxhd); keybox_release (kbxhd); } dotlock_release (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; }
/* * 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; }