Skip to content
Browse files

Rewrite gprefs() in settings.c so that its input mapping includes

information about where to put items that aren't mentioned in the
saved configuration. So far the only nontrivial use I've made of this
facility is to default to placing KEX_RSA just above KEX_WARN in the
absence of any other information, which should fix
'ssh2-rsa-kex-pref'.

While I'm here I've rewritten wprefs() on general principles to remove
the needless length limit, since I was touching it anyway. The length
limit is still in gprefs (but I've lengthened it just in case).


git-svn-id: svn://svn.tartarus.org/sgt/putty@9181 cda61777-01e9-0310-a592-d414129be87e
  • Loading branch information...
1 parent ac3337f commit 4ceef22460eca9798463c80ff09c74942d0f25b6 simon committed Jun 25, 2011
Showing with 159 additions and 68 deletions.
  1. +1 −1 nogss.c
  2. +43 −3 putty.h
  3. +104 −53 settings.c
  4. +7 −7 unix/uxgss.c
  5. +4 −4 windows/wingss.c
View
2 nogss.c
@@ -8,4 +8,4 @@
const int ngsslibs = 0;
const char *const gsslibnames[1] = { "dummy" };
-const struct keyval gsslibkeywords[1] = { { "dummy", 0 } };
+const struct keyvalwhere gsslibkeywords[1] = { { "dummy", 0, -1, -1 } };
View
46 putty.h
@@ -353,12 +353,52 @@ enum {
* Defined here so that backends can export their GSS library tables
* to the cross-platform settings code.
*/
-struct keyval { char *s; int v; };
+struct keyvalwhere {
+ /*
+ * Two fields which define a string and enum value to be
+ * equivalent to each other.
+ */
+ char *s;
+ int v;
+
+ /*
+ * The next pair of fields are used by gprefs() in settings.c to
+ * arrange that when it reads a list of strings representing a
+ * preference list and translates it into the corresponding list
+ * of integers, strings not appearing in the list are entered in a
+ * configurable position rather than uniformly at the end.
+ */
+
+ /*
+ * 'vrel' indicates which other value in the list to place this
+ * element relative to. It should be a value that has occurred in
+ * a 'v' field of some other element of the array, or -1 to
+ * indicate that we simply place relative to one or other end of
+ * the list.
+ *
+ * gprefs will try to process the elements in an order which makes
+ * this field work (i.e. so that the element referenced has been
+ * added before processing this one).
+ */
+ int vrel;
+
+ /*
+ * 'where' indicates whether to place the new value before or
+ * after the one referred to by vrel. -1 means before; +1 means
+ * after.
+ *
+ * When vrel is -1, this also implicitly indicates which end of
+ * the array to use. So vrel=-1, where=-1 means to place _before_
+ * some end of the list (hence, at the last element); vrel=-1,
+ * where=+1 means to place _after_ an end (hence, at the first).
+ */
+ int where;
+};
#ifndef NO_GSSAPI
extern const int ngsslibs;
-extern const char *const gsslibnames[];/* for displaying in configuration */
-extern const struct keyval gsslibkeywords[]; /* for storing by settings.c */
+extern const char *const gsslibnames[]; /* for displaying in configuration */
+extern const struct keyvalwhere gsslibkeywords[]; /* for settings.c */
#endif
extern const char *const ttymodes[];
View
157 settings.c
@@ -9,21 +9,21 @@
#include "storage.h"
/* The cipher order given here is the default order. */
-static const struct keyval ciphernames[] = {
- { "aes", CIPHER_AES },
- { "blowfish", CIPHER_BLOWFISH },
- { "3des", CIPHER_3DES },
- { "WARN", CIPHER_WARN },
- { "arcfour", CIPHER_ARCFOUR },
- { "des", CIPHER_DES }
+static const struct keyvalwhere ciphernames[] = {
+ { "aes", CIPHER_AES, -1, -1 },
+ { "blowfish", CIPHER_BLOWFISH, -1, -1 },
+ { "3des", CIPHER_3DES, -1, -1 },
+ { "WARN", CIPHER_WARN, -1, -1 },
+ { "arcfour", CIPHER_ARCFOUR, -1, -1 },
+ { "des", CIPHER_DES, -1, -1 }
};
-static const struct keyval kexnames[] = {
- { "dh-gex-sha1", KEX_DHGEX },
- { "dh-group14-sha1", KEX_DHGROUP14 },
- { "dh-group1-sha1", KEX_DHGROUP1 },
- { "rsa", KEX_RSA },
- { "WARN", KEX_WARN }
+static const struct keyvalwhere kexnames[] = {
+ { "dh-gex-sha1", KEX_DHGEX, -1, -1 },
+ { "dh-group14-sha1", KEX_DHGROUP14, -1, -1 },
+ { "dh-group1-sha1", KEX_DHGROUP1, -1, -1 },
+ { "rsa", KEX_RSA, KEX_WARN, -1 },
+ { "WARN", KEX_WARN, -1, -1 }
};
/*
@@ -188,15 +188,17 @@ static void wmap(void *handle, char const *key, char const *value, int len)
sfree(buf);
}
-static int key2val(const struct keyval *mapping, int nmaps, char *key)
+static int key2val(const struct keyvalwhere *mapping,
+ int nmaps, char *key)
{
int i;
for (i = 0; i < nmaps; i++)
if (!strcmp(mapping[i].s, key)) return mapping[i].v;
return -1;
}
-static const char *val2key(const struct keyval *mapping, int nmaps, int val)
+static const char *val2key(const struct keyvalwhere *mapping,
+ int nmaps, int val)
{
int i;
for (i = 0; i < nmaps; i++)
@@ -211,66 +213,115 @@ static const char *val2key(const struct keyval *mapping, int nmaps, int val)
* XXX: assumes vals in 'mapping' are small +ve integers
*/
static void gprefs(void *sesskey, char *name, char *def,
- const struct keyval *mapping, int nvals,
+ const struct keyvalwhere *mapping, int nvals,
int *array)
{
- char commalist[80];
- char *tokarg = commalist;
- int n;
+ char commalist[256];
+ char *p, *q;
+ int i, j, n, v, pos;
unsigned long seen = 0; /* bitmap for weeding dups etc */
+
+ /*
+ * Fetch the string which we'll parse as a comma-separated list.
+ */
gpps(sesskey, name, def, commalist, sizeof(commalist));
- /* Grotty parsing of commalist. */
+ /*
+ * Go through that list and convert it into values.
+ */
n = 0;
- do {
- int v;
- char *key;
- key = strtok(tokarg, ","); /* sorry */
- tokarg = NULL;
- if (!key) break;
- if (((v = key2val(mapping, nvals, key)) != -1) &&
- !(seen & 1<<v)) {
- array[n] = v;
- n++;
- seen |= 1<<v;
+ p = commalist;
+ while (1) {
+ while (*p && *p == ',') p++;
+ if (!*p)
+ break; /* no more words */
+
+ q = p;
+ while (*p && *p != ',') p++;
+ if (*p) *p++ = '\0';
+
+ v = key2val(mapping, nvals, q);
+ if (v != -1 && !(seen & (1 << v))) {
+ seen |= (1 << v);
+ array[n++] = v;
}
- } while (n < nvals);
- /* Add any missing values (backward compatibility ect). */
- {
- int i;
- for (i = 0; i < nvals; i++) {
+ }
+
+ /*
+ * Now go through 'mapping' and add values that weren't mentioned
+ * in the list we fetched. We may have to loop over it multiple
+ * times so that we add values before other values whose default
+ * positions depend on them.
+ */
+ while (n < nvals) {
+ for (i = 0; i < nvals; i++) {
assert(mapping[i].v < 32);
- if (!(seen & 1<<mapping[i].v)) {
- array[n] = mapping[i].v;
- n++;
- }
- }
+
+ if (!(seen & (1 << mapping[i].v))) {
+ /*
+ * This element needs adding. But can we add it yet?
+ */
+ if (mapping[i].vrel != -1 && !(seen & (1 << mapping[i].vrel)))
+ continue; /* nope */
+
+ /*
+ * OK, we can work out where to add this element, so
+ * do so.
+ */
+ if (mapping[i].vrel == -1) {
+ pos = (mapping[i].where < 0 ? n : 0);
+ } else {
+ for (j = 0; j < n; j++)
+ if (array[j] == mapping[i].vrel)
+ break;
+ assert(j < n); /* implied by (seen & (1<<vrel)) */
+ pos = (mapping[i].where < 0 ? j : j+1);
+ }
+
+ /*
+ * And add it.
+ */
+ for (j = n-1; j >= pos; j--)
+ array[j+1] = array[j];
+ array[pos] = mapping[i].v;
+ n++;
+ }
+ }
}
}
/*
* Write out a preference list.
*/
static void wprefs(void *sesskey, char *name,
- const struct keyval *mapping, int nvals,
+ const struct keyvalwhere *mapping, int nvals,
int *array)
{
- char buf[80] = ""; /* XXX assumed big enough */
- int l = sizeof(buf)-1, i;
- buf[l] = '\0';
- for (i = 0; l > 0 && i < nvals; i++) {
+ char *buf, *p;
+ int i, maxlen;
+
+ for (maxlen = i = 0; i < nvals; i++) {
const char *s = val2key(mapping, nvals, array[i]);
if (s) {
- int sl = strlen(s);
- if (i > 0) {
- strncat(buf, ",", l);
- l--;
- }
- strncat(buf, s, l);
- l -= sl;
+ maxlen += 1 + strlen(s);
+ }
+ }
+
+ buf = snewn(maxlen, char);
+ p = buf;
+
+ for (i = 0; i < nvals; i++) {
+ const char *s = val2key(mapping, nvals, array[i]);
+ if (s) {
+ p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);
}
}
+
+ assert(p - buf == maxlen - 1); /* maxlen counted the NUL */
+
write_setting_s(sesskey, name, buf);
+
+ sfree(buf);
}
char *save_settings(char *section, Config * cfg)
View
14 unix/uxgss.c
@@ -15,11 +15,11 @@ const char *const gsslibnames[4] = {
"libgss (Sun)",
"User-specified GSSAPI library",
};
-const struct keyval gsslibkeywords[] = {
- { "libgssapi", 0 },
- { "libgssapi_krb5", 1 },
- { "libgss", 2 },
- { "custom", 3 },
+const struct keyvalwhere gsslibkeywords[] = {
+ { "libgssapi", 0, -1, -1 },
+ { "libgssapi_krb5", 1, -1, -1 },
+ { "libgss", 2, -1, -1 },
+ { "custom", 3, -1, -1 },
};
/*
@@ -116,8 +116,8 @@ const int ngsslibs = 1;
const char *const gsslibnames[1] = {
"static",
};
-const struct keyval gsslibkeywords[] = {
- { "static", 0 },
+const struct keyvalwhere gsslibkeywords[] = {
+ { "static", 0, -1, -1 },
};
/*
View
8 windows/wingss.c
@@ -18,10 +18,10 @@ const char *const gsslibnames[3] = {
"Microsoft SSPI SECUR32.DLL",
"User-specified GSSAPI DLL",
};
-const struct keyval gsslibkeywords[] = {
- { "gssapi32", 0 },
- { "sspi", 1 },
- { "custom", 2 },
+const struct keyvalwhere gsslibkeywords[] = {
+ { "gssapi32", 0, -1, -1 },
+ { "sspi", 1, -1, -1 },
+ { "custom", 2, -1, -1 },
};
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,

0 comments on commit 4ceef22

Please sign in to comment.
Something went wrong with that request. Please try again.