Skip to content

Commit

Permalink
s_user: sanitize username early
Browse files Browse the repository at this point in the history
This ensures we don't allow [ in usernames anywhere.  This also adds the
tilde early, which simplifies a lot of things, and fixes an issue with
username K-Lines on IsNoTilde users.
  • Loading branch information
dwfreed committed Jun 15, 2024
1 parent 0c59c5b commit a482889
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 89 deletions.
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
48 changes: 16 additions & 32 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,26 @@ 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];

notildeusername[o] = '\0';

myusername[i] = '\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);

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

/* Apply nick override */
Expand Down Expand Up @@ -481,9 +480,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 +496,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

0 comments on commit a482889

Please sign in to comment.