diff --git a/nogss.c b/nogss.c index adb1e224..844a1323 100644 --- a/nogss.c +++ b/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 } }; diff --git a/putty.h b/putty.h index 9fddcae6..78bc4294 100644 --- a/putty.h +++ b/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[]; diff --git a/settings.c b/settings.c index 82b915a9..943fbf3e 100644 --- a/settings.c +++ b/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,7 +188,8 @@ 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++) @@ -196,7 +197,8 @@ static int key2val(const struct keyval *mapping, int nmaps, char *key) 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,40 +213,80 @@ 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<= pos; j--) + array[j+1] = array[j]; + array[pos] = mapping[i].v; + n++; + } + } } } @@ -252,25 +294,34 @@ static void gprefs(void *sesskey, char *name, char *def, * 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) diff --git a/unix/uxgss.c b/unix/uxgss.c index 62d517ab..278fb866 100644 --- a/unix/uxgss.c +++ b/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 }, }; /* diff --git a/windows/wingss.c b/windows/wingss.c index 9084c3cf..a161ad6e 100644 --- a/windows/wingss.c +++ b/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,