Commit 00c56b2a authored by Rob Swindell's avatar Rob Swindell

Use a more-liberal username matching algorithm

- Ignore all non-trailing non-alphanumeric characters when comparing a string against a user's name. Previously, spaces and dots and underscores were mostly-treated as equivalent and white-space was sometimes compressed for comparison purposes (if the user name contained both spaces and dots). This updated algo helps to insure that deliberate or accidental name collisions cannot be created but also aids usability (e.g. users can make some minor cosmetic adjustments to their user name and still be considered the "same user" for most comparison purposes).
- Terminate the comparison string at an '@' (ignore everything after). This resolves the FAQ of why users can't login with "username@domain" and aides some other username/address matching algorithms (e.g. in the mailserver). '@'s are illegal characters for usernames already.

Expose the new algorithm via new function matchusername().
Use the algorithm in matchuser() and lookup_user().

Unrelated: don't lower-case the 'localuser' part of email addresses in  usermailaddr() - cosmetic only.
parent 24021e05
......@@ -56,10 +56,8 @@ static const char* strIpFilterExemptConfigFile = "ipfilter_exempt.cfg";
uint matchuser(scfg_t* cfg, const char *name, BOOL sysop_alias)
{
int file,c;
char* p;
char dat[LEN_ALIAS+2];
char str[256];
char tmp[256];
ulong l,length;
FILE* stream;
......@@ -79,42 +77,7 @@ uint matchuser(scfg_t* cfg, const char *name, BOOL sysop_alias)
for(c=0;c<LEN_ALIAS;c++)
if(dat[c]==ETX) break;
dat[c]=0;
if(!stricmp(dat,name))
break;
/* convert dots to spaces */
strcpy(str,dat);
REPLACE_CHARS(str,'.',' ',p);
if(!stricmp(str,name))
break;
/* convert spaces to dots */
strcpy(str,dat);
REPLACE_CHARS(str,' ','.',p);
if(!stricmp(str,name))
break;
/* convert dots to underscores */
strcpy(str,dat);
REPLACE_CHARS(str,'.','_',p);
if(!stricmp(str,name))
break;
/* convert underscores to dots */
strcpy(str,dat);
REPLACE_CHARS(str,'_','.',p);
if(!stricmp(str,name))
break;
/* convert spaces to underscores */
strcpy(str,dat);
REPLACE_CHARS(str,' ','_',p);
if(!stricmp(str,name))
break;
/* convert underscores to spaces */
strcpy(str,dat);
REPLACE_CHARS(str,'_',' ',p);
if(!stricmp(str,name))
break;
/* strip spaces (from both) */
strip_space(dat,str);
strip_space(name,tmp);
if(!stricmp(str,tmp))
if(matchusername(cfg, dat, name))
break;
}
fclose(stream);
......@@ -123,6 +86,33 @@ uint matchuser(scfg_t* cfg, const char *name, BOOL sysop_alias)
return(0);
}
/****************************************************************************/
/* Return TRUE if the user 'name' (or alias) matches with 'comp' */
/* ... ignoring non-alpha-numeric chars in either string */
/* and terminating the comparison string at an '@' */
/****************************************************************************/
BOOL matchusername(scfg_t* cfg, const char* name, const char* comp)
{
(void)cfg; // in case we want this matching logic to be configurable in the future
const char* np = name;
const char* cp = comp;
while(*np != '\0' && *cp != '\0' && *cp != '@') {
if(!isalnum(*np)) {
np++;
continue;
}
if(!isalnum(*cp)) {
cp++;
continue;
}
if(toupper(*np) != toupper(*cp))
break;
np++, cp++;
}
return *np == '\0' && (*cp == '\0' || *cp == '@');
}
/****************************************************************************/
uint total_users(scfg_t* cfg)
{
......@@ -2625,7 +2615,6 @@ char* usermailaddr(scfg_t* cfg, char* addr, const char* name)
for(i=0;addr[i];i++)
if(addr[i]==' ' || addr[i]&0x80)
addr[i]='.';
strlwr(addr);
}
if(VALID_CFG(cfg)) {
strcat(addr,"@");
......@@ -3653,11 +3642,11 @@ int lookup_user(scfg_t* cfg, link_list_t* list, const char *inname)
close(userdat);
}
for(list_node_t* node = listFirstNode(list); node != NULL; node = node->next) {
if(stricmp(((user_t*)node->data)->alias, inname) == 0)
if(matchusername(cfg, ((user_t*)node->data)->alias, inname))
return ((user_t*)node->data)->number;
}
for(list_node_t* node = listFirstNode(list); node != NULL; node = node->next) {
if(stricmp(((user_t*)node->data)->name, inname) == 0)
if(matchusername(cfg, ((user_t*)node->data)->name, inname))
return ((user_t*)node->data)->number;
}
return 0;
......
......@@ -75,6 +75,7 @@ DLLEXPORT int fgetuserdat(scfg_t*, user_t*, int file);
DLLEXPORT int putuserdat(scfg_t*, user_t*); /* Put userdat struct into user file */
DLLEXPORT int newuserdat(scfg_t*, user_t*); /* Create new userdat in user file */
DLLEXPORT uint matchuser(scfg_t*, const char *str, BOOL sysop_alias); /* Checks for a username match */
DLLEXPORT BOOL matchusername(scfg_t*, const char* name, const char* compare);
DLLEXPORT char* alias(scfg_t*, const char* name, char* buf);
DLLEXPORT int putusername(scfg_t*, int number, char * name);
DLLEXPORT uint total_users(scfg_t*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment