diff options
author | unknown <pesco@khjk.org> | 2011-11-26 01:41:45 +0100 |
---|---|---|
committer | unknown <pesco@khjk.org> | 2011-11-26 01:41:45 +0100 |
commit | c7b94ef51bcc4585068b568dbe74108ef0340296 (patch) | |
tree | 432b2d30073cb03425ce3f85edfa7a17670b961d /otr.c | |
parent | 3bd2f17754009d84df1aeb60cfa1d3510182e87c (diff) |
make sure we avoid file traversal in otr load/save functions (#853)
Diffstat (limited to 'otr.c')
-rw-r--r-- | otr.c | 86 |
1 files changed, 54 insertions, 32 deletions
@@ -185,6 +185,9 @@ Fingerprint *match_fingerprint(irc_t *irc, ConnContext *ctx, const char **args); /* find a private key by fingerprint prefix (given as any number of hex strings) */ OtrlPrivKey *match_privkey(irc_t *irc, const char **args); +/* check whether a string is safe to use in a path component */ +int strsane(const char *s); + /* functions to be called for certain events */ static const struct irc_plugin otr_plugin; @@ -274,15 +277,17 @@ void otr_load(irc_t *irc) gcry_error_t enoent = gcry_error_from_errno(ENOENT); int kg=0; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->user->nick); - e = otrl_privkey_read(irc->otr->us, s); - if(e && e!=enoent) { - irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); - } - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); - e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); - if(e && e!=enoent) { - irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + if(strsane(irc->user->nick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, irc->user->nick); + e = otrl_privkey_read(irc->otr->us, s); + if(e && e!=enoent) { + irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + } + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); + e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); + if(e && e!=enoent) { + irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); + } } /* check for otr keys on all accounts */ @@ -305,34 +310,40 @@ void otr_save(irc_t *irc) char s[512]; gcry_error_t e; - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); - e = otrl_privkey_write_fingerprints(irc->otr->us, s); - if(e) { - irc_rootmsg(irc, "otr save: %s: %s", s, gcry_strerror(e)); + if(strsane(irc->user->nick)) { + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); + e = otrl_privkey_write_fingerprints(irc->otr->us, s); + if(e) { + irc_rootmsg(irc, "otr save: %s: %s", s, gcry_strerror(e)); + } + chmod(s, 0600); } - chmod(s, 0600); } void otr_remove(const char *nick) { char s[512]; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, nick); - unlink(s); - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, nick); - unlink(s); + if(strsane(nick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, nick); + unlink(s); + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, nick); + unlink(s); + } } void otr_rename(const char *onick, const char *nnick) { char s[512], t[512]; - g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, onick); - g_snprintf(t, 511, "%s%s.otr_keys", global.conf->configdir, nnick); - rename(s,t); - g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, onick); - g_snprintf(t, 511, "%s%s.otr_fprints", global.conf->configdir, nnick); - rename(s,t); + if(strsane(nnick) && strsane(onick)) { + g_snprintf(s, 511, "%s%s.otr_keys", global.conf->configdir, onick); + g_snprintf(t, 511, "%s%s.otr_keys", global.conf->configdir, nnick); + rename(s,t); + g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, onick); + g_snprintf(t, 511, "%s%s.otr_fprints", global.conf->configdir, nnick); + rename(s,t); + } } int otr_check_for_key(account_t *a) @@ -1776,14 +1787,19 @@ gboolean keygen_finish_handler(gpointer data, gint fd, b_input_condition cond) irc_rootmsg(irc, "%s", msg); if(filename[0]) { - char *kf = g_strdup_printf("%s%s.otr_keys", global.conf->configdir, irc->user->nick); - char *tmp = g_strdup_printf("%s.new", kf); - copyfile(filename, tmp); - unlink(filename); - rename(tmp,kf); - otrl_privkey_read(irc->otr->us, kf); - g_free(kf); - g_free(tmp); + if(strsane(irc->user->nick)) { + char *kf = g_strdup_printf("%s%s.otr_keys", global.conf->configdir, irc->user->nick); + char *tmp = g_strdup_printf("%s.new", kf); + copyfile(filename, tmp); + unlink(filename); + rename(tmp,kf); + otrl_privkey_read(irc->otr->us, kf); + g_free(kf); + g_free(tmp); + } else { + otrl_privkey_read(irc->otr->us, filename); + unlink(filename); + } } /* forget this job */ @@ -1858,4 +1874,10 @@ void yes_keygen(void *data) } } +/* check whether a string is safe to use in a path component */ +int strsane(const char *s) +{ + return strpbrk(s, "/\\") == NULL; +} + /* vim: set noet ts=4 sw=4: */ |