Skip to content

Commit

Permalink
[ADDED] Support %-encoded username/password in server URLs (#765)
Browse files Browse the repository at this point in the history
* [FIXED] Support %-encoding in username, password when parsing connect URLs

* better test

* [TEST ONLY] Fixed Test_JetStreamSubscribeIdleHeartbeat

* Nit: removed an irrelevant format change

* PR feedback: typo

* PR feedback: include %00 in the test
  • Loading branch information
levb committed Jun 13, 2024
1 parent d98acf0 commit 8505264
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
41 changes: 39 additions & 2 deletions src/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "util.h"

#include <string.h>
#include <ctype.h>

#include "mem.h"

Expand Down Expand Up @@ -46,6 +47,42 @@ _parsePort(int *port, const char *sport)
return s;
}

static natsStatus _decodeAndDup(char **decoded, const char *encoded)
{
size_t len = strlen(encoded);
const char *p = encoded;
const char *e = encoded + len;
char *d;

*decoded = NATS_MALLOC(len + 1);
if (*decoded == NULL)
{
return nats_setDefaultError(NATS_NO_MEMORY);
}
d = *decoded;
for (; p < e; p++)
{
if (*p != '%')
{
*d++ = *p;
continue;
}

if (e - p < 3 || (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2))))
{
NATS_FREE(*decoded);
*decoded = NULL;
return nats_setError(NATS_ERR, "invalid percent encoding in URL: %s", encoded);
}

char buf[3] = {p[1], p[2], '\0'};
*d++ = (char)strtol(buf, NULL, 16);
p += 2;
}
*d = '\0';
return NATS_OK;
}

natsStatus
natsUrl_Create(natsUrl **newUrl, const char *urlStr)
{
Expand Down Expand Up @@ -166,9 +203,9 @@ natsUrl_Create(natsUrl **newUrl, const char *urlStr)
DUP_STRING(s, url->host, host);

if (user != NULL)
IF_OK_DUP_STRING(s, url->username, user);
IFOK(s, _decodeAndDup(&url->username, user));
if (pwd != NULL)
IF_OK_DUP_STRING(s, url->password, pwd);
IFOK(s, _decodeAndDup(&url->password, pwd));

if ((s == NATS_OK) && nats_asprintf(&url->fullUrl, "%s://%s%s%s%s%s:%d%s%s",
scheme, userval, usep, pwdval, hsep, host, url->port, pathsep, pathval) < 0)
Expand Down
30 changes: 30 additions & 0 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,36 @@ test_natsUrl(void)
natsUrl_Destroy(u);
u = NULL;

test("'tcp://%4C%65v%00ignored:p%77d%00ignoredalso@localhost':");
s = natsUrl_Create(&u, "tcp://%4C%65v%00ignored:p%77d%00ignoredalso@localhost");
testCond((s == NATS_OK)
&& (u != NULL)
&& (u->host != NULL)
&& (strcmp(u->host, "localhost") == 0)
&& (u->username != NULL)
&& (strcmp(u->username, "Lev") == 0)
&& (u->password != NULL)
&& (strcmp(u->password, "pwd") == 0)
&& (u->port == 4222));
natsUrl_Destroy(u);
u = NULL;

test("'tcp://%4C%65v:p%77d@localhost':");
s = natsUrl_Create(&u, "tcp://%4C%65v:p%77d@localhost");
testCond((s == NATS_OK) && (u != NULL) && (u->host != NULL) && (strcmp(u->host, "localhost") == 0) && (u->username != NULL) && (strcmp(u->username, "Lev") == 0) && (u->password != NULL) && (strcmp(u->password, "pwd") == 0) && (u->port == 4222));
natsUrl_Destroy(u);
u = NULL;

test("'tcp://%4c%65v:p%@localhost':");
s = natsUrl_Create(&u, "tcp://%4c%65v:p%@localhost");
testCond((s == NATS_ERR) && (u == NULL) && (strstr(nats_GetLastError(NULL), "invalid percent encoding in URL: p%") != NULL));
nats_clearLastError();

test("'tcp://%4H%65v:p%@localhost':");
s = natsUrl_Create(&u, "tcp://%4H%65v:p%@localhost");
testCond((s == NATS_ERR) && (u == NULL) && (strstr(nats_GetLastError(NULL), "invalid percent encoding in URL: %4H%65v") != NULL));
nats_clearLastError();

test("'tcp://localhost: 4222':");
s = natsUrl_Create(&u, "tcp://localhost: 4222");
testCond((s == NATS_INVALID_ARG)
Expand Down

0 comments on commit 8505264

Please sign in to comment.