diff --git a/g10/keyring.c b/g10/keyring.c index a0b7a0ef8..535dd2b78 100644 --- a/g10/keyring.c +++ b/g10/keyring.c @@ -36,6 +36,8 @@ #include "options.h" #include "main.h" /*for check_key_signature()*/ #include "i18n.h" +#include "../kbx/keybox.h" + typedef struct keyring_resource *KR_RESOURCE; struct keyring_resource @@ -1287,69 +1289,36 @@ static int create_tmp_file (const char *template, char **r_bakfname, char **r_tmpfname, IOBUF *r_fp) { - char *bakfname, *tmpfname; + gpg_error_t err; mode_t oldmask; - *r_bakfname = NULL; - *r_tmpfname = NULL; + err = keybox_tmp_names (template, 1, r_bakfname, r_tmpfname); + if (err) + return err; -# ifdef USE_ONLY_8DOT3 - /* Here is another Windoze bug?: - * you can't rename("pubring.gpg.tmp", "pubring.gpg"); - * but rename("pubring.gpg.tmp", "pubring.aaa"); - * works. So we replace .gpg by .bak or .tmp - */ - if (strlen (template) > 4 - && !strcmp (template+strlen(template)-4, EXTSEP_S GPGEXT_GPG) ) + /* Create the temp file with limited access. Note that the umask + call is not anymore needed because iobuf_create now takes care of + it. However, it does not harm and thus we keep it. */ + oldmask = umask (077); + if (is_secured_filename (*r_tmpfname)) { - bakfname = xmalloc (strlen (template) + 1); - strcpy (bakfname, template); - strcpy (bakfname+strlen(template)-4, EXTSEP_S "bak"); - - tmpfname = xmalloc (strlen( template ) + 1 ); - strcpy (tmpfname,template); - strcpy (tmpfname+strlen(template)-4, EXTSEP_S "tmp"); + *r_fp = NULL; + gpg_err_set_errno (EPERM); } - else - { /* file does not end with gpg; hmmm */ - bakfname = xmalloc (strlen( template ) + 5); - strcpy (stpcpy(bakfname, template), EXTSEP_S "bak"); - - tmpfname = xmalloc (strlen( template ) + 5); - strcpy (stpcpy(tmpfname, template), EXTSEP_S "tmp"); + else + *r_fp = iobuf_create (*r_tmpfname, 1); + umask (oldmask); + if (!*r_fp) + { + err = gpg_error_from_syserror (); + log_error (_("can't create '%s': %s\n"), *r_tmpfname, gpg_strerror (err)); + xfree (*r_tmpfname); + *r_tmpfname = NULL; + xfree (*r_bakfname); + *r_bakfname = NULL; } -# else /* Posix file names */ - bakfname = xmalloc (strlen( template ) + 2); - strcpy (stpcpy (bakfname,template),"~"); - tmpfname = xmalloc (strlen( template ) + 5); - strcpy (stpcpy(tmpfname,template), EXTSEP_S "tmp"); -# endif /* Posix filename */ - - /* Create the temp file with limited access. Note that the umask - call is not anymore needed because iobuf_create now takes care - of it. However, it does not harm and thus we keep it. */ - oldmask=umask(077); - if (is_secured_filename (tmpfname)) - { - *r_fp = NULL; - gpg_err_set_errno (EPERM); - } - else - *r_fp = iobuf_create (tmpfname, 1); - umask(oldmask); - if (!*r_fp) - { - int rc = gpg_error_from_syserror (); - log_error(_("can't create '%s': %s\n"), tmpfname, strerror(errno) ); - xfree (tmpfname); - xfree (bakfname); - return rc; - } - - *r_bakfname = bakfname; - *r_tmpfname = tmpfname; - return 0; + return err; } diff --git a/kbx/keybox-update.c b/kbx/keybox-update.c index aa8086550..eebcfcad4 100644 --- a/kbx/keybox-update.c +++ b/kbx/keybox-update.c @@ -68,88 +68,27 @@ fseeko (FILE * stream, off_t newpos, int whence) #endif /* !defined(HAVE_FSEEKO) && !defined(fseeko) */ - static int create_tmp_file (const char *template, char **r_bakfname, char **r_tmpfname, FILE **r_fp) { - char *bakfname, *tmpfname; + gpg_error_t err; - *r_bakfname = NULL; - *r_tmpfname = NULL; - -# ifdef USE_ONLY_8DOT3 - /* Here is another Windoze bug?: - * you can't rename("pubring.kbx.tmp", "pubring.kbx"); - * but rename("pubring.kbx.tmp", "pubring.aaa"); - * works. So we replace ".kbx" by ".kb_" or ".k__". Note that we - * can't use ".bak" and ".tmp", because these suffixes are used by - * gpg and would lead to a sharing violation or data corruption. - */ - if (strlen (template) > 4 - && !strcmp (template+strlen(template)-4, EXTSEP_S "kbx") ) + err = keybox_tmp_names (template, 0, r_bakfname, r_tmpfname); + if (!err) { - bakfname = xtrymalloc (strlen (template) + 1); - if (!bakfname) - return gpg_error_from_syserror (); - strcpy (bakfname, template); - strcpy (bakfname+strlen(template)-4, EXTSEP_S "kb_"); - - tmpfname = xtrymalloc (strlen (template) + 1); - if (!tmpfname) + *r_fp = fopen (*r_tmpfname, "wb"); + if (!*r_fp) { - gpg_error_t tmperr = gpg_error_from_syserror (); - xfree (bakfname); - return tmperr; + err = gpg_error_from_syserror (); + xfree (*r_tmpfname); + *r_tmpfname = NULL; + xfree (*r_bakfname); + *r_bakfname = NULL; } - strcpy (tmpfname,template); - strcpy (tmpfname + strlen (template)-4, EXTSEP_S "k__"); - } - else - { /* File does not end with kbx, thus we hope we are working on a - modern file system and appending a suffix works. */ - bakfname = xtrymalloc ( strlen (template) + 5); - if (!bakfname) - return gpg_error_from_syserror (); - strcpy (stpcpy (bakfname, template), EXTSEP_S "kb_"); - - tmpfname = xtrymalloc ( strlen (template) + 5); - if (!tmpfname) - { - gpg_error_t tmperr = gpg_error_from_syserror (); - xfree (bakfname); - return tmperr; - } - strcpy (stpcpy (tmpfname, template), EXTSEP_S "k__"); - } -# else /* Posix file names */ - bakfname = xtrymalloc (strlen (template) + 2); - if (!bakfname) - return gpg_error_from_syserror (); - strcpy (stpcpy (bakfname,template),"~"); - - tmpfname = xtrymalloc ( strlen (template) + 5); - if (!tmpfname) - { - gpg_error_t tmperr = gpg_error_from_syserror (); - xfree (bakfname); - return tmperr; - } - strcpy (stpcpy (tmpfname,template), EXTSEP_S "tmp"); -# endif /* Posix filename */ - - *r_fp = fopen (tmpfname, "wb"); - if (!*r_fp) - { - gpg_error_t tmperr = gpg_error_from_syserror (); - xfree (tmpfname); - xfree (bakfname); - return tmperr; } - *r_bakfname = bakfname; - *r_tmpfname = tmpfname; - return 0; + return err; } diff --git a/kbx/keybox-util.c b/kbx/keybox-util.c index 9fe9290ac..f7efd1a29 100644 --- a/kbx/keybox-util.c +++ b/kbx/keybox-util.c @@ -68,3 +68,76 @@ _keybox_free (void *p) if (p) free_func (p); } + + +/* Store the two malloced temporary file names used for keybox updates + of file FILENAME at R_BAKNAME and R_TMPNAME. On error an error + code is returned and NULL stored at R_BAKNAME and R_TMPNAME. If + FOR_KEYRING is true the returned names match those used by GnuPG's + keyring code. */ +gpg_error_t +keybox_tmp_names (const char *filename, int for_keyring, + char **r_bakname, char **r_tmpname) +{ + gpg_error_t err; + char *bak_name, *tmp_name; + + *r_bakname = NULL; + *r_tmpname = NULL; + +# ifdef USE_ONLY_8DOT3 + /* Here is another Windoze bug?: + * you can't rename("pubring.kbx.tmp", "pubring.kbx"); + * but rename("pubring.kbx.tmp", "pubring.aaa"); + * works. So we replace ".kbx" by ".kb_" or ".k__". Note that we + * can't use ".bak" and ".tmp", because these suffixes are used by + * gpg's keyrings and would lead to a sharing violation or data + * corruption. If the name does not end in ".kbx" we assume working + * on a modern file system and append the suffix. */ + { + const char *ext = for_keyring? EXTSEP_S GPGEXT_GPG : EXTSEP_S "kbx"; + const char *b_ext = for_keyring? EXTSEP_S "bak" : EXTSEP_S "kb_"; + const char *t_ext = for_keyring? EXTSEP_S "tmp" : EXTSEP_S "k__"; + int repl; + + if (strlen (ext) != 4 || strlen (b_ext) != 4) + BUG (); + repl = (strlen (filename) > 4 + && !strcmp (filename + strlen (filename) - 4, ext)); + bak_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1); + if (!bak_name) + return gpg_error_from_syserror (); + strcpy (bak_name, filename); + strcpy (bak_name + strlen (filename) - (repl?4:0), b_ext); + + tmp_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1); + if (!tmp_name) + { + err = gpg_error_from_syserror (); + xfree (bak_name); + return err; + } + strcpy (tmp_name, filename); + strcpy (tmp_name + strlen (filename) - (repl?4:0), t_ext); + } +# else /* Posix file names */ + (void)for_keyring; + bak_name = xtrymalloc (strlen (filename) + 2); + if (!bak_name) + return gpg_error_from_syserror (); + strcpy (stpcpy (bak_name, filename), "~"); + + tmp_name = xtrymalloc (strlen (filename) + 5); + if (!tmp_name) + { + err = gpg_error_from_syserror (); + xfree (bak_name); + return err; + } + strcpy (stpcpy (tmp_name,filename), EXTSEP_S "tmp"); +# endif /* Posix filename */ + + *r_bakname = bak_name; + *r_tmpname = tmp_name; + return 0; +} diff --git a/kbx/keybox.h b/kbx/keybox.h index 3c60971a8..4d556c571 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -132,6 +132,9 @@ void keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n), void *(*new_realloc_func)(void *p, size_t n), void (*new_free_func)(void*) ); +gpg_error_t keybox_tmp_names (const char *filename, int for_keyring, + char **r_bakname, char **r_tmpname); + #ifdef __cplusplus }