Skip to content

Commit d764872

Browse files
committed
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). [originally from svn r9181]
1 parent af78191 commit d764872

File tree

5 files changed

+159
-68
lines changed

5 files changed

+159
-68
lines changed

nogss.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88

99
const int ngsslibs = 0;
1010
const char *const gsslibnames[1] = { "dummy" };
11-
const struct keyval gsslibkeywords[1] = { { "dummy", 0 } };
11+
const struct keyvalwhere gsslibkeywords[1] = { { "dummy", 0, -1, -1 } };

putty.h

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,52 @@ enum {
353353
* Defined here so that backends can export their GSS library tables
354354
* to the cross-platform settings code.
355355
*/
356-
struct keyval { char *s; int v; };
356+
struct keyvalwhere {
357+
/*
358+
* Two fields which define a string and enum value to be
359+
* equivalent to each other.
360+
*/
361+
char *s;
362+
int v;
363+
364+
/*
365+
* The next pair of fields are used by gprefs() in settings.c to
366+
* arrange that when it reads a list of strings representing a
367+
* preference list and translates it into the corresponding list
368+
* of integers, strings not appearing in the list are entered in a
369+
* configurable position rather than uniformly at the end.
370+
*/
371+
372+
/*
373+
* 'vrel' indicates which other value in the list to place this
374+
* element relative to. It should be a value that has occurred in
375+
* a 'v' field of some other element of the array, or -1 to
376+
* indicate that we simply place relative to one or other end of
377+
* the list.
378+
*
379+
* gprefs will try to process the elements in an order which makes
380+
* this field work (i.e. so that the element referenced has been
381+
* added before processing this one).
382+
*/
383+
int vrel;
384+
385+
/*
386+
* 'where' indicates whether to place the new value before or
387+
* after the one referred to by vrel. -1 means before; +1 means
388+
* after.
389+
*
390+
* When vrel is -1, this also implicitly indicates which end of
391+
* the array to use. So vrel=-1, where=-1 means to place _before_
392+
* some end of the list (hence, at the last element); vrel=-1,
393+
* where=+1 means to place _after_ an end (hence, at the first).
394+
*/
395+
int where;
396+
};
357397

358398
#ifndef NO_GSSAPI
359399
extern const int ngsslibs;
360-
extern const char *const gsslibnames[];/* for displaying in configuration */
361-
extern const struct keyval gsslibkeywords[]; /* for storing by settings.c */
400+
extern const char *const gsslibnames[]; /* for displaying in configuration */
401+
extern const struct keyvalwhere gsslibkeywords[]; /* for settings.c */
362402
#endif
363403

364404
extern const char *const ttymodes[];

settings.c

Lines changed: 104 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@
99
#include "storage.h"
1010

1111
/* The cipher order given here is the default order. */
12-
static const struct keyval ciphernames[] = {
13-
{ "aes", CIPHER_AES },
14-
{ "blowfish", CIPHER_BLOWFISH },
15-
{ "3des", CIPHER_3DES },
16-
{ "WARN", CIPHER_WARN },
17-
{ "arcfour", CIPHER_ARCFOUR },
18-
{ "des", CIPHER_DES }
12+
static const struct keyvalwhere ciphernames[] = {
13+
{ "aes", CIPHER_AES, -1, -1 },
14+
{ "blowfish", CIPHER_BLOWFISH, -1, -1 },
15+
{ "3des", CIPHER_3DES, -1, -1 },
16+
{ "WARN", CIPHER_WARN, -1, -1 },
17+
{ "arcfour", CIPHER_ARCFOUR, -1, -1 },
18+
{ "des", CIPHER_DES, -1, -1 }
1919
};
2020

21-
static const struct keyval kexnames[] = {
22-
{ "dh-gex-sha1", KEX_DHGEX },
23-
{ "dh-group14-sha1", KEX_DHGROUP14 },
24-
{ "dh-group1-sha1", KEX_DHGROUP1 },
25-
{ "rsa", KEX_RSA },
26-
{ "WARN", KEX_WARN }
21+
static const struct keyvalwhere kexnames[] = {
22+
{ "dh-gex-sha1", KEX_DHGEX, -1, -1 },
23+
{ "dh-group14-sha1", KEX_DHGROUP14, -1, -1 },
24+
{ "dh-group1-sha1", KEX_DHGROUP1, -1, -1 },
25+
{ "rsa", KEX_RSA, KEX_WARN, -1 },
26+
{ "WARN", KEX_WARN, -1, -1 }
2727
};
2828

2929
/*
@@ -188,15 +188,17 @@ static void wmap(void *handle, char const *key, char const *value, int len)
188188
sfree(buf);
189189
}
190190

191-
static int key2val(const struct keyval *mapping, int nmaps, char *key)
191+
static int key2val(const struct keyvalwhere *mapping,
192+
int nmaps, char *key)
192193
{
193194
int i;
194195
for (i = 0; i < nmaps; i++)
195196
if (!strcmp(mapping[i].s, key)) return mapping[i].v;
196197
return -1;
197198
}
198199

199-
static const char *val2key(const struct keyval *mapping, int nmaps, int val)
200+
static const char *val2key(const struct keyvalwhere *mapping,
201+
int nmaps, int val)
200202
{
201203
int i;
202204
for (i = 0; i < nmaps; i++)
@@ -211,66 +213,115 @@ static const char *val2key(const struct keyval *mapping, int nmaps, int val)
211213
* XXX: assumes vals in 'mapping' are small +ve integers
212214
*/
213215
static void gprefs(void *sesskey, char *name, char *def,
214-
const struct keyval *mapping, int nvals,
216+
const struct keyvalwhere *mapping, int nvals,
215217
int *array)
216218
{
217-
char commalist[80];
218-
char *tokarg = commalist;
219-
int n;
219+
char commalist[256];
220+
char *p, *q;
221+
int i, j, n, v, pos;
220222
unsigned long seen = 0; /* bitmap for weeding dups etc */
223+
224+
/*
225+
* Fetch the string which we'll parse as a comma-separated list.
226+
*/
221227
gpps(sesskey, name, def, commalist, sizeof(commalist));
222228

223-
/* Grotty parsing of commalist. */
229+
/*
230+
* Go through that list and convert it into values.
231+
*/
224232
n = 0;
225-
do {
226-
int v;
227-
char *key;
228-
key = strtok(tokarg, ","); /* sorry */
229-
tokarg = NULL;
230-
if (!key) break;
231-
if (((v = key2val(mapping, nvals, key)) != -1) &&
232-
!(seen & 1<<v)) {
233-
array[n] = v;
234-
n++;
235-
seen |= 1<<v;
233+
p = commalist;
234+
while (1) {
235+
while (*p && *p == ',') p++;
236+
if (!*p)
237+
break; /* no more words */
238+
239+
q = p;
240+
while (*p && *p != ',') p++;
241+
if (*p) *p++ = '\0';
242+
243+
v = key2val(mapping, nvals, q);
244+
if (v != -1 && !(seen & (1 << v))) {
245+
seen |= (1 << v);
246+
array[n++] = v;
236247
}
237-
} while (n < nvals);
238-
/* Add any missing values (backward compatibility ect). */
239-
{
240-
int i;
241-
for (i = 0; i < nvals; i++) {
248+
}
249+
250+
/*
251+
* Now go through 'mapping' and add values that weren't mentioned
252+
* in the list we fetched. We may have to loop over it multiple
253+
* times so that we add values before other values whose default
254+
* positions depend on them.
255+
*/
256+
while (n < nvals) {
257+
for (i = 0; i < nvals; i++) {
242258
assert(mapping[i].v < 32);
243-
if (!(seen & 1<<mapping[i].v)) {
244-
array[n] = mapping[i].v;
245-
n++;
246-
}
247-
}
259+
260+
if (!(seen & (1 << mapping[i].v))) {
261+
/*
262+
* This element needs adding. But can we add it yet?
263+
*/
264+
if (mapping[i].vrel != -1 && !(seen & (1 << mapping[i].vrel)))
265+
continue; /* nope */
266+
267+
/*
268+
* OK, we can work out where to add this element, so
269+
* do so.
270+
*/
271+
if (mapping[i].vrel == -1) {
272+
pos = (mapping[i].where < 0 ? n : 0);
273+
} else {
274+
for (j = 0; j < n; j++)
275+
if (array[j] == mapping[i].vrel)
276+
break;
277+
assert(j < n); /* implied by (seen & (1<<vrel)) */
278+
pos = (mapping[i].where < 0 ? j : j+1);
279+
}
280+
281+
/*
282+
* And add it.
283+
*/
284+
for (j = n-1; j >= pos; j--)
285+
array[j+1] = array[j];
286+
array[pos] = mapping[i].v;
287+
n++;
288+
}
289+
}
248290
}
249291
}
250292

251293
/*
252294
* Write out a preference list.
253295
*/
254296
static void wprefs(void *sesskey, char *name,
255-
const struct keyval *mapping, int nvals,
297+
const struct keyvalwhere *mapping, int nvals,
256298
int *array)
257299
{
258-
char buf[80] = ""; /* XXX assumed big enough */
259-
int l = sizeof(buf)-1, i;
260-
buf[l] = '\0';
261-
for (i = 0; l > 0 && i < nvals; i++) {
300+
char *buf, *p;
301+
int i, maxlen;
302+
303+
for (maxlen = i = 0; i < nvals; i++) {
262304
const char *s = val2key(mapping, nvals, array[i]);
263305
if (s) {
264-
int sl = strlen(s);
265-
if (i > 0) {
266-
strncat(buf, ",", l);
267-
l--;
268-
}
269-
strncat(buf, s, l);
270-
l -= sl;
306+
maxlen += 1 + strlen(s);
307+
}
308+
}
309+
310+
buf = snewn(maxlen, char);
311+
p = buf;
312+
313+
for (i = 0; i < nvals; i++) {
314+
const char *s = val2key(mapping, nvals, array[i]);
315+
if (s) {
316+
p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);
271317
}
272318
}
319+
320+
assert(p - buf == maxlen - 1); /* maxlen counted the NUL */
321+
273322
write_setting_s(sesskey, name, buf);
323+
324+
sfree(buf);
274325
}
275326

276327
char *save_settings(char *section, Config * cfg)

unix/uxgss.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const char *const gsslibnames[4] = {
1515
"libgss (Sun)",
1616
"User-specified GSSAPI library",
1717
};
18-
const struct keyval gsslibkeywords[] = {
19-
{ "libgssapi", 0 },
20-
{ "libgssapi_krb5", 1 },
21-
{ "libgss", 2 },
22-
{ "custom", 3 },
18+
const struct keyvalwhere gsslibkeywords[] = {
19+
{ "libgssapi", 0, -1, -1 },
20+
{ "libgssapi_krb5", 1, -1, -1 },
21+
{ "libgss", 2, -1, -1 },
22+
{ "custom", 3, -1, -1 },
2323
};
2424

2525
/*
@@ -116,8 +116,8 @@ const int ngsslibs = 1;
116116
const char *const gsslibnames[1] = {
117117
"static",
118118
};
119-
const struct keyval gsslibkeywords[] = {
120-
{ "static", 0 },
119+
const struct keyvalwhere gsslibkeywords[] = {
120+
{ "static", 0, -1, -1 },
121121
};
122122

123123
/*

windows/wingss.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ const char *const gsslibnames[3] = {
1818
"Microsoft SSPI SECUR32.DLL",
1919
"User-specified GSSAPI DLL",
2020
};
21-
const struct keyval gsslibkeywords[] = {
22-
{ "gssapi32", 0 },
23-
{ "sspi", 1 },
24-
{ "custom", 2 },
21+
const struct keyvalwhere gsslibkeywords[] = {
22+
{ "gssapi32", 0, -1, -1 },
23+
{ "sspi", 1, -1, -1 },
24+
{ "custom", 2, -1, -1 },
2525
};
2626

2727
DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS,

0 commit comments

Comments
 (0)