Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sanitize username early, and early reject invalid ones #434

Merged
merged 2 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 35 additions & 57 deletions ircd/s_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ static int cmp_prop_ban(const void *, const void *);
FILE *conf_fbfile_in;
extern char yytext[];

static int verify_access(struct Client *client_p, const char *username);
static struct ConfItem *find_address_conf_by_client(struct Client *client_p, const char *username);
static int verify_access(struct Client *client_p, const char *notildeusername);
static struct ConfItem *find_address_conf_by_client(struct Client *client_p, const char *notildeusername);
static int attach_iline(struct Client *, struct ConfItem *);

void
Expand Down Expand Up @@ -178,11 +178,11 @@ free_conf(struct ConfItem *aconf)
* status as the flags passed.
*/
int
check_client(struct Client *client_p, struct Client *source_p, const char *username)
check_client(struct Client *client_p, struct Client *source_p, const char *notildeusername)
{
int i;

if((i = verify_access(source_p, username)))
if((i = verify_access(source_p, notildeusername)))
{
ilog(L_FUSER, "Access denied: %s[%s]",
source_p->name, source_p->sockhost);
Expand All @@ -200,57 +200,49 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
* see the IP, we still cannot send it.
*/
sendto_realops_snomask(SNO_FULL, L_NETWIDE,
"Too many local connections for %s[%s%s@%s] [%s]",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->host,
"Too many local connections for %s[%s@%s] [%s]",
source_p->name, source_p->username, source_p->host,
show_ip(NULL, source_p) && !IsIPSpoof(source_p) ? source_p->sockhost : "0");

ilog(L_FUSER, "Too many local connections from %s!%s%s@%s",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost);
ilog(L_FUSER, "Too many local connections from %s!%s@%s",
source_p->name, source_p->username, source_p->sockhost);

ServerStats.is_ref++;
exit_client(client_p, source_p, &me, "Too many host connections (local)");
break;

case TOO_MANY_GLOBAL:
sendto_realops_snomask(SNO_FULL, L_NETWIDE,
"Too many global connections for %s[%s%s@%s] [%s]",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->host,
"Too many global connections for %s[%s@%s] [%s]",
source_p->name, source_p->username, source_p->host,
show_ip(NULL, source_p) && !IsIPSpoof(source_p) ? source_p->sockhost : "0");
ilog(L_FUSER, "Too many global connections from %s!%s%s@%s",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost);
ilog(L_FUSER, "Too many global connections from %s!%s@%s",
source_p->name, source_p->username, source_p->sockhost);

ServerStats.is_ref++;
exit_client(client_p, source_p, &me, "Too many host connections (global)");
break;

case TOO_MANY_IDENT:
sendto_realops_snomask(SNO_FULL, L_NETWIDE,
"Too many user connections for %s[%s%s@%s] [%s]",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->host,
"Too many user connections for %s[%s@%s] [%s]",
source_p->name, source_p->username, source_p->host,
show_ip(NULL, source_p) && !IsIPSpoof(source_p) ? source_p->sockhost : "0");
ilog(L_FUSER, "Too many user connections from %s!%s%s@%s",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost);
ilog(L_FUSER, "Too many user connections from %s!%s@%s",
source_p->name, source_p->username, source_p->sockhost);

ServerStats.is_ref++;
exit_client(client_p, source_p, &me, "Too many user connections (global)");
break;

case I_LINE_FULL:
sendto_realops_snomask(SNO_FULL, L_NETWIDE,
"I-line is full for %s[%s%s@%s] [%s]",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->host,
"I-line is full for %s[%s@%s] [%s]",
source_p->name, source_p->username, source_p->host,
show_ip(NULL, source_p) && !IsIPSpoof(source_p) ? source_p->sockhost : "0");

ilog(L_FUSER, "Too many connections from %s!%s%s@%s.",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost);
ilog(L_FUSER, "Too many connections from %s!%s@%s.",
source_p->name, source_p->username, source_p->sockhost);

ServerStats.is_ref++;
exit_client(client_p, source_p, &me,
Expand All @@ -272,16 +264,14 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
#endif
sendto_realops_snomask(SNO_UNAUTH, L_NETWIDE,
"Unauthorised client connection from "
"%s!%s%s@%s [%s] on [%s/%u].",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->host,
"%s!%s@%s [%s] on [%s/%u].",
source_p->name, source_p->username, source_p->host,
source_p->sockhost,
source_p->localClient->listener->name, port);

ilog(L_FUSER,
"Unauthorised client connection from %s!%s%s@%s on [%s/%u].",
source_p->name, IsGotId(source_p) ? "" : "~",
source_p->username, source_p->sockhost,
"Unauthorised client connection from %s!%s@%s on [%s/%u].",
source_p->name, source_p->username, source_p->sockhost,
source_p->localClient->listener->name, port);
add_reject(client_p, NULL, NULL, NULL, "You are not authorised to use this server.");
exit_client(client_p, source_p, &me, "You are not authorised to use this server.");
Expand All @@ -303,16 +293,16 @@ check_client(struct Client *client_p, struct Client *source_p, const char *usern
* verify_access
*
* inputs - pointer to client to verify
* - pointer to proposed username
* - pointer to proposed notildeusername
* output - 0 if success -'ve if not
* side effect - find the first (best) I line to attach.
*/
static int
verify_access(struct Client *client_p, const char *username)
verify_access(struct Client *client_p, const char *notildeusername)
{
struct ConfItem *aconf;

aconf = find_address_conf_by_client(client_p, username);
aconf = find_address_conf_by_client(client_p, notildeusername);
if(aconf == NULL)
return NOT_AUTHORISED;

Expand Down Expand Up @@ -382,29 +372,17 @@ verify_access(struct Client *client_p, const char *username)
* find_address_conf_by_client
*/
static struct ConfItem *
find_address_conf_by_client(struct Client *client_p, const char *username)
find_address_conf_by_client(struct Client *client_p, const char *notildeusername)
{
struct ConfItem *aconf;
char non_ident[USERLEN + 1];

if(IsGotId(client_p))
{
aconf = find_address_conf(client_p->host, client_p->sockhost,
client_p->username, client_p->username,
(struct sockaddr *) &client_p->localClient->ip,
GET_SS_FAMILY(&client_p->localClient->ip),
client_p->localClient->auth_user);
}
else
{
rb_strlcpy(non_ident, "~", sizeof(non_ident));
rb_strlcat(non_ident, username, sizeof(non_ident));
aconf = find_address_conf(client_p->host, client_p->sockhost,
non_ident, client_p->username,
(struct sockaddr *) &client_p->localClient->ip,
GET_SS_FAMILY(&client_p->localClient->ip),
client_p->localClient->auth_user);
}
aconf = find_address_conf(client_p->host, client_p->sockhost,
client_p->username,
IsGotId(client_p) ? client_p->username : notildeusername,
(struct sockaddr *) &client_p->localClient->ip,
GET_SS_FAMILY(&client_p->localClient->ip),
client_p->localClient->auth_user);

return aconf;
}

Expand Down
100 changes: 42 additions & 58 deletions ircd/s_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ register_local_user(struct Client *client_p, struct Client *source_p)
struct ConfItem *aconf, *xconf;
char tmpstr2[BUFSIZE];
char ipaddr[HOSTIPLEN];
char myusername[USERLEN+1];
char notildeusername[USERLEN + 1];
int status, umodes;

s_assert(NULL != source_p);
Expand Down Expand Up @@ -390,27 +390,52 @@ register_local_user(struct Client *client_p, struct Client *source_p)
* rather than initial connection. */
source_p->localClient->firsttime = client_p->localClient->last = rb_current_time();

/* XXX - fixme. we shouldnt have to build a users buffer twice.. */
if(!IsGotId(source_p) && (strchr(source_p->username, '[') != NULL))
if (!IsGotId(source_p))
{
const char *p;
int i = 0;
const char *haystack;
int o = 0;

p = source_p->username;
haystack = source_p->username;

while(*p && i < USERLEN)
{
if(*p != '[')
myusername[i++] = *p;
p++;
}
for (int i = 0; haystack[i] != '\0'; i++)
if (haystack[i] != '[')
notildeusername[o++] = haystack[i];

myusername[i] = '\0';
notildeusername[o] = '\0';

rb_strlcpy(source_p->username, "~", sizeof(source_p->username));
rb_strlcat(source_p->username, notildeusername, sizeof(source_p->username));
}
else
rb_strlcpy(myusername, source_p->username, sizeof myusername);
rb_strlcpy(notildeusername, source_p->username, sizeof notildeusername);

/* valid user name check */

if(!valid_username(source_p->username))
{
sendto_realops_snomask(SNO_REJ, L_NETWIDE,
"Invalid username: %s (%s@%s)",
source_p->name, source_p->username, source_p->host);

const char *illegal_name_long_client_message = ConfigFileEntry.illegal_name_long_client_message;
const char *illegal_name_short_client_message = ConfigFileEntry.illegal_name_short_client_message;

if((status = check_client(client_p, source_p, myusername)) < 0)
if (illegal_name_long_client_message == NULL)
illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains "
"only alphanumeric characters.";
if (illegal_name_short_client_message == NULL)
illegal_name_short_client_message = "Invalid username";

ServerStats.is_ref++;
sendto_one_notice(source_p, ":*** %s", illegal_name_long_client_message);
sprintf(tmpstr2, "%s [%s]", illegal_name_short_client_message, source_p->username);
exit_client(client_p, source_p, &me, tmpstr2);
return (CLIENT_EXITED);
}

/* end of valid user name check */

if((status = check_client(client_p, source_p, notildeusername)) < 0)
return (CLIENT_EXITED);

/* Apply nick override */
Expand Down Expand Up @@ -481,9 +506,6 @@ register_local_user(struct Client *client_p, struct Client *source_p)

if(!IsGotId(source_p))
{
const char *p;
int i = 0;

if(IsNeedIdentd(aconf))
{

Expand All @@ -500,21 +522,9 @@ register_local_user(struct Client *client_p, struct Client *source_p)
}

/* dont replace username if its supposed to be spoofed --fl */
if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->info.name, '@'))
if (IsNoTilde(aconf) && (!IsConfDoSpoofIp(aconf) || !strchr(aconf->info.name, '@')))
{
p = myusername;

if(!IsNoTilde(aconf))
source_p->username[i++] = '~';

while (*p && i < USERLEN)
{
if(*p != '[')
source_p->username[i++] = *p;
p++;
}

source_p->username[i] = '\0';
rb_strlcpy(source_p->username, notildeusername, sizeof(source_p->username));
}
}

Expand Down Expand Up @@ -609,32 +619,6 @@ register_local_user(struct Client *client_p, struct Client *source_p)
if(authd_check(client_p, source_p))
return CLIENT_EXITED;

/* valid user name check */

if(!valid_username(source_p->username))
{
sendto_realops_snomask(SNO_REJ, L_NETWIDE,
"Invalid username: %s (%s@%s)",
source_p->name, source_p->username, source_p->host);

const char *illegal_name_long_client_message = ConfigFileEntry.illegal_name_long_client_message;
const char *illegal_name_short_client_message = ConfigFileEntry.illegal_name_short_client_message;

if (illegal_name_long_client_message == NULL)
illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains "
"only alphanumeric characters.";
if (illegal_name_short_client_message == NULL)
illegal_name_short_client_message = "Invalid username";

ServerStats.is_ref++;
sendto_one_notice(source_p, ":*** %s", illegal_name_long_client_message);
sprintf(tmpstr2, "%s [%s]", illegal_name_short_client_message, source_p->username);
exit_client(client_p, source_p, &me, tmpstr2);
return (CLIENT_EXITED);
}

/* end of valid user name check */

/* Store original hostname -- jilles */
rb_strlcpy(source_p->orighost, source_p->host, HOSTLEN + 1);

Expand Down
Loading