telnet: parse telnet options without sscanf

Closes #10596
This commit is contained in:
Daniel Stenberg 2023-02-23 18:14:35 +01:00
parent 304b5183fd
commit 0c28ba2faa
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -774,18 +774,15 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
{
struct curl_slist *head;
struct curl_slist *beg;
char option_keyword[128] = "";
char option_arg[256] = "";
struct TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
CURLcode result = CURLE_OK;
int binary_option;
/* Add the user name as an environment variable if it
was given on the command line */
if(data->state.aptr.user) {
msnprintf(option_arg, sizeof(option_arg), "USER,%s", conn->user);
beg = curl_slist_append(tn->telnet_vars, option_arg);
char buffer[256];
msnprintf(buffer, sizeof(buffer), "USER,%s", data->conn->user);
beg = curl_slist_append(tn->telnet_vars, buffer);
if(!beg) {
curl_slist_free_all(tn->telnet_vars);
tn->telnet_vars = NULL;
@ -795,68 +792,89 @@ static CURLcode check_telnet_options(struct Curl_easy *data)
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
for(head = data->set.telnet_options; head; head = head->next) {
if(sscanf(head->data, "%127[^= ]%*[ =]%255s",
option_keyword, option_arg) == 2) {
/* Terminal type */
if(strcasecompare(option_keyword, "TTYPE")) {
strncpy(tn->subopt_ttype, option_arg, 31);
tn->subopt_ttype[31] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
continue;
}
/* Display variable */
if(strcasecompare(option_keyword, "XDISPLOC")) {
strncpy(tn->subopt_xdisploc, option_arg, 127);
tn->subopt_xdisploc[127] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
continue;
}
/* Environment variable */
if(strcasecompare(option_keyword, "NEW_ENV")) {
beg = curl_slist_append(tn->telnet_vars, option_arg);
if(!beg) {
result = CURLE_OUT_OF_MEMORY;
break;
for(head = data->set.telnet_options; head && !result; head = head->next) {
size_t olen;
char *option = head->data;
char *arg;
char *sep = strchr(option, '=');
if(sep) {
olen = sep - option;
arg = ++sep;
switch(olen) {
case 5:
/* Terminal type */
if(strncasecompare(option, "TTYPE", 5)) {
strncpy(tn->subopt_ttype, arg, 31);
tn->subopt_ttype[31] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_TTYPE] = CURL_YES;
}
tn->telnet_vars = beg;
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
continue;
}
else
result = CURLE_UNKNOWN_OPTION;
break;
/* Window Size */
if(strcasecompare(option_keyword, "WS")) {
if(sscanf(option_arg, "%hu%*[xX]%hu",
&tn->subopt_wsx, &tn->subopt_wsy) == 2)
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
else {
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
break;
case 8:
/* Display variable */
if(strncasecompare(option, "XDISPLOC", 8)) {
strncpy(tn->subopt_xdisploc, arg, 127);
tn->subopt_xdisploc[127] = 0; /* String termination */
tn->us_preferred[CURL_TELOPT_XDISPLOC] = CURL_YES;
}
continue;
}
else
result = CURLE_UNKNOWN_OPTION;
break;
/* To take care or not of the 8th bit in data exchange */
if(strcasecompare(option_keyword, "BINARY")) {
binary_option = atoi(option_arg);
if(binary_option != 1) {
tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
case 7:
/* Environment variable */
if(strncasecompare(option, "NEW_ENV", 7)) {
beg = curl_slist_append(tn->telnet_vars, arg);
if(!beg) {
result = CURLE_OUT_OF_MEMORY;
break;
}
tn->telnet_vars = beg;
tn->us_preferred[CURL_TELOPT_NEW_ENVIRON] = CURL_YES;
}
continue;
}
else
result = CURLE_UNKNOWN_OPTION;
break;
failf(data, "Unknown telnet option %s", head->data);
result = CURLE_UNKNOWN_OPTION;
break;
case 2:
/* Window Size */
if(strncasecompare(option, "WS", 2)) {
if(sscanf(arg, "%hu%*[xX]%hu",
&tn->subopt_wsx, &tn->subopt_wsy) == 2)
tn->us_preferred[CURL_TELOPT_NAWS] = CURL_YES;
else {
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
}
}
else
result = CURLE_UNKNOWN_OPTION;
break;
case 6:
/* To take care or not of the 8th bit in data exchange */
if(strncasecompare(option, "BINARY", 6)) {
int binary_option = atoi(arg);
if(binary_option != 1) {
tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO;
tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO;
}
}
else
result = CURLE_UNKNOWN_OPTION;
break;
default:
failf(data, "Unknown telnet option %s", head->data);
result = CURLE_UNKNOWN_OPTION;
break;
}
}
else {
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
}
failf(data, "Syntax error in telnet option: %s", head->data);
result = CURLE_SETOPT_OPTION_SYNTAX;
break;
}
if(result) {