Skip to content

Commit

Permalink
* src/ne_auth.c (get_credentials): Clean the realm before passing to the
Browse files Browse the repository at this point in the history
  credentials callback.

* test/auth.c (serve_unclean_realm, get_realm_cb, clean_realm): Add
  test case.
  • Loading branch information
notroj committed Sep 21, 2024
1 parent f1c1c18 commit 0007f22
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/ne_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,16 +402,19 @@ static int get_credentials(auth_session *sess, ne_buffer **errmsg, int attempt,
{
unsigned mask = chall->protocol->id | sess->spec->protomask;
int rv;
char *realm = ne_strclean(ne_strdup(sess->realm));

if (chall->handler->new_creds)
rv = chall->handler->new_creds(chall->handler->userdata,
attempt, mask, sess->realm,
attempt, mask, realm,
sess->username, pwbuf,
ABUFSIZE);
else
rv = chall->handler->old_creds(chall->handler->userdata, sess->realm,
rv = chall->handler->old_creds(chall->handler->userdata, realm,
chall->handler->attempt++, sess->username, pwbuf);

ne_free(realm);

if (rv == 0)
return 0;

Expand Down
7 changes: 5 additions & 2 deletions src/ne_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ NE_BEGIN_DECLS
* realm. The username and password must be copied into the buffers
* which are both of size NE_ABUFSIZ. The 'attempt' parameter is zero
* on the first call to the callback, and increases by one for each
* invocation of the callback during an attempt to authenticate.
* invocation of the callback during an attempt to authenticate. The
* 'realm' parameter is provided by the server, the string is cleaned
* of non-printable characters.
*
* The callback must return zero to indicate that authentication
* should be attempted with the username/password, or non-zero to
Expand Down Expand Up @@ -155,7 +157,8 @@ void ne_add_proxy_auth(ne_session *sess, unsigned protocol,
* (NE_AUTH_*) of the challenge, bitwise-ORed with NE_AUTH_PROXY when
* the auth challenge is made by an HTTP proxy.
*
* 'realm' is the realm name. The 'attempt' counter reflects the
* 'realm' is the realm name provided by the server, and is cleaned of
* non-printable characters. The 'attempt' counter reflects the
* number of attempts to provide credentials to the server
* (i.e. retried requests sent with a challenge response), NOT the
* number of times the callback is invoked, unlike the ne_auth_creds
Expand Down
49 changes: 49 additions & 0 deletions test/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,54 @@ static int star_scope(void)
return destroy_and_wait(sess);
}

/* Test for realm with non-readable characters. */
static int serve_unclean_realm(ne_socket *sock, void *userdata)
{
CALL(discard_request(sock));
send_response(sock, "WWW-Authenticate: Basic realm='Foo\tBar'", 401, 0);

CALL(discard_request(sock));
send_response(sock, NULL, 200, 0);

return 0;
}

static int get_realm_cb(void *userdata, const char *realm, int tries,
char *un, char *pw)
{
char **rp = userdata;

*rp = ne_strdup(realm);

ne_strnzcpy(un, "foo", NE_ABUFSIZ);
ne_strnzcpy(pw, "bar", NE_ABUFSIZ);

return 0;
}

/* Test for the scope of "*". */
static int clean_realm(void)
{
ne_session *sess;
char *realm = NULL;

CALL(make_session(&sess, serve_unclean_realm, NULL));

ne_set_server_auth(sess, get_realm_cb, &realm);

ONREQ(any_request(sess, "/realm-test"));

ONN("no realm header found?", realm == NULL);

ONV(strchr(realm, '\t') != NULL,
("realm header returned unclean: '%s'", realm));

ne_free(realm);

return destroy_and_wait(sess);
}


/* proxy auth, proxy AND origin */

ne_test tests[] = {
Expand All @@ -1703,5 +1751,6 @@ ne_test tests[] = {
T(forget),
T(basic_scope),
T(star_scope),
T(clean_realm),
T(NULL)
};

0 comments on commit 0007f22

Please sign in to comment.