2002-10-09 22:09:42 +04:00
|
|
|
/*
|
|
|
|
* uxstore.c: Unix-specific implementation of the interface defined
|
|
|
|
* in storage.h.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2003-04-01 22:10:25 +04:00
|
|
|
#include <string.h>
|
2003-03-31 15:36:14 +04:00
|
|
|
#include <assert.h>
|
2003-04-01 22:10:25 +04:00
|
|
|
#include <errno.h>
|
2002-10-17 02:54:58 +04:00
|
|
|
#include <ctype.h>
|
2005-09-14 00:08:25 +04:00
|
|
|
#include <limits.h>
|
2002-10-31 22:49:52 +03:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
2003-03-31 15:36:14 +04:00
|
|
|
#include <dirent.h>
|
2002-10-31 22:49:52 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2008-03-22 15:01:16 +03:00
|
|
|
#include <pwd.h>
|
2002-10-09 22:09:42 +04:00
|
|
|
#include "putty.h"
|
|
|
|
#include "storage.h"
|
2002-10-17 02:54:58 +04:00
|
|
|
#include "tree234.h"
|
2002-10-09 22:09:42 +04:00
|
|
|
|
2005-09-14 00:08:25 +04:00
|
|
|
#ifdef PATH_MAX
|
|
|
|
#define FNLEN PATH_MAX
|
|
|
|
#else
|
|
|
|
#define FNLEN 1024 /* XXX */
|
|
|
|
#endif
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
enum {
|
2004-01-17 16:00:18 +03:00
|
|
|
INDEX_DIR, INDEX_HOSTKEYS, INDEX_HOSTKEYS_TMP, INDEX_RANDSEED,
|
2003-03-31 15:36:14 +04:00
|
|
|
INDEX_SESSIONDIR, INDEX_SESSION,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char hex[16] = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
static char *mungestr(const char *in)
|
|
|
|
{
|
|
|
|
char *out, *ret;
|
|
|
|
|
2003-04-11 21:42:52 +04:00
|
|
|
if (!in || !*in)
|
2003-03-31 15:36:14 +04:00
|
|
|
in = "Default Settings";
|
|
|
|
|
|
|
|
ret = out = snewn(3*strlen(in)+1, char);
|
|
|
|
|
|
|
|
while (*in) {
|
|
|
|
/*
|
|
|
|
* There are remarkably few punctuation characters that
|
|
|
|
* aren't shell-special in some way or likely to be used as
|
|
|
|
* separators in some file format or another! Hence we use
|
|
|
|
* opt-in for safe characters rather than opt-out for
|
|
|
|
* specific unsafe ones...
|
|
|
|
*/
|
|
|
|
if (*in!='+' && *in!='-' && *in!='.' && *in!='@' && *in!='_' &&
|
|
|
|
!(*in >= '0' && *in <= '9') &&
|
|
|
|
!(*in >= 'A' && *in <= 'Z') &&
|
|
|
|
!(*in >= 'a' && *in <= 'z')) {
|
|
|
|
*out++ = '%';
|
|
|
|
*out++ = hex[((unsigned char) *in) >> 4];
|
|
|
|
*out++ = hex[((unsigned char) *in) & 15];
|
|
|
|
} else
|
|
|
|
*out++ = *in;
|
|
|
|
in++;
|
|
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *unmungestr(const char *in)
|
|
|
|
{
|
|
|
|
char *out, *ret;
|
|
|
|
out = ret = snewn(strlen(in)+1, char);
|
|
|
|
while (*in) {
|
|
|
|
if (*in == '%' && in[1] && in[2]) {
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
i = in[1] - '0';
|
|
|
|
i -= (i > 9 ? 7 : 0);
|
|
|
|
j = in[2] - '0';
|
|
|
|
j -= (j > 9 ? 7 : 0);
|
|
|
|
|
|
|
|
*out++ = (i << 4) + j;
|
|
|
|
in += 3;
|
|
|
|
} else {
|
|
|
|
*out++ = *in++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
static char *make_filename(int index, const char *subname)
|
2003-03-31 15:36:14 +04:00
|
|
|
{
|
2008-03-22 15:01:16 +03:00
|
|
|
char *env, *tmp, *ret;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allow override of the PuTTY configuration location, and of
|
|
|
|
* specific subparts of it, by means of environment variables.
|
|
|
|
*/
|
|
|
|
if (index == INDEX_DIR) {
|
|
|
|
struct passwd *pwd;
|
|
|
|
|
|
|
|
env = getenv("PUTTYDIR");
|
|
|
|
if (env)
|
|
|
|
return dupstr(env);
|
|
|
|
env = getenv("HOME");
|
|
|
|
if (env)
|
|
|
|
return dupprintf("%s/.putty", env);
|
|
|
|
pwd = getpwuid(getuid());
|
|
|
|
if (pwd && pwd->pw_dir)
|
|
|
|
return dupprintf("%s/.putty", pwd->pw_dir);
|
|
|
|
return dupstr("/.putty");
|
|
|
|
}
|
|
|
|
if (index == INDEX_SESSIONDIR) {
|
|
|
|
env = getenv("PUTTYSESSIONS");
|
|
|
|
if (env)
|
|
|
|
return dupstr(env);
|
|
|
|
tmp = make_filename(INDEX_DIR, NULL);
|
|
|
|
ret = dupprintf("%s/sessions", tmp);
|
|
|
|
sfree(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
2003-03-31 15:36:14 +04:00
|
|
|
if (index == INDEX_SESSION) {
|
|
|
|
char *munged = mungestr(subname);
|
2008-03-22 15:01:16 +03:00
|
|
|
tmp = make_filename(INDEX_SESSIONDIR, NULL);
|
|
|
|
ret = dupprintf("%s/%s", tmp, munged);
|
|
|
|
sfree(tmp);
|
|
|
|
sfree(munged);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (index == INDEX_HOSTKEYS) {
|
|
|
|
env = getenv("PUTTYSSHHOSTKEYS");
|
|
|
|
if (env)
|
|
|
|
return dupstr(env);
|
|
|
|
tmp = make_filename(INDEX_DIR, NULL);
|
|
|
|
ret = dupprintf("%s/sshhostkeys", tmp);
|
|
|
|
sfree(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (index == INDEX_HOSTKEYS_TMP) {
|
|
|
|
tmp = make_filename(INDEX_HOSTKEYS, NULL);
|
|
|
|
ret = dupprintf("%s.tmp", tmp);
|
|
|
|
sfree(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (index == INDEX_RANDSEED) {
|
|
|
|
env = getenv("PUTTYRANDOMSEED");
|
|
|
|
if (env)
|
|
|
|
return dupstr(env);
|
|
|
|
tmp = make_filename(INDEX_DIR, NULL);
|
|
|
|
ret = dupprintf("%s/randomseed", tmp);
|
|
|
|
sfree(tmp);
|
|
|
|
return ret;
|
2003-03-31 15:36:14 +04:00
|
|
|
}
|
2008-03-22 15:01:16 +03:00
|
|
|
tmp = make_filename(INDEX_DIR, NULL);
|
|
|
|
ret = dupprintf("%s/ERROR", tmp);
|
|
|
|
sfree(tmp);
|
|
|
|
return ret;
|
2003-03-31 15:36:14 +04:00
|
|
|
}
|
|
|
|
|
2003-04-01 22:10:25 +04:00
|
|
|
void *open_settings_w(const char *sessionname, char **errmsg)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename;
|
2003-03-31 15:36:14 +04:00
|
|
|
FILE *fp;
|
|
|
|
|
2003-04-01 22:10:25 +04:00
|
|
|
*errmsg = NULL;
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
/*
|
2003-04-01 22:10:25 +04:00
|
|
|
* Start by making sure the .putty directory and its sessions
|
|
|
|
* subdir actually exist. Ignore error returns from mkdir since
|
|
|
|
* they're perfectly likely to be `already exists', and any
|
|
|
|
* other error will trip us up later on so there's no real need
|
|
|
|
* to catch it now.
|
2003-03-31 15:36:14 +04:00
|
|
|
*/
|
2008-03-22 15:01:16 +03:00
|
|
|
filename = make_filename(INDEX_SESSIONDIR, NULL);
|
2008-10-12 15:32:23 +04:00
|
|
|
if (mkdir(filename, 0700) != 0) {
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename2 = make_filename(INDEX_DIR, NULL);
|
|
|
|
mkdir(filename2, 0700);
|
|
|
|
sfree(filename2);
|
|
|
|
mkdir(filename, 0700);
|
|
|
|
}
|
|
|
|
sfree(filename);
|
2003-03-31 15:36:14 +04:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
filename = make_filename(INDEX_SESSION, sessionname);
|
2003-03-31 15:36:14 +04:00
|
|
|
fp = fopen(filename, "w");
|
2003-04-01 22:10:25 +04:00
|
|
|
if (!fp) {
|
|
|
|
*errmsg = dupprintf("Unable to create %s: %s",
|
|
|
|
filename, strerror(errno));
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2003-04-01 22:10:25 +04:00
|
|
|
return NULL; /* can't open */
|
|
|
|
}
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2003-03-31 15:36:14 +04:00
|
|
|
return fp;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
void write_setting_s(void *handle, const char *key, const char *value)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
FILE *fp = (FILE *)handle;
|
|
|
|
fprintf(fp, "%s=%s\n", key, value);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
void write_setting_i(void *handle, const char *key, int value)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
FILE *fp = (FILE *)handle;
|
|
|
|
fprintf(fp, "%s=%d\n", key, value);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void close_settings_w(void *handle)
|
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
FILE *fp = (FILE *)handle;
|
|
|
|
fclose(fp);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-16 18:32:06 +04:00
|
|
|
/*
|
|
|
|
* Reading settings, for the moment, is done by retrieving X
|
|
|
|
* resources from the X display. When we introduce disk files, I
|
|
|
|
* think what will happen is that the X resources will override
|
|
|
|
* PuTTY's inbuilt defaults, but that the disk files will then
|
|
|
|
* override those. This isn't optimal, but it's the best I can
|
|
|
|
* immediately work out.
|
2003-10-15 01:01:12 +04:00
|
|
|
* FIXME: the above comment is a bit out of date. Did it happen?
|
2002-10-16 18:32:06 +04:00
|
|
|
*/
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
struct keyval {
|
2003-01-14 21:43:45 +03:00
|
|
|
const char *key;
|
|
|
|
const char *value;
|
2002-10-17 02:54:58 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static tree234 *xrmtree = NULL;
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
int keycmp(void *av, void *bv)
|
2002-10-17 02:54:58 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
struct keyval *a = (struct keyval *)av;
|
|
|
|
struct keyval *b = (struct keyval *)bv;
|
2002-10-17 02:54:58 +04:00
|
|
|
return strcmp(a->key, b->key);
|
|
|
|
}
|
|
|
|
|
|
|
|
void provide_xrm_string(char *string)
|
|
|
|
{
|
2003-01-14 21:43:45 +03:00
|
|
|
char *p, *q, *key;
|
2003-03-31 15:36:14 +04:00
|
|
|
struct keyval *xrms, *ret;
|
2002-10-17 02:54:58 +04:00
|
|
|
|
|
|
|
p = q = strchr(string, ':');
|
|
|
|
if (!q) {
|
|
|
|
fprintf(stderr, "pterm: expected a colon in resource string"
|
|
|
|
" \"%s\"\n", string);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
q++;
|
|
|
|
while (p > string && p[-1] != '.' && p[-1] != '*')
|
|
|
|
p--;
|
2003-03-31 15:36:14 +04:00
|
|
|
xrms = snew(struct keyval);
|
2003-03-29 19:14:26 +03:00
|
|
|
key = snewn(q-p, char);
|
2003-01-14 21:43:45 +03:00
|
|
|
memcpy(key, p, q-p);
|
|
|
|
key[q-p-1] = '\0';
|
|
|
|
xrms->key = key;
|
2003-03-11 12:30:31 +03:00
|
|
|
while (*q && isspace((unsigned char)*q))
|
2002-10-17 02:54:58 +04:00
|
|
|
q++;
|
|
|
|
xrms->value = dupstr(q);
|
|
|
|
|
|
|
|
if (!xrmtree)
|
2003-03-31 15:36:14 +04:00
|
|
|
xrmtree = newtree234(keycmp);
|
2002-10-17 02:54:58 +04:00
|
|
|
|
|
|
|
ret = add234(xrmtree, xrms);
|
|
|
|
if (ret) {
|
|
|
|
/* Override an existing string. */
|
|
|
|
del234(xrmtree, ret);
|
|
|
|
add234(xrmtree, xrms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
const char *get_setting(const char *key)
|
2002-10-17 02:54:58 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
struct keyval tmp, *ret;
|
2002-10-17 02:54:58 +04:00
|
|
|
tmp.key = key;
|
|
|
|
if (xrmtree) {
|
|
|
|
ret = find234(xrmtree, &tmp, NULL);
|
|
|
|
if (ret)
|
|
|
|
return ret->value;
|
|
|
|
}
|
2002-10-31 22:49:52 +03:00
|
|
|
return x_get_default(key);
|
2002-10-17 02:54:58 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
void *open_settings_r(const char *sessionname)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename;
|
2003-03-31 15:36:14 +04:00
|
|
|
FILE *fp;
|
|
|
|
char *line;
|
|
|
|
tree234 *ret;
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
filename = make_filename(INDEX_SESSION, sessionname);
|
2003-03-31 15:36:14 +04:00
|
|
|
fp = fopen(filename, "r");
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2003-03-31 15:36:14 +04:00
|
|
|
if (!fp)
|
|
|
|
return NULL; /* can't open */
|
|
|
|
|
|
|
|
ret = newtree234(keycmp);
|
|
|
|
|
|
|
|
while ( (line = fgetline(fp)) ) {
|
|
|
|
char *value = strchr(line, '=');
|
|
|
|
struct keyval *kv;
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
continue;
|
|
|
|
*value++ = '\0';
|
|
|
|
value[strcspn(value, "\r\n")] = '\0'; /* trim trailing NL */
|
|
|
|
|
|
|
|
kv = snew(struct keyval);
|
|
|
|
kv->key = dupstr(line);
|
|
|
|
kv->value = dupstr(value);
|
|
|
|
add234(ret, kv);
|
|
|
|
|
|
|
|
sfree(line);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
return ret;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
char *read_setting_s(void *handle, const char *key, char *buffer, int buflen)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
tree234 *tree = (tree234 *)handle;
|
|
|
|
const char *val;
|
|
|
|
struct keyval tmp, *kv;
|
|
|
|
|
|
|
|
tmp.key = key;
|
|
|
|
if (tree != NULL &&
|
|
|
|
(kv = find234(tree, &tmp, NULL)) != NULL) {
|
|
|
|
val = kv->value;
|
|
|
|
assert(val != NULL);
|
|
|
|
} else
|
|
|
|
val = get_setting(key);
|
|
|
|
|
2002-10-16 18:32:06 +04:00
|
|
|
if (!val)
|
|
|
|
return NULL;
|
|
|
|
else {
|
|
|
|
strncpy(buffer, val, buflen);
|
|
|
|
buffer[buflen-1] = '\0';
|
|
|
|
return buffer;
|
|
|
|
}
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
int read_setting_i(void *handle, const char *key, int defvalue)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
tree234 *tree = (tree234 *)handle;
|
|
|
|
const char *val;
|
|
|
|
struct keyval tmp, *kv;
|
|
|
|
|
|
|
|
tmp.key = key;
|
|
|
|
if (tree != NULL &&
|
|
|
|
(kv = find234(tree, &tmp, NULL)) != NULL) {
|
|
|
|
val = kv->value;
|
|
|
|
assert(val != NULL);
|
|
|
|
} else
|
|
|
|
val = get_setting(key);
|
|
|
|
|
2002-10-16 18:32:06 +04:00
|
|
|
if (!val)
|
|
|
|
return defvalue;
|
|
|
|
else
|
|
|
|
return atoi(val);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-02-01 15:54:40 +03:00
|
|
|
int read_setting_fontspec(void *handle, const char *name, FontSpec *result)
|
|
|
|
{
|
In the new unified font handling, my strategy so far for combining
client- and server-side fonts into a single namespace was mainly to
hope there would naturally be no collisions, and to provide
disambiguating "client:" and "server:" prefixes for manual use in
emergencies.
Jacob points out, however, that his system not only has a namespace
clash but worse still the clash is at the name "fixed", which is our
default font! So, modify my namespace policy to use the
disambiguating prefixes everywhere by default, and use _unprefixed_
names only if the user types one in by hand.
In particular, I've changed the keys used to store font names in
Unix saved session files. Font names read from the new keys will be
passed straight to the new unifont framework; font names read from
the old keys will have "server:" prepended. So any existing
configuration file for GTK1 PuTTY should now work reliably in GTK2
PuTTY and select the same font, even if that font is one on which
your system (rather, your client+server combination) has a font
namespace clash.
[originally from svn r7973]
2008-04-05 17:37:20 +04:00
|
|
|
/*
|
|
|
|
* In GTK1-only PuTTY, we used to store font names simply as a
|
|
|
|
* valid X font description string (logical or alias), under a
|
|
|
|
* bare key such as "Font".
|
|
|
|
*
|
|
|
|
* In GTK2 PuTTY, we have a prefix system where "client:"
|
|
|
|
* indicates a Pango font and "server:" an X one; existing
|
|
|
|
* configuration needs to be reinterpreted as having the
|
|
|
|
* "server:" prefix, so we change the storage key from the
|
|
|
|
* provided name string (e.g. "Font") to a suffixed one
|
|
|
|
* ("FontName").
|
|
|
|
*/
|
|
|
|
char *suffname = dupcat(name, "Name", NULL);
|
|
|
|
if (read_setting_s(handle, suffname, result->name, sizeof(result->name))) {
|
|
|
|
sfree(suffname);
|
|
|
|
return TRUE; /* got new-style name */
|
|
|
|
}
|
|
|
|
sfree(suffname);
|
|
|
|
|
|
|
|
/* Fall back to old-style name. */
|
|
|
|
memcpy(result->name, "server:", 7);
|
|
|
|
if (!read_setting_s(handle, name,
|
|
|
|
result->name + 7, sizeof(result->name) - 7) ||
|
|
|
|
!result->name[7]) {
|
|
|
|
result->name[0] = '\0';
|
|
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
return TRUE;
|
|
|
|
}
|
2003-02-01 15:54:40 +03:00
|
|
|
}
|
|
|
|
int read_setting_filename(void *handle, const char *name, Filename *result)
|
|
|
|
{
|
|
|
|
return !!read_setting_s(handle, name, result->path, sizeof(result->path));
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_setting_fontspec(void *handle, const char *name, FontSpec result)
|
|
|
|
{
|
In the new unified font handling, my strategy so far for combining
client- and server-side fonts into a single namespace was mainly to
hope there would naturally be no collisions, and to provide
disambiguating "client:" and "server:" prefixes for manual use in
emergencies.
Jacob points out, however, that his system not only has a namespace
clash but worse still the clash is at the name "fixed", which is our
default font! So, modify my namespace policy to use the
disambiguating prefixes everywhere by default, and use _unprefixed_
names only if the user types one in by hand.
In particular, I've changed the keys used to store font names in
Unix saved session files. Font names read from the new keys will be
passed straight to the new unifont framework; font names read from
the old keys will have "server:" prepended. So any existing
configuration file for GTK1 PuTTY should now work reliably in GTK2
PuTTY and select the same font, even if that font is one on which
your system (rather, your client+server combination) has a font
namespace clash.
[originally from svn r7973]
2008-04-05 17:37:20 +04:00
|
|
|
/*
|
|
|
|
* read_setting_fontspec had to handle two cases, but when
|
|
|
|
* writing our settings back out we simply always generate the
|
|
|
|
* new-style name.
|
|
|
|
*/
|
|
|
|
char *suffname = dupcat(name, "Name", NULL);
|
|
|
|
write_setting_s(handle, suffname, result.name);
|
|
|
|
sfree(suffname);
|
2003-02-01 15:54:40 +03:00
|
|
|
}
|
|
|
|
void write_setting_filename(void *handle, const char *name, Filename result)
|
|
|
|
{
|
|
|
|
write_setting_s(handle, name, result.path);
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
void close_settings_r(void *handle)
|
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
tree234 *tree = (tree234 *)handle;
|
|
|
|
struct keyval *kv;
|
|
|
|
|
|
|
|
if (!tree)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while ( (kv = index234(tree, 0)) != NULL) {
|
|
|
|
del234(tree, kv);
|
|
|
|
sfree((char *)kv->key);
|
|
|
|
sfree((char *)kv->value);
|
|
|
|
sfree(kv);
|
|
|
|
}
|
|
|
|
|
|
|
|
freetree234(tree);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
void del_settings(const char *sessionname)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename;
|
|
|
|
filename = make_filename(INDEX_SESSION, sessionname);
|
2003-03-31 15:36:14 +04:00
|
|
|
unlink(filename);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void *enum_settings_start(void)
|
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
DIR *dp;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename;
|
2002-10-09 22:09:42 +04:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
filename = make_filename(INDEX_SESSIONDIR, NULL);
|
2003-03-31 15:36:14 +04:00
|
|
|
dp = opendir(filename);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2002-10-09 22:09:42 +04:00
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
return dp;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
char *enum_settings_next(void *handle, char *buffer, int buflen)
|
2002-10-31 22:49:52 +03:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
DIR *dp = (DIR *)handle;
|
|
|
|
struct dirent *de;
|
|
|
|
struct stat st;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *fullpath;
|
|
|
|
int maxlen, thislen, len;
|
2003-03-31 15:36:14 +04:00
|
|
|
char *unmunged;
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
fullpath = make_filename(INDEX_SESSIONDIR, NULL);
|
|
|
|
maxlen = len = strlen(fullpath);
|
2003-03-31 15:36:14 +04:00
|
|
|
|
|
|
|
while ( (de = readdir(dp)) != NULL ) {
|
2008-03-22 15:01:16 +03:00
|
|
|
thislen = len + 1 + strlen(de->d_name);
|
|
|
|
if (maxlen < thislen) {
|
|
|
|
maxlen = thislen;
|
|
|
|
fullpath = sresize(fullpath, maxlen+1, char);
|
|
|
|
}
|
|
|
|
fullpath[len] = '/';
|
|
|
|
strncpy(fullpath+len+1, de->d_name, thislen - (len+1));
|
|
|
|
fullpath[thislen] = '\0';
|
2003-03-31 15:36:14 +04:00
|
|
|
|
|
|
|
if (stat(fullpath, &st) < 0 || !S_ISREG(st.st_mode))
|
|
|
|
continue; /* try another one */
|
|
|
|
|
|
|
|
unmunged = unmungestr(de->d_name);
|
|
|
|
strncpy(buffer, unmunged, buflen);
|
|
|
|
buffer[buflen-1] = '\0';
|
|
|
|
sfree(unmunged);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(fullpath);
|
2003-03-31 15:36:14 +04:00
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(fullpath);
|
2003-03-31 15:36:14 +04:00
|
|
|
return NULL;
|
2002-10-31 22:49:52 +03:00
|
|
|
}
|
|
|
|
|
2003-03-31 15:36:14 +04:00
|
|
|
void enum_settings_finish(void *handle)
|
2002-10-31 22:49:52 +03:00
|
|
|
{
|
2003-03-31 15:36:14 +04:00
|
|
|
DIR *dp = (DIR *)handle;
|
|
|
|
closedir(dp);
|
2002-10-31 22:49:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lines in the host keys file are of the form
|
|
|
|
*
|
|
|
|
* type@port:hostname keydata
|
|
|
|
*
|
|
|
|
* e.g.
|
|
|
|
*
|
|
|
|
* rsa@22:foovax.example.org 0x23,0x293487364395345345....2343
|
|
|
|
*/
|
2003-01-14 21:43:45 +03:00
|
|
|
int verify_host_key(const char *hostname, int port,
|
|
|
|
const char *keytype, const char *key)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-31 22:49:52 +03:00
|
|
|
FILE *fp;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename;
|
2002-10-31 22:49:52 +03:00
|
|
|
char *line;
|
|
|
|
int ret;
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
filename = make_filename(INDEX_HOSTKEYS, NULL);
|
2002-10-31 22:49:52 +03:00
|
|
|
fp = fopen(filename, "r");
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(filename);
|
2002-10-31 22:49:52 +03:00
|
|
|
if (!fp)
|
|
|
|
return 1; /* key does not exist */
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
while ( (line = fgetline(fp)) ) {
|
|
|
|
int i;
|
|
|
|
char *p = line;
|
|
|
|
char porttext[20];
|
|
|
|
|
|
|
|
line[strcspn(line, "\n")] = '\0'; /* strip trailing newline */
|
|
|
|
|
|
|
|
i = strlen(keytype);
|
|
|
|
if (strncmp(p, keytype, i))
|
|
|
|
goto done;
|
|
|
|
p += i;
|
|
|
|
|
|
|
|
if (*p != '@')
|
|
|
|
goto done;
|
|
|
|
p++;
|
|
|
|
|
|
|
|
sprintf(porttext, "%d", port);
|
|
|
|
i = strlen(porttext);
|
|
|
|
if (strncmp(p, porttext, i))
|
|
|
|
goto done;
|
|
|
|
p += i;
|
|
|
|
|
|
|
|
if (*p != ':')
|
|
|
|
goto done;
|
|
|
|
p++;
|
|
|
|
|
|
|
|
i = strlen(hostname);
|
|
|
|
if (strncmp(p, hostname, i))
|
|
|
|
goto done;
|
|
|
|
p += i;
|
|
|
|
|
|
|
|
if (*p != ' ')
|
|
|
|
goto done;
|
|
|
|
p++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Found the key. Now just work out whether it's the right
|
|
|
|
* one or not.
|
|
|
|
*/
|
|
|
|
if (!strcmp(p, key))
|
|
|
|
ret = 0; /* key matched OK */
|
|
|
|
else
|
|
|
|
ret = 2; /* key mismatch */
|
|
|
|
|
|
|
|
done:
|
|
|
|
sfree(line);
|
|
|
|
if (ret != 1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2003-11-01 00:45:15 +03:00
|
|
|
fclose(fp);
|
2002-10-31 22:49:52 +03:00
|
|
|
return ret;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
void store_host_key(const char *hostname, int port,
|
|
|
|
const char *keytype, const char *key)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2004-01-17 16:00:18 +03:00
|
|
|
FILE *rfp, *wfp;
|
|
|
|
char *newtext, *line;
|
|
|
|
int headerlen;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *filename, *tmpfilename;
|
2002-10-31 22:49:52 +03:00
|
|
|
|
2004-01-17 16:00:18 +03:00
|
|
|
newtext = dupprintf("%s@%d:%s %s\n", keytype, port, hostname, key);
|
|
|
|
headerlen = 1 + strcspn(newtext, " "); /* count the space too */
|
2002-10-31 22:49:52 +03:00
|
|
|
|
2004-01-17 16:00:18 +03:00
|
|
|
/*
|
|
|
|
* Open both the old file and a new file.
|
|
|
|
*/
|
2008-03-22 15:01:16 +03:00
|
|
|
tmpfilename = make_filename(INDEX_HOSTKEYS_TMP, NULL);
|
2004-01-17 16:00:18 +03:00
|
|
|
wfp = fopen(tmpfilename, "w");
|
|
|
|
if (!wfp) {
|
2008-03-22 15:01:16 +03:00
|
|
|
char *dir;
|
2004-01-19 12:37:17 +03:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
dir = make_filename(INDEX_DIR, NULL);
|
2004-01-19 12:37:17 +03:00
|
|
|
mkdir(dir, 0700);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(dir);
|
|
|
|
|
2004-01-19 12:37:17 +03:00
|
|
|
wfp = fopen(tmpfilename, "w");
|
2002-10-31 22:49:52 +03:00
|
|
|
}
|
2008-03-22 15:01:16 +03:00
|
|
|
if (!wfp) {
|
|
|
|
sfree(tmpfilename);
|
2004-01-19 12:37:17 +03:00
|
|
|
return;
|
2008-03-22 15:01:16 +03:00
|
|
|
}
|
|
|
|
filename = make_filename(INDEX_HOSTKEYS, NULL);
|
2004-01-19 12:37:17 +03:00
|
|
|
rfp = fopen(filename, "r");
|
2004-01-17 16:00:18 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy all lines from the old file to the new one that _don't_
|
|
|
|
* involve the same host key identifier as the one we're adding.
|
|
|
|
*/
|
2004-01-19 12:37:17 +03:00
|
|
|
if (rfp) {
|
|
|
|
while ( (line = fgetline(rfp)) ) {
|
|
|
|
if (strncmp(line, newtext, headerlen))
|
|
|
|
fputs(line, wfp);
|
|
|
|
}
|
|
|
|
fclose(rfp);
|
2002-10-31 22:49:52 +03:00
|
|
|
}
|
2004-01-17 16:00:18 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now add the new line at the end.
|
|
|
|
*/
|
|
|
|
fputs(newtext, wfp);
|
|
|
|
|
|
|
|
fclose(wfp);
|
|
|
|
|
|
|
|
rename(tmpfilename, filename);
|
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(tmpfilename);
|
|
|
|
sfree(filename);
|
2004-01-17 16:00:18 +03:00
|
|
|
sfree(newtext);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void read_random_seed(noise_consumer_t consumer)
|
|
|
|
{
|
2002-11-02 18:23:20 +03:00
|
|
|
int fd;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *fname;
|
2002-11-02 18:23:20 +03:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
fname = make_filename(INDEX_RANDSEED, NULL);
|
2002-11-02 18:23:20 +03:00
|
|
|
fd = open(fname, O_RDONLY);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(fname);
|
2002-11-02 18:23:20 +03:00
|
|
|
if (fd) {
|
|
|
|
char buf[512];
|
|
|
|
int ret;
|
|
|
|
while ( (ret = read(fd, buf, sizeof(buf))) > 0)
|
|
|
|
consumer(buf, ret);
|
|
|
|
close(fd);
|
|
|
|
}
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void write_random_seed(void *data, int len)
|
|
|
|
{
|
2002-11-02 18:23:20 +03:00
|
|
|
int fd;
|
2008-03-22 15:01:16 +03:00
|
|
|
char *fname;
|
2002-11-02 18:23:20 +03:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
fname = make_filename(INDEX_RANDSEED, NULL);
|
2002-11-07 23:01:04 +03:00
|
|
|
/*
|
|
|
|
* Don't truncate the random seed file if it already exists; if
|
|
|
|
* something goes wrong half way through writing it, it would
|
|
|
|
* be better to leave the old data there than to leave it empty.
|
|
|
|
*/
|
|
|
|
fd = open(fname, O_CREAT | O_WRONLY, 0600);
|
2002-11-02 18:23:20 +03:00
|
|
|
if (fd < 0) {
|
2008-03-22 15:01:16 +03:00
|
|
|
char *dir;
|
2002-11-02 18:23:20 +03:00
|
|
|
|
2008-03-22 15:01:16 +03:00
|
|
|
dir = make_filename(INDEX_DIR, NULL);
|
2002-11-02 18:23:20 +03:00
|
|
|
mkdir(dir, 0700);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(dir);
|
|
|
|
|
2002-11-07 23:01:04 +03:00
|
|
|
fd = open(fname, O_CREAT | O_WRONLY, 0600);
|
2002-11-02 18:23:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
while (len > 0) {
|
|
|
|
int ret = write(fd, data, len);
|
|
|
|
if (ret <= 0) break;
|
|
|
|
len -= ret;
|
|
|
|
data = (char *)data + len;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(fd);
|
2008-03-22 15:01:16 +03:00
|
|
|
sfree(fname);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void cleanup_all(void)
|
|
|
|
{
|
|
|
|
}
|