/*
* user.cc
*
* Part of ezbounce
*
* (C) 2001-2002 Murat Deligonul
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
*/
#include <stdlib.h>
#include "user.h"
#include "logfile.h"
#include "linkedlist.h"
#include "debug.h"
userdef::userdef(const char * user)
{
name = my_strdup(user);
rulesets = new list<ruleset>;
conns = new list<conn>;
vhosts = 0;
obsolete = 0;
DEBUG("userdef::userdef(): [%p] (%s)\n", this, name);
}
userdef::~userdef()
{
DEBUG("userdef::~userdef(): [%p] (%s)\n", this, name);
destroy_list(rulesets, 0);
destroy_list(this->vhosts, 1); /* do delete[] */
delete rulesets;
delete conns;
delete[] name;
delete vhosts;
}
/*
* "Register" a user. return:
* 0 -- bad password
* -1 -- not allowed
* 1 -- added */
int userdef::add(conn * c, list<ruleset> * plist, const char * password,
const char * hostname, unsigned short port)
{
if (strcasecmp(password, cfg.get(OPT_PASSWORD, NULL)))
return 0;
if (!ruleset::find_matching(hostname, port, rulesets, plist))
return -1;
conns->add(c);
return 1;
}
userdef * userdef::find(list<userdef> * ls, const char * str)
{
list_iterator<userdef> i(ls);
while (i.has_next())
{
userdef * u = i.next();
if (!u->obsolete && !strcasecmp(u->name, str))
return u;
}
return 0;
}
int userdef::remove(conn * c)
{
DEBUG("userdef::remove for %s (%p)\n", name, c);
conns->remove(c);
return 1;
}
/*
* The efficiency of this function is atrocious.
* But it works :-)
*/
list<userdef> * userdef::sync_lists(list<userdef> * oldlist, list<userdef> * newlist)
{
list<userdef> * list3 = new list<userdef>;
/*
* For each user in the old list:
* - Check if he has a match in the new list
* - if he does, syncronize options
* add original to list3, remove new one from new list, and delete
* - if he doesn't,
* he is obsolete.. if has no users, delete and remove from list
* if he he has users, mark obsolete and add to list3
*
* Add anyone left in newlist to list3
*
*/
list_iterator<userdef> i(oldlist);
while (i.has_next())
{
userdef * u = i.next();
userdef * u2 = userdef::find(newlist, u->name);
/* Found a match */
if (u2)
{
/* Copy vhosts */
destroy_list(u->vhosts, 1);
u->vhosts = u2->vhosts;
u2->vhosts = 0;
u->obsolete = 0;
/* Copy options */
u->cfg.copy(&u2->cfg);
/* the rulesets :-P */
if (!u->conns->size())
{
DEBUG(" USER %s: no conns found, copying new rulesets to old\n", u->name);
destroy_list(u->rulesets, 0);
u->rulesets = u2->rulesets;
u2->rulesets = 0;
} else {
/* Since we have clients ... */
DEBUG(" USER %s: This user has clients, syncing ruleset lists\n", u->name);
u->rulesets = ruleset::sync_lists(u->rulesets, u2->rulesets);
u2->rulesets = 0; /* deleted by above call */
/* Update clients' config */
list_iterator<conn> i(u->conns);
while (i.has_next())
{
conn * c = i.next();
if (c->get_config())
c->get_config()->copy_config_only(&u2->cfg);
}
}
delete u2;
newlist->remove(u2);
list3->add(u);
DEBUG(" \\---->Deleted [new] %p, added [original] %p to list3\n", u2, u);
}
else {
/* No match -- whats the usage count on this ? */
if (!u->conns->size())
{
DEBUG(" USER %s: NO MATCH deleting this user\n", u->name);
/* ok cool, you don't go anywhere */
delete u;
continue;
}
else {
/* We have users .. mark this one as obsolete */
u->obsolete = 1;
DEBUG(" USER %s: marking as obsolete\n", u->name);
list3->add(u);
}
}
}
/* Add any left over in newlist to list3 */
i.attach(newlist);
while (i.has_next())
{
userdef * u = i.next();
DEBUG("--Adding new user %s (%p)\n", u->name, u);
list3->add(u);
}
delete oldlist; /* don't delete each of the members, because */
delete newlist; /* they are referenced in list3 */
return list3;
}
/*
* Saving user preferences -- syntax is:
*
* prefs <username> <option - 8>
*
* option 1: flags
* option 2: log options
* option 3: default vhost
* option 7: fake ident
* option 8: auto detach password
* option 9: autoserver
*
* don't know what else to put in there, perhaps to make it extensible for the
* future..
*/
int user_options::load(const char * s)
{
char s_dummy[256];
char s_autoserver[256], s_autopass[128], s_fake_ident[128];
int dummy;
int r ;
r = sscanf(s, "%s %s %d %d %u %d %d %d %s %s %s\n",
s_dummy,
s_dummy,
&prefs,
&log_options,
&iface.s_addr,
&dummy,
&dummy,
&dummy,
s_fake_ident,
s_autopass,
s_autoserver);
if (r < 11)
DEBUG("User file corrupted??\n");;
delete[] autoserver;
delete[] autopass;
delete[] fake_ident;
autoserver = autopass = fake_ident = 0;
if (strcmp(s_autoserver, "[none]") != 0 && *s_autoserver)
autoserver = my_strdup(s_autoserver);
if (strcmp(s_autopass, "[none]") != 0 && *s_autopass)
autopass = my_strdup(s_autopass);
if (strcmp(s_fake_ident, "[none]") != 0 && *s_fake_ident)
fake_ident = my_strdup(s_fake_ident);
DEBUG(" ---> load() for %s ...\n", s_dummy);
DEBUG(" prefs: %d\n", prefs);
DEBUG(" log options: %d\n" , log_options);
DEBUG(" autopass: %s\n" , autopass);
DEBUG(" autoserver: %s\n" , autoserver);
DEBUG(" fake-ident: %s\n", fake_ident);
return 1;
}
int user_options::save(const char * name, int f)
{
fdprintf(f, "prefs %s %d %d %u %d %d %d %s %s %s\n",
name,
prefs,
log_options,
iface.s_addr,
0, /* reserved */
0, /* reserved */
0, /* reserved */
fake_ident ? fake_ident : "[none]",
autopass ? autopass : "[none]",
autoserver ? autoserver : "[none]");
DEBUG(" ---> save() for %s ...\n", name);
DEBUG(" prefs: %d\n", prefs);
DEBUG(" log options: %d\n" , log_options);
DEBUG(" autopass: %s\n" , autopass);
DEBUG(" autoserver: %s\n" , autoserver);
DEBUG(" fake-ident: %s\n" , fake_ident);
return 1;
}
/* copy constructor type of thing */
user_options::user_options(user_options * u2)
{
autoserver = autopass = password = fake_ident = 0;
copy(u2);
}
/* default constructor
* default user settings reside here */
user_options::user_options()
{
autoserver = autopass = password = fake_ident = 0;
max_logsize = 0;
max_idle = 0;
prefs = 0;
log_options = logfile::LOG_ALL | logfile::LOG_SEPERATE;
flags = OPT_ENABLE_DETACH_COMMAND | OPT_LOG_OPTIONS;
memset(&iface, 0, sizeof(iface));
}
int user_options::copy(user_options * u2)
{
DEBUG("user_options::copy()\n");
delete[] this->password;
delete[] this->autoserver;
delete[] this->fake_ident;
delete[] this->autopass;
this->password = my_strdup(u2->password);
this->autoserver = my_strdup(u2->autoserver);
this->fake_ident = my_strdup(u2->fake_ident);
this->autopass = my_strdup(u2->autopass);
max_logsize = u2->max_logsize;
max_idle = u2->max_idle;
log_options = u2->log_options;
flags = u2->flags;
prefs = u2->prefs;
iface = u2->iface;
return 1;
}
/* set integer option */
int user_options::set(int field, int value)
{
switch (field)
{
case OPT_MAX_LOGFILE_SIZE:
max_logsize = value;
break;
case OPT_MAX_IDLE_TIME:
max_idle = value;
break;
case OPT_LOG_OPTIONS:
case OPT_DEFAULT_LOG_OPTIONS:
log_options = value;
break;
case PREF_VHOST:
iface.s_addr = (unsigned long) value;
break;
default:
DEBUG("user_options::set_option(int, int) --> bad option!\n");
abort();
}
return 1;
}
/*
* set string option ... */
int user_options::set(int field, const char * value)
{
switch (field)
{
case OPT_PASSWORD:
delete[] password;
password = my_strdup(value);
break;
case OPT_AUTOSERVER:
delete[] autoserver;
autoserver = my_strdup(value);
break;
case PREF_AUTO_PASS:
delete[] autopass;
autopass = my_strdup(value);
break;
case PREF_FAKE_IDENT:
delete[] fake_ident;
fake_ident = my_strdup(value);
break;
case PREF_VHOST:
case OPT_DEFAULT_VHOST:
/* String given .. resolve, and try to fill in */
struct in_addr in;
if (fill_in_addr(value, &in) < 1)
return 0;
set(PREF_VHOST, in.s_addr);
break;
default:
DEBUG("user_options::set_option() --> bad option!\n");
abort();
}
return 1;
}
int user_options::clear(int field)
{
switch (field)
{
case OPT_MAX_LOGFILE_SIZE:
max_logsize = 0;
break;
case OPT_MAX_IDLE_TIME:
max_idle = 0;
break;
case OPT_LOG_OPTIONS:
log_options = 0;
break;
case PREF_VHOST:
iface.s_addr = 0;
break;
case OPT_PASSWORD:
delete[] password;
password = 0;
break;
case OPT_AUTOSERVER:
delete[] autoserver;
autoserver = 0;
break;
case PREF_AUTO_PASS:
delete[] autopass;
autopass = 0;
break;
case PREF_FAKE_IDENT:
delete[] fake_ident;
fake_ident = 0;
break;
default:
DEBUG("WTF?");
abort();
}
return 1;
}
int user_options::get(int field) const
{
switch (field)
{
case OPT_MAX_LOGFILE_SIZE:
return max_logsize;
case OPT_MAX_IDLE_TIME:
return max_idle;
case OPT_LOG_OPTIONS:
case OPT_DEFAULT_LOG_OPTIONS:
return log_options;
case PREF_VHOST:
return (int) iface.s_addr;
default:
DEBUG("user_options::get(int) ---> bad option!\n");
abort();
}
return 1;
}
char * user_options::get(int field, char * ) const
{
switch (field)
{
case OPT_PASSWORD:
return password;
case OPT_AUTOSERVER:
return autoserver;
case PREF_AUTO_PASS:
return autopass;
case PREF_FAKE_IDENT:
return fake_ident;
default:
DEBUG("user_options::get() --> bad option!\n");
abort();
}
return 0;
}
/*
* decide whether or not we can do v and we want to do it
*/
int user_options::decide(int v) const
{
if ((flags & v) || (flags & OPT_USER_IS_ADMIN))
if (prefs & v)
return 1;
else
return 0;
return 0;
}
user_options::~user_options(void)
{
delete[] fake_ident;
delete[] autopass;
delete[] password;
delete[] autoserver;
}
int user_options::lookup_cmd(const char * cmd)
{
struct user_pref_struct {
const char * str;
int flag;
};
const static struct user_pref_struct user_pref_table[] = {
{ "fake-ident", PREF_FAKE_IDENT},
{ "log", PREF_LOG},
{ "auto-detach", PREF_AUTO_DETACH},
{ "vhost", PREF_VHOST},
{ "proxy-dcc-in", PREF_DCC_IN},
{ "proxy-dcc-out", PREF_DCC_OUT},
{ "auto-detach-pass", PREF_AUTO_PASS},
{ "auto-server", OPT_AUTOSERVER},
};
for (unsigned i = 0; i < sizeof(user_pref_table) / sizeof(user_pref_struct); i++)
if (!strcasecmp(cmd, user_pref_table[i].str))
return user_pref_table[i].flag;
return 0;
}
int user_options::copy_config_only(const user_options * u2)
{
flags = u2->flags;
max_logsize = u2->max_logsize;
max_idle = u2->max_idle;
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1