diff --git a/src/sbbs3/str.cpp b/src/sbbs3/str.cpp index fff7567b4736f1f8d45ab965cb2f897b731b4771..d7124dd3ab0165a893163002ba03baf0800a3fc8 100644 --- a/src/sbbs3/str.cpp +++ b/src/sbbs3/str.cpp @@ -843,86 +843,18 @@ bool sbbs_t::inputnstime(time_t *dt) return true; } -/*****************************************************************************/ -/* Checks a password for uniqueness and validity */ -/*****************************************************************************/ +/****************************************************************************/ +/* Check a password for validity and print reason upon failure */ +/****************************************************************************/ bool sbbs_t::chkpass(char *passwd, user_t* user, bool unique) { - char first[128], last[128], sysop[41], sysname[41], *p; - char alias[LEN_ALIAS + 1], name[LEN_NAME + 1], handle[LEN_HANDLE + 1]; - char pass[LEN_PASS + 1]; - - SAFECOPY(pass, passwd); - strupr(pass); - - int len = strlen(pass); - if (len < cfg.min_pwlen || len < MIN_PASS_LEN) { - bputs(text[PasswordTooShort]); - return false; - } - if (unique && strcmp(pass, user->pass) == 0) { - bputs(text[PasswordNotChanged]); - return false; - } - int i; - int run = 0; - for (i = 0; i < (len - 1); ++i) { - if (abs(toupper(pass[i]) - toupper(pass[i + 1])) > 1) { - if (++run >= cfg.min_pwlen / 2) - break; - } else - run = 0; - } - if (i >= (len - 1)) { - bputs(text[PasswordInvalid]); - return false; - } - SAFECOPY(name, user->name); - strupr(name); - SAFECOPY(alias, user->alias); - strupr(alias); - SAFECOPY(first, alias); - p = strchr(first, ' '); - if (p) { - *p = 0; - SAFECOPY(last, p + 1); - } - else - last[0] = 0; - SAFECOPY(handle, user->handle); - strupr(handle); - SAFECOPY(sysop, cfg.sys_op); - strupr(sysop); - SAFECOPY(sysname, cfg.sys_name); - strupr(sysname); - if ((unique && user->pass[0] - && (strstr(pass, user->pass) || strstr(user->pass, pass))) - || (name[0] - && (strstr(pass, name) || strstr(name, pass))) - || strstr(pass, alias) || strstr(alias, pass) - || strstr(pass, first) || strstr(first, pass) - || (last[0] - && (strstr(pass, last) || strstr(last, pass))) - || strstr(pass, handle) || strstr(handle, pass) - || (user->zipcode[0] - && (strstr(pass, user->zipcode) || strstr(user->zipcode, pass))) - || (sysname[0] - && (strstr(pass, sysname) || strstr(sysname, pass))) - || (sysop[0] - && (strstr(pass, sysop) || strstr(sysop, pass))) - || (cfg.sys_id[0] - && (strstr(pass, cfg.sys_id) || strstr(cfg.sys_id, pass))) - || (cfg.node_phone[0] && strstr(pass, cfg.node_phone)) - || (user->phone[0] && strstr(user->phone, pass)) - || !strncmp(pass, "QWER", 4) - || !strncmp(pass, "ASDF", 4) - || !strncmp(pass, "!@#$", 4) - ) - { - bputs(text[PasswordObvious]); + int reason = -1; + if (!check_pass(&cfg, passwd, user, unique, &reason)) { + if (reason >= 0) + bputs(text[reason]); return false; } - return !trashcan(pass, "password"); + return !trashcan(passwd, "password"); } /****************************************************************************/ diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index 662ac7634be3841b78836c47c5b2f982f961983b..9b2b0e095512f0909692698f21a43ddfc1be3c0b 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -4588,3 +4588,88 @@ enum parsed_vpath parse_vpath(scfg_t* cfg, const char* vpath, int* lib, int* dir return *filename == NULL ? PARSED_VPATH_DIR : PARSED_VPATH_FULL; } + +/****************************************************************************/ +/* Check a password for uniqueness and validity */ +/* Does *not* check the password.can file! */ +/****************************************************************************/ +bool check_pass(scfg_t* cfg, const char *pass, user_t* user, bool unique, int* reason) +{ + int reason_; + + if (reason == NULL) + reason = &reason_; + + int len = strlen(pass); + if (len < cfg->min_pwlen || len < MIN_PASS_LEN) { + *reason = PasswordTooShort; + return false; + } + if (unique) { + if (user == NULL) + return false; + if (stricmp(pass, user->pass) == 0) { + *reason = PasswordNotChanged; + return false; + } + } + + // Require a minimum sequence of unique (non-repeating/increment/decrementing) characters + int i; + int run = 0; + for (i = 0; i < (len - 1); ++i) { + if (abs(toupper(pass[i]) - toupper(pass[i + 1])) > 1) { + if (++run >= cfg->min_pwlen / 2) + break; + } else + run = 0; + } + if (i >= (len - 1)) { + *reason = PasswordInvalid; + return false; + } + + // Compare proposed password against user properties + if (user != NULL) { + char first[128], last[128], *p; + + SAFECOPY(first, user->alias); + p = strchr(first, ' '); + if (p) { + *p = 0; + SAFECOPY(last, p + 1); + } + else + last[0] = 0; + if ((unique && user->pass[0] + && (strcasestr(pass, user->pass) || strcasestr(user->pass, pass))) + || (user->name[0] + && (strcasestr(pass, user->name) || strcasestr(user->name, pass))) + || strcasestr(pass, user->alias) || strcasestr(user->alias, pass) + || strcasestr(pass, first) || strcasestr(first, pass) + || (last[0] + && (strcasestr(pass, last) || strcasestr(last, pass))) + || strcasestr(pass, user->handle) || strcasestr(user->handle, pass) + || (user->zipcode[0] + && (strcasestr(pass, user->zipcode) || strcasestr(user->zipcode, pass))) + || (user->phone[0] && strcasestr(user->phone, pass)) + ) { + *reason = PasswordObvious; + return false; + } + } + + // Compare proposed password against system properties + if ((cfg->sys_name[0] + && (strcasestr(pass, cfg->sys_name) || strcasestr(cfg->sys_name, pass))) + || (cfg->sys_op[0] + && (strcasestr(pass, cfg->sys_op) || strcasestr(cfg->sys_op, pass))) + || (cfg->sys_id[0] + && (strcasestr(pass, cfg->sys_id) || strcasestr(cfg->sys_id, pass))) + || (cfg->node_phone[0] && strcasestr(pass, cfg->node_phone)) + ) { + *reason = PasswordObvious; + return false; + } + return true; +} diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h index a04744540e50333375ceeed9a6ce69028850b3cb..6d07f7915bf3400c6506ffec862efc38e8eb9700 100644 --- a/src/sbbs3/userdat.h +++ b/src/sbbs3/userdat.h @@ -202,6 +202,7 @@ DLLEXPORT bool user_adjust_minutes(scfg_t*, user_t*, long amount); DLLEXPORT time_t gettimeleft(scfg_t*, user_t*, time_t starttime); +DLLEXPORT bool check_pass(scfg_t*, const char *passwd, user_t* user, bool unique, int* reason); DLLEXPORT bool check_name(scfg_t*, const char* name); DLLEXPORT bool check_realname(scfg_t*, const char* name); DLLEXPORT bool sysop_available(scfg_t*);