1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 19:42:48 -05:00

Rewrite some manual char-buffer-handling code.

In the course of recent refactorings I noticed a couple of cases where
we were doing old-fashioned preallocation of a char array with some
conservative maximum size, then writing into it via *p++ or similar
and hoping we got the calculation right.

Now we have strbuf and dupcat, so we shouldn't ever have to do that.
Fixed as many cases as I could find by searching for allocations of
the form 'snewn(foo, char)'.

Particularly worth a mention was the Windows GSSAPI setup code, which
was directly using the Win32 Registry API, and looks much more legible
using the windows/utils/registry.c wrappers. (But that was why I had
to enhance them in the previous commit so as to be able to open
registry keys read-only: without that, the open operation would
actually fail on this key, which is not user-writable.)

Also unix/askpass.c, which was doing a careful reallocation of its
buffer to avoid secrets being left behind in the vacated memory -
which is now just a matter of ensuring we called strbuf_new_nm().
This commit is contained in:
Simon Tatham
2022-09-13 15:00:26 +01:00
parent 7339e00f4a
commit 6cf6682c54
13 changed files with 174 additions and 291 deletions

View File

@ -358,28 +358,26 @@ static void proc_rec_opt(Telnet *telnet, int cmd, int option)
static void process_subneg(Telnet *telnet)
{
unsigned char *b, *p, *q;
int var, value, n, bsize;
char *e, *eval, *ekey, *user;
unsigned char *p, *q;
int var, value;
switch (telnet->sb_opt) {
case TELOPT_TSPEED:
if (telnet->sb_buf->len == 1 && telnet->sb_buf->u[0] == TELQUAL_SEND) {
char *termspeed = conf_get_str(telnet->conf, CONF_termspeed);
b = snewn(20 + strlen(termspeed), unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
strcpy((char *)(b + 4), termspeed);
n = 4 + strlen(termspeed);
b[n] = IAC;
b[n + 1] = SE;
telnet->bufsize = sk_write(telnet->s, b, n + 2);
strbuf *sb = strbuf_new();
put_byte(sb, IAC);
put_byte(sb, SB);
put_byte(sb, TELOPT_TSPEED);
put_byte(sb, TELQUAL_IS);
put_datapl(sb, ptrlen_from_asciz(termspeed));
put_byte(sb, IAC);
put_byte(sb, SE);
telnet->bufsize = sk_write(telnet->s, sb->s, sb->len);
logevent(telnet->logctx, "server subnegotiation: SB TSPEED SEND");
logeventf(telnet->logctx,
"client subnegotiation: SB TSPEED IS %s", termspeed);
sfree(b);
strbuf_free(sb);
} else
logevent(telnet->logctx,
"server subnegotiation: SB TSPEED <something weird>");
@ -387,24 +385,24 @@ static void process_subneg(Telnet *telnet)
case TELOPT_TTYPE:
if (telnet->sb_buf->len == 1 && telnet->sb_buf->u[0] == TELQUAL_SEND) {
char *termtype = conf_get_str(telnet->conf, CONF_termtype);
b = snewn(20 + strlen(termtype), unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
for (n = 0; termtype[n]; n++)
b[n + 4] = (termtype[n] >= 'a' && termtype[n] <= 'z' ?
termtype[n] + 'A' - 'a' :
termtype[n]);
b[n + 4] = IAC;
b[n + 5] = SE;
telnet->bufsize = sk_write(telnet->s, b, n + 6);
b[n + 4] = 0;
logevent(telnet->logctx,
"server subnegotiation: SB TTYPE SEND");
logeventf(telnet->logctx,
"client subnegotiation: SB TTYPE IS %s", b + 4);
sfree(b);
strbuf *sb = strbuf_new();
put_byte(sb, IAC);
put_byte(sb, SB);
put_byte(sb, TELOPT_TTYPE);
put_byte(sb, TELQUAL_IS);
size_t tt_start = sb->len;
for (size_t n = 0; termtype[n]; n++)
put_byte(sb, (termtype[n] >= 'a' && termtype[n] <= 'z' ?
termtype[n] + 'A' - 'a' : termtype[n]));
size_t tt_end = sb->len;
put_byte(sb, IAC);
put_byte(sb, SE);
telnet->bufsize = sk_write(telnet->s, sb->s, sb->len);
strbuf_shrink_to(sb, tt_end);
logevent(telnet->logctx, "server subnegotiation: SB TTYPE SEND");
logeventf(telnet->logctx, "client subnegotiation: SB TTYPE IS %s",
sb->s + tt_start);
strbuf_free(sb);
} else
logevent(telnet->logctx,
"server subnegotiation: SB TTYPE <something weird>\r\n");
@ -446,49 +444,34 @@ static void process_subneg(Telnet *telnet)
value = RFC_VALUE;
var = RFC_VAR;
}
bsize = 20;
for (eval = conf_get_str_strs(telnet->conf, CONF_environmt,
NULL, &ekey);
eval != NULL;
eval = conf_get_str_strs(telnet->conf, CONF_environmt,
ekey, &ekey))
bsize += strlen(ekey) + strlen(eval) + 2;
user = get_remote_username(telnet->conf);
if (user)
bsize += 6 + strlen(user);
b = snewn(bsize, unsigned char);
b[0] = IAC;
b[1] = SB;
b[2] = telnet->sb_opt;
b[3] = TELQUAL_IS;
n = 4;
strbuf *sb = strbuf_new();
put_byte(sb, IAC);
put_byte(sb, SB);
put_byte(sb, telnet->sb_opt);
put_byte(sb, TELQUAL_IS);
char *ekey, *eval;
for (eval = conf_get_str_strs(telnet->conf, CONF_environmt,
NULL, &ekey);
eval != NULL;
eval = conf_get_str_strs(telnet->conf, CONF_environmt,
ekey, &ekey)) {
b[n++] = var;
for (e = ekey; *e; e++)
b[n++] = *e;
b[n++] = value;
for (e = eval; *e; e++)
b[n++] = *e;
put_byte(sb, var);
put_datapl(sb, ptrlen_from_asciz(ekey));
put_byte(sb, value);
put_datapl(sb, ptrlen_from_asciz(eval));
}
char *user = get_remote_username(telnet->conf);
if (user) {
b[n++] = var;
b[n++] = 'U';
b[n++] = 'S';
b[n++] = 'E';
b[n++] = 'R';
b[n++] = value;
for (e = user; *e; e++)
b[n++] = *e;
put_byte(sb, var);
put_datalit(sb, "USER");
put_byte(sb, value);
put_datapl(sb, ptrlen_from_asciz(user));
}
b[n++] = IAC;
b[n++] = SE;
telnet->bufsize = sk_write(telnet->s, b, n);
if (n == 6) {
put_byte(sb, IAC);
put_byte(sb, SE);
telnet->bufsize = sk_write(telnet->s, sb->s, sb->len);
if (sb->len == 6) {
logeventf(telnet->logctx,
"client subnegotiation: SB %s IS <nothing>",
telopt(telnet->sb_opt));
@ -505,7 +488,7 @@ static void process_subneg(Telnet *telnet)
if (user)
logeventf(telnet->logctx, " USER=%s", user);
}
sfree(b);
strbuf_free(sb);
sfree(user);
}
break;