dict: URL decode the entire path always

Reported-by: dekerser on github
Fixes #10298
Closes #10354
This commit is contained in:
Daniel Stenberg 2023-01-28 22:05:11 +01:00
parent 22d3e89e6f
commit 0c3d54269e
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2

View File

@ -98,37 +98,27 @@ const struct Curl_handler Curl_handler_dict = {
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
};
static char *unescape_word(const char *inputbuff)
#define DYN_DICT_WORD 10000
static char *unescape_word(const char *input)
{
char *newp = NULL;
char *dictp;
size_t len;
struct dynbuf out;
const char *ptr;
CURLcode result = CURLE_OK;
Curl_dyn_init(&out, DYN_DICT_WORD);
CURLcode result = Curl_urldecode(inputbuff, 0, &newp, &len,
REJECT_NADA);
if(!newp || result)
return NULL;
dictp = malloc(len*2 + 1); /* add one for terminating zero */
if(dictp) {
char *ptr;
char ch;
int olen = 0;
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
for(ptr = newp;
(ch = *ptr) != 0;
ptr++) {
if((ch <= 32) || (ch == 127) ||
(ch == '\'') || (ch == '\"') || (ch == '\\')) {
dictp[olen++] = '\\';
}
dictp[olen++] = ch;
}
dictp[olen] = 0;
/* According to RFC2229 section 2.2, these letters need to be escaped with
\[letter] */
for(ptr = input; *ptr; ptr++) {
char ch = *ptr;
if((ch <= 32) || (ch == 127) ||
(ch == '\'') || (ch == '\"') || (ch == '\\'))
result = Curl_dyn_addn(&out, "\\", 1);
if(!result)
result = Curl_dyn_addn(&out, ptr, 1);
if(result)
return NULL;
}
free(newp);
return dictp;
return Curl_dyn_ptr(&out);
}
/* sendf() sends formatted data to the server */
@ -178,20 +168,25 @@ static CURLcode sendf(curl_socket_t sockfd, struct Curl_easy *data,
static CURLcode dict_do(struct Curl_easy *data, bool *done)
{
char *word;
char *eword;
char *eword = NULL;
char *ppath;
char *database = NULL;
char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */
CURLcode result = CURLE_OK;
CURLcode result;
struct connectdata *conn = data->conn;
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
char *path = data->state.up.path;
char *path;
*done = TRUE; /* unconditionally */
/* url-decode path before further evaluation */
result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL);
if(result)
return result;
if(strncasecompare(path, DICT_MATCH, sizeof(DICT_MATCH)-1) ||
strncasecompare(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) ||
strncasecompare(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) {
@ -225,8 +220,10 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
eword = unescape_word(word);
if(!eword)
return CURLE_OUT_OF_MEMORY;
if(!eword) {
result = CURLE_OUT_OF_MEMORY;
goto error;
}
result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
@ -239,11 +236,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
strategy,
eword);
free(eword);
if(result) {
failf(data, "Failed sending DICT request");
return result;
goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); /* no upload */
}
@ -273,8 +268,10 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
}
eword = unescape_word(word);
if(!eword)
return CURLE_OUT_OF_MEMORY;
if(!eword) {
result = CURLE_OUT_OF_MEMORY;
goto error;
}
result = sendf(sockfd, data,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
@ -285,11 +282,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
database,
eword);
free(eword);
if(result) {
failf(data, "Failed sending DICT request");
return result;
goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
}
@ -310,13 +305,16 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done)
"QUIT\r\n", ppath);
if(result) {
failf(data, "Failed sending DICT request");
return result;
goto error;
}
Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1);
}
}
return CURLE_OK;
error:
free(eword);
free(path);
return result;
}
#endif /* CURL_DISABLE_DICT */