Newer
Older
/* Synchronet ARS checking routine */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
bool sbbs_t::ar_exp(const uchar **ptrptr, user_t* user, client_t* client)
bool result, _not, _or, equal;
uint i, n, artype, age;
uint64_t l;
struct tm tm;
const char* p;
for (; (**ptrptr); (*ptrptr)++) {
if ((**ptrptr) == AR_ENDNEST)
_not = _or = equal = false;
if ((**ptrptr) == AR_OR) {
_or = true;
(*ptrptr)++;
if ((**ptrptr) == AR_NOT) {
_not = true;
(*ptrptr)++;
if ((**ptrptr) == AR_EQUAL) {
equal = true;
(*ptrptr)++;
if ((result && _or) || (!result && !_or))
if ((**ptrptr) == AR_BEGNEST) {
if (ar_exp(ptrptr, user, client))
result = !_not;
result = _not;
while ((**ptrptr) != AR_ENDNEST && (**ptrptr)) /* in case of early exit */
artype = (**ptrptr);
if (ar_type(artype) != AR_BOOL)
(*ptrptr)++;
n = (**ptrptr);
i = (*(short *)*ptrptr);
switch (artype) {
if ((equal && user->level != n) || (!equal && user->level < n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessLevel];
noaccess_val = n;
age = getage(&cfg, user->birth);
if ((equal && age != n) || (!equal && age < n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessAge];
noaccess_val = n;
if ((equal && cur_rate != i) || (!equal && cur_rate < i))
result = _not;
if (!result) {
noaccess_str = text[NoAccessBPS];
noaccess_val = i;
if (!term_supports(ANSI))
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = ANSI;
if ((term_supports() & CHARSET_FLAGS) != CHARSET_PETSCII)
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = PETSCII;
if ((term_supports() & CHARSET_FLAGS) != CHARSET_ASCII)
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = NO_EXASCII;
}
break;
case AR_UTF8:
if ((term_supports() & CHARSET_FLAGS) != CHARSET_UTF8)
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = UTF8;
}
break;
case AR_CP437:
if ((term_supports() & CHARSET_FLAGS) != CHARSET_CP437)
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = 0;
if (!term_supports(RIP))
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = RIP;
result = _not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
break;
case AR_OS2:
#ifndef __OS2__
case AR_DOS: /* DOS program support */
result = _not;
if (startup->options & BBS_OPT_NO_DOS)
break;
if (startup->usedosemu)
result = !_not;
#endif
break;
case AR_WIN32:
#ifndef _WIN32
#endif
break;
case AR_UNIX:
#ifndef __unix__
#endif
break;
case AR_LINUX:
#ifndef __linux__
if (user->misc & (DELETED | INACTIVE))
result = _not;
break;
case AR_INACTIVE:
if (!(user->misc & INACTIVE))
result = _not;
break;
case AR_DELETED:
if (!(user->misc & DELETED))
result = _not;
if (!(user->misc & EXPERT))
result = _not;
if (user->level < SYSOP_LEVEL && !(sys_status & SS_TMPSYSOP))
result = _not;
if (!(user->rest & FLAG('G')))
result = _not;
break;
case AR_QNODE:
if (!(user->rest & FLAG('Q')))
result = _not;
if (thisnode.status != NODE_QUIET)
result = _not;
if (online != ON_LOCAL)
result = _not;
now = time(NULL);
localtime_r(&now, &tm);
if ((equal && tm.tm_wday != (int)n)
|| (!equal && tm.tm_wday < (int)n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessDay];
noaccess_val = n;
if ((equal && user_available_credits(user) != l)
|| (!equal && user_available_credits(user) < l))
result = _not;
if (!result) {
noaccess_str = text[NoAccessCredit];
noaccess_val = (long)l;
if ((equal && cfg.node_num != n) || (!equal && cfg.node_num < n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessNode];
noaccess_val = n;
if ((equal && user->number != i) || (!equal && user->number < i))
result = _not;
if (!result) {
noaccess_str = text[NoAccessUser];
noaccess_val = i;
case AR_USERNAME:
if (!matchusername(&cfg, user->alias, (char*)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
(*ptrptr)++;
if (!result)
noaccess_str = text[NoAccessUser];
if ((equal
&& (cursubnum >= cfg.total_subs
|| cfg.sub[cursubnum]->grp != i))
|| (!equal && cursubnum < cfg.total_subs
&& cfg.sub[cursubnum]->grp < i))
result = _not;
else
result = !_not;
if (!result) {
noaccess_str = text[NoAccessGroup];
noaccess_val = i + 1;
if ((equal && cursubnum != (int)i) || (!equal && cursubnum < (int)i))
result = _not;
if (!result) {
noaccess_str = text[NoAccessSub];
noaccess_val = i + 1;
if (cursubnum >= cfg.total_subs
|| !findstr_in_string(cfg.sub[cursubnum]->code, (char*)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
if (!result)
noaccess_str = text[NoAccessSub];
if ((equal
&& (curdirnum >= cfg.total_dirs
|| cfg.dir[curdirnum]->lib != i))
|| (!equal && curdirnum < cfg.total_dirs
&& cfg.dir[curdirnum]->lib < i))
result = _not;
else
result = !_not;
if (!result) {
noaccess_str = text[NoAccessLib];
noaccess_val = i + 1;
if ((equal && curdirnum != (int)i) || (!equal && curdirnum < (int)i))
result = _not;
if (!result) {
noaccess_str = text[NoAccessDir];
noaccess_val = i + 1;
if (curdirnum >= cfg.total_dirs
|| !findstr_in_string(cfg.dir[curdirnum]->code, (char *)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
if (!result)
noaccess_str = text[NoAccessSub];
now = time(NULL);
if (!user->expire || now + ((long)i * 24L * 60L * 60L) > user->expire)
result = _not;
if (!result) {
noaccess_str = text[NoAccessExpire];
noaccess_val = i;
n = sbbs_random(i + 1);
if ((equal && n != i) || (!equal && n < i))
result = _not;
(*ptrptr)++;
break;
case AR_LASTON:
now = time(NULL);
if ((now - user->laston) / (24L * 60L * 60L) < (long)i)
result = _not;
(*ptrptr)++;
break;
case AR_LOGONS:
if ((equal && user->logons != i) || (!equal && user->logons < i))
result = _not;
(*ptrptr)++;
break;
case AR_MAIN_CMDS:
if ((equal && main_cmds != i) || (!equal && main_cmds < i))
result = _not;
(*ptrptr)++;
break;
case AR_FILE_CMDS:
if ((equal && xfer_cmds != i) || (!equal && xfer_cmds < i))
result = _not;
(*ptrptr)++;
break;
case AR_TLEFT:
if (timeleft / 60 < (ulong)n)
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessTimeLeft];
noaccess_val = n;
if ((time(NULL) - logontime) / 60 < (long)n)
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessTimeUsed];
noaccess_val = n;
now = time(NULL);
localtime_r(&now, &tm);
if ((tm.tm_hour * 60) + tm.tm_min < (int)i)
result = _not;
if (!result) {
noaccess_str = text[NoAccessTime];
noaccess_val = i;
case AR_PCR: /* post/call ratio (by percentage) */
if (user->logons > user->posts
&& (!user->posts || (100 / ((float)user->logons / user->posts)) < (long)n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessPCR];
noaccess_val = n;
case AR_UDR: /* up/download byte ratio (by percentage) */
l = user->dlb;
if (user->dlb > user->ulb
&& (!user->ulb || (100 / ((float)l / user->ulb)) < n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessUDR];
noaccess_val = n;
case AR_UDFR: /* up/download file ratio (in percentage) */
i = user->dls;
if (user->dls > user->uls
&& (!user->uls || (100 / ((float)i / user->uls)) < n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessUDFR];
noaccess_val = n;
if ((equal && user->uls != i) || (!equal && user->uls < i))
result = _not;
case AR_ULK:
if ((equal && (user->ulb / 1024) != i) || (!equal && (user->ulb / 1024) < i))
result = _not;
else
(*ptrptr)++;
break;
case AR_ULM:
if ((equal && (user->ulb / (1024 * 1024)) != i) || (!equal && (user->ulb / (1024 * 1024)) < i))
result = _not;
if ((equal && user->dls != i) || (!equal && user->dls < i))
result = _not;
case AR_DLK:
if ((equal && user->dlb / 1024 != i) || (!equal && user->dlb / 1024 < i))
result = _not;
else
(*ptrptr)++;
break;
case AR_DLM:
if ((equal && user->dlb / (1024 * 1024) != i) || (!equal && user->dlb / (1024 * 1024) < i))
result = _not;
if ((!equal && !(user->flags1 & FLAG(n)))
|| (equal && user->flags1 != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessFlag1];
noaccess_val = n;
if ((!equal && !(user->flags2 & FLAG(n)))
|| (equal && user->flags2 != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessFlag2];
noaccess_val = n;
if ((!equal && !(user->flags3 & FLAG(n)))
|| (equal && user->flags3 != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessFlag3];
noaccess_val = n;
if ((!equal && !(user->flags4 & FLAG(n)))
|| (equal && user->flags4 != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessFlag4];
noaccess_val = n;
if ((!equal && !(user->rest & FLAG(n)))
|| (equal && user->rest != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessRest];
noaccess_val = n;
if ((!equal && !(user->exempt & FLAG(n)))
|| (equal && user->exempt != FLAG(n)))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessExempt];
noaccess_val = n;
if (user->sex != n)
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessSex];
noaccess_val = n;
case AR_SHELL:
if (user->shell >= cfg.total_shells
|| !findstr_in_string(cfg.shell[user->shell]->code, (char*)*ptrptr))
result = _not;
else
result = !_not;
while (*(*ptrptr))
(*ptrptr)++;
break;
case AR_PROT:
if (client != NULL)
p = client->protocol;
if (!findstr_in_string(p, (char*)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
if (client != NULL)
p = client->host;
p = user->comp;
if (!findstr_in_string(p, (char*)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
if (client != NULL)
p = client->addr;
p = user->ipaddr;
if (!findstr_in_string(p, (char*)*ptrptr))
result = _not;
else
result = !_not;
while (*(*ptrptr))
(*ptrptr)++;
break;
if (!findstr_in_string(terminal, (char*)*ptrptr))
result = _not;
result = !_not;
while (*(*ptrptr))
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = 0;
if ((equal && cols != (long)n) || (!equal && cols < (long)n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = n;
if ((equal && rows != (long)n) || (!equal && rows < (long)n))
result = _not;
result = !_not;
if (!result) {
noaccess_str = text[NoAccessTerminal];
noaccess_val = n;
}
}
bool sbbs_t::chk_ar(const uchar *ar, user_t* user, client_t* client)
const uchar *p;
return ar_exp(&p, user, client);

Rob Swindell
committed
/****************************************************************************/
/* Does the Access Requirement String (ARS) parse and check */
/****************************************************************************/
bool sbbs_t::chk_ars(const char *ars, user_t* user, client_t* client)
{
uchar ar_buf[LEN_ARSTR + 1];
return chk_ar(arstr(NULL, ars, &cfg, ar_buf), user, client);
}
/****************************************************************************/
/* This function fills the usrsub, usrsubs, usrgrps, curgrp, and cursub */
/* variables based on the security clearance of the current user (useron) */
/****************************************************************************/
void sbbs_t::getusrsubs()
{
for (j = 0, i = 0; i < cfg.total_grps; i++) {
if (!chk_ar(cfg.grp[i]->ar, &useron, &client))
for (k = 0, l = 0; l < cfg.total_subs; l++) {
if (cfg.sub[l]->grp != i)
continue;
if (!chk_ar(cfg.sub[l]->ar, &useron, &client))

rswindell
committed
}
usrsubs[j] = k;
if (!k) /* No subs accessible in group */

rswindell
committed
}
usrgrps = j;
if (usrgrps == 0)

rswindell
committed
return;
while ((curgrp >= usrgrps || !usrsubs[curgrp]) && curgrp) curgrp--;
while (cursub[curgrp] >= usrsubs[curgrp] && cursub[curgrp]) cursub[curgrp]--;
}
/****************************************************************************/
/* This function fills the usrdir, usrdirs, usrlibs, curlib, and curdir */
/* variables based on the security clearance of the current user (useron) */
/****************************************************************************/
void sbbs_t::getusrdirs()
{
if (useron.rest & FLAG('T')) {
usrlibs = 0;
return;

rswindell
committed
}
for (j = 0, i = 0; i < cfg.total_libs; i++) {
if (!chk_ar(cfg.lib[i]->ar, &useron, &client))
for (k = 0, l = 0; l < cfg.total_dirs; l++) {
if (cfg.dir[l]->lib != i)
continue;
if (!chk_ar(cfg.dir[l]->ar, &useron, &client))
usrdirs[j] = k;
if (!k) /* No dirs accessible in lib */

rswindell
committed
}
usrlibs = j;
if (usrlibs == 0)

rswindell
committed
return;
while ((curlib >= usrlibs || !usrdirs[curlib]) && curlib) curlib--;
while (curdir[curlib] >= usrdirs[curlib] && curdir[curlib]) curdir[curlib]--;

Rob Swindell
committed
int sbbs_t::getusrgrp(int subnum)
{
if (!subnum_is_valid(subnum))
for (ugrp = 0; ugrp < usrgrps; ugrp++)
if (usrgrp[ugrp] == cfg.sub[subnum]->grp)
break;
}

Rob Swindell
committed
int sbbs_t::getusrsub(int subnum)
{
int usub;
int ugrp;
ugrp = getusrgrp(subnum);
for (usub = 0; usub < usrsubs[ugrp]; usub++)
if (usrsub[ugrp][usub] == subnum)
break;
}

Rob Swindell
committed
int sbbs_t::getusrlib(int dirnum)
if (!dirnum_is_valid(dirnum))
for (ulib = 0; ulib < usrlibs; ulib++)
if (usrlib[ulib] == cfg.dir[dirnum]->lib)

Rob Swindell
committed
int sbbs_t::getusrdir(int dirnum)
int udir;
int ulib;
for (udir = 0; udir < usrdirs[ulib]; udir++)
if (usrdir[ulib][udir] == dirnum)

Rob Swindell
committed
int sbbs_t::dir_op(int dirnum)
return user_is_dirop(&cfg, dirnum, &useron, &client);