From c311c6c83e9bbc9f08cf8da211a9f64d01edd201 Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 8 Jul 2011 01:54:49 +0200 Subject: [PATCH] added LOC Support with privilege exchange and privilege class interface --- src/modcmd.c | 2 + src/nickserv.c | 145 +++++++++++- src/nickserv.h | 8 +- src/opserv.c | 578 +++++++++++++++++++++++++++++++++++++++++++++ src/opserv.h | 34 +++ src/proto-common.c | 1 + src/proto-p10.c | 37 ++- 7 files changed, 801 insertions(+), 4 deletions(-) diff --git a/src/modcmd.c b/src/modcmd.c index e36e536..569e83b 100644 --- a/src/modcmd.c +++ b/src/modcmd.c @@ -2417,6 +2417,8 @@ create_default_binds(void) { struct svccmd *svccmd; svccmd = service_make_alias(service, "stats", "*modcmd.joiner", NULL); svccmd->min_opserv_level = 101; + svccmd = service_make_alias(service, "devnull", "*modcmd.joiner", NULL); + svccmd->min_opserv_level = 200; svccmd = service_make_alias(service, "service", "*modcmd.joiner", NULL); svccmd->min_opserv_level = 900; } diff --git a/src/nickserv.c b/src/nickserv.c index 6c621bc..f245d6e 100644 --- a/src/nickserv.c +++ b/src/nickserv.c @@ -85,6 +85,7 @@ #define KEY_REGISTER_ON "register" #define KEY_LAST_SEEN "lastseen" #define KEY_INFO "info" +#define KEY_DEVNULL "devnull" #define KEY_WEBSITE "website" #define KEY_USERLIST_STYLE "user_style" #define KEY_SCREEN_WIDTH "screen_width" @@ -213,6 +214,7 @@ static const struct message_entry msgtab[] = { { "NSMSG_HANDLEINFO_COOKIE_ALLOWAUTH", " Cookie: There is currently an allowauth cookie issued for this account" }, { "NSMSG_HANDLEINFO_COOKIE_UNKNOWN", " Cookie: There is currently an unknown cookie issued for this account" }, { "NSMSG_HANDLEINFO_INFOLINE", " Infoline: %s" }, + { "NSMSG_HANDLEINFO_DEVNULL", " DevNull Class: %s" }, { "NSMSG_HANDLEINFO_WEBSITE", " Website: %s" }, { "NSMSG_HANDLEINFO_FLAGS", " Flags: %s" }, { "NSMSG_HANDLEINFO_EPITHET", " Epithet: %s" }, @@ -307,6 +309,8 @@ static const struct message_entry msgtab[] = { { "NSMSG_SETTING_LIST", "$b$N account settings:$b" }, { "NSMSG_INVALID_OPTION", "$b%s$b is an invalid account setting." }, { "NSMSG_SET_INFO", "$bINFO: $b%s" }, + { "NSMSG_SET_DEVNULL", "$bDEVNULL: $b%s" }, + { "NSMSG_SET_AUTOHIDE", "$bAUTOHIDE: $b%s" }, { "NSMSG_SET_WEBSITE", "$bWEBSITE: $b%s" }, { "NSMSG_SET_WIDTH", "$bWIDTH: $b%d" }, { "NSMSG_SET_TABLEWIDTH", "$bTABLEWIDTH: $b%d" }, @@ -467,6 +471,7 @@ register_handle(const char *handle, const char *passwd, unsigned long id) hi->id = id; hi->website = NULL; + hi->devnull = NULL; dict_insert(nickserv_id_dict, strdup(id_base64), hi); return hi; @@ -553,6 +558,7 @@ free_handle_info(void *vhi) free(hi->infoline); free(hi->epithet); free(hi->fakehost); + free(hi->devnull); free(hi->website); free(hi->fakeident); if (hi->cookie) { @@ -1404,6 +1410,8 @@ static NICKSERV_FUNC(cmd_handleinfo) } reply("NSMSG_HANDLEINFO_INFOLINE", (hi->infoline ? hi->infoline : nsmsg_none)); + if (oper_has_access(user, cmd->parent->bot, 200, 1)) + reply("NSMSG_HANDLEINFO_DEVNULL", (hi->devnull ? hi->devnull : nsmsg_none)); if (user->handle_info && HANDLE_FLAGGED(user->handle_info, BOT)) reply("NSMSG_HANDLEINFO_WEBSITE", (hi->website ? hi->website : nsmsg_none)); if (HANDLE_FLAGGED(hi, FROZEN)) @@ -1670,7 +1678,7 @@ static NICKSERV_FUNC(cmd_rename_handle) reply("NSMSG_HANDLE_CHANGED", old_handle, hi->handle); global_message(MESSAGE_RECIPIENT_STAFF, msgbuf); free(old_handle); - apply_fakehost(hi); + apply_fakehost(hi, NULL); return 1; } @@ -1791,6 +1799,10 @@ static NICKSERV_FUNC(cmd_auth) return 1; } } + if (HANDLE_FLAGGED(hi, AUTOHIDE)) { + //ok we have a fakehost set... but we need to set mode +x + irc_svsmode(nickserv,user,"+x"); + } set_user_handle_info(user, hi, 1); if (nickserv_conf.email_required && !hi->email_addr) @@ -1810,6 +1822,53 @@ static NICKSERV_FUNC(cmd_auth) return 1; } +struct handle_info *checklogin(const char *user, const char *pass, const char *numeric, const char *hostmask) +{ + struct handle_info *hi; + hi = dict_find(nickserv_handle_dict, user, NULL); + if(!hi) + return NULL; + if(!checkpass(pass, hi->passwd)) + return NULL; + if (HANDLE_FLAGGED(hi, SUSPENDED)) + return NULL; + /** following in one of the next commits + struct last_login *login,*clogin,*old; + unsigned int ii = 0; + login = calloc(1, sizeof(*login)); + login->last_login = hi->last_login; + login->hostmask = strdup(hostmask); + login->authtime = now; + login->quittime = 0; + login->quit = NULL; + login->user = NULL; + login->loc_pending = strdup(numeric); + for (clogin = hi->last_login; clogin != NULL && ii < 9; clogin = clogin->last_login) { + if(ii == 8 && clogin->last_login) { + old = clogin->last_login; + clogin->last_login = NULL; + free(old->hostmask); + if(old->quit) + free(old->quit); + if(old->loc_pending) + free(old->loc_pending); + free(old); + } + } + hi->last_login = login; + */ + return hi; +} + +char *getfakehost(const char *user) +{ + struct handle_info *hi; + hi = dict_find(nickserv_handle_dict, user, NULL); + if(!hi) + return 0; + return generate_fakehost(hi); +} + static allowauth_func_t *allowauth_func_list; static unsigned int allowauth_func_size = 0, allowauth_func_used = 0; @@ -2283,7 +2342,7 @@ set_list(struct userNode *user, struct handle_info *hi, int override) unsigned int i; char *set_display[] = { "INFO", "WIDTH", "TABLEWIDTH", "COLOR", "PRIVMSG", "STYLE", - "EMAIL", "MAXLOGINS", "LANGUAGE" + "EMAIL", "MAXLOGINS", "LANGUAGE", "DEVNULL" }; send_message(user, nickserv, "NSMSG_SETTING_LIST"); @@ -2358,6 +2417,56 @@ static OPTION_FUNC(opt_info) return 1; } +static OPTION_FUNC(opt_devnull) +{ + const char *devnull; + + if (argc > 1) { + if (!override) { + send_message(user, nickserv, "MSG_SETTING_PRIVILEGED", argv[0]); + return 0; + } + if ((argv[1][0] == '*') && (argv[1][1] == 0)) { + free(hi->devnull); + hi->devnull = NULL; + } else { + devnull = unsplit_string(argv+1, argc-1, NULL); + if(devnull_check(devnull) == 1) { + hi->devnull = strdup(devnull); + } + } + } + + devnull = hi->devnull ? hi->devnull : user_find_message(user, "MSG_NONE"); + send_message(user, nickserv, "NSMSG_SET_DEVNULL", devnull); + return 1; +} + +void nickserv_devnull_delete(char *name) { + dict_iterator_t it; + struct handle_info *hi; + + for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) { + hi = iter_data(it); + if (hi->devnull && !irccasecmp(name, hi->devnull)) { + free(hi->devnull); + hi->devnull = NULL; + } + } +} + +void nickserv_devnull_rename(char *oldname, char *newname) { + dict_iterator_t it; + struct handle_info *hi; + + for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) { + hi = iter_data(it); + if (hi->devnull && !irccasecmp(oldname, hi->devnull)) { + hi->devnull = strdup(newname); + } + } +} + static OPTION_FUNC(opt_website) { const char *website; @@ -2444,6 +2553,23 @@ static OPTION_FUNC(opt_privmsg) return 1; } +static OPTION_FUNC(opt_autohide) +{ + if (argc > 1) { + if (enabled_string(argv[1])) + HANDLE_SET_FLAG(hi, AUTOHIDE); + else if (disabled_string(argv[1])) + HANDLE_CLEAR_FLAG(hi, AUTOHIDE); + else { + send_message(user, nickserv, "MSG_INVALID_BINARY", argv[1]); + return 0; + } + } + + send_message(user, nickserv, "NSMSG_SET_AUTOHIDE", user_find_message(user, HANDLE_FLAGGED(hi, AUTOHIDE) ? "MSG_ON" : "MSG_OFF")); + return 1; +} + static OPTION_FUNC(opt_style) { char *style; @@ -3110,6 +3236,8 @@ nickserv_saxdb_write(struct saxdb_context *ctx) { saxdb_write_int(ctx, KEY_ID, hi->id); if (hi->infoline) saxdb_write_string(ctx, KEY_INFO, hi->infoline); + if (hi->devnull) + saxdb_write_string(ctx, KEY_DEVNULL, hi->devnull); if (hi->website) saxdb_write_string(ctx, KEY_WEBSITE, hi->website); if (hi->last_quit_host[0]) @@ -3302,6 +3430,7 @@ struct nickserv_discrim { const char *fakehostmask; const char *fakeidentmask; const char *website; + const char *devnullclass; const char *handlemask; const char *emailmask; }; @@ -3413,6 +3542,12 @@ nickserv_discrim_create(struct userNode *user, unsigned int argc, char *argv[]) } else { discrim->website = argv[i]; } + } else if (!irccasecmp(argv[i], "devnull")) { + if (!irccasecmp(argv[++i], "*")) { + discrim->devnullclass = 0; + } else { + discrim->devnullclass = argv[i]; + } } else if (!irccasecmp(argv[i], "handlemask") || !irccasecmp(argv[i], "accountmask")) { if (!irccasecmp(argv[++i], "*")) { discrim->handlemask = 0; @@ -3490,6 +3625,7 @@ nickserv_discrim_match(struct nickserv_discrim *discrim, struct handle_info *hi) || (discrim->fakehostmask && (!hi->fakehost || !match_ircglob(hi->fakehost, discrim->fakehostmask))) || (discrim->fakeidentmask && (!hi->fakeident || !match_ircglob(hi->fakeident, discrim->fakeidentmask))) || (discrim->website && (!hi->website || !match_ircglob(hi->website, discrim->website))) + || (discrim->devnullclass && (!hi->devnull || !match_ircglob(hi->devnull, discrim->devnullclass))) || (discrim->emailmask && (!hi->email_addr || !match_ircglob(hi->email_addr, discrim->emailmask))) || (discrim->min_level > hi->opserv_level) || (discrim->max_level < hi->opserv_level) @@ -3739,6 +3875,9 @@ nickserv_db_read_handle(const char *handle, dict_t obj) str = database_get_data(obj, KEY_WEBSITE, RECDB_QSTRING); if (str) hi->website = strdup(str); + str = database_get_data(obj, KEY_DEVNULL, RECDB_QSTRING); + if (str) + hi->devnull = strdup(str); str = database_get_data(obj, KEY_REGISTER_ON, RECDB_QSTRING); hi->registered = str ? strtoul(str, NULL, 0) : now; str = database_get_data(obj, KEY_LAST_SEEN, RECDB_QSTRING); @@ -4363,10 +4502,12 @@ init_nickserv(const char *nick) dict_insert(nickserv_opt_dict, "COLOR", opt_color); dict_insert(nickserv_opt_dict, "PRIVMSG", opt_privmsg); dict_insert(nickserv_opt_dict, "STYLE", opt_style); + dict_insert(nickserv_opt_dict, "AUTOHIDE", opt_autohide); dict_insert(nickserv_opt_dict, "PASS", opt_password); dict_insert(nickserv_opt_dict, "PASSWORD", opt_password); dict_insert(nickserv_opt_dict, "FLAGS", opt_flags); dict_insert(nickserv_opt_dict, "WEBSITE", opt_website); + dict_insert(nickserv_opt_dict, "DEVNULL", opt_devnull); dict_insert(nickserv_opt_dict, "ACCESS", opt_level); dict_insert(nickserv_opt_dict, "LEVEL", opt_level); dict_insert(nickserv_opt_dict, "EPITHET", opt_epithet); diff --git a/src/nickserv.h b/src/nickserv.h index f32e23e..de721a6 100644 --- a/src/nickserv.h +++ b/src/nickserv.h @@ -38,8 +38,9 @@ struct svccmd; #define HI_FLAG_NODELETE 0x00000080 #define HI_FLAG_NETWORK_HELPER 0x00000100 #define HI_FLAG_BOT 0x00000200 +#define HI_FLAG_AUTOHIDE 0x00000400 /* Flag characters for the above. First char is LSB, etc. */ -#define HANDLE_FLAGS "SphgscfnHb" +#define HANDLE_FLAGS "SphgscfnHbx" /* HI_STYLE_* go into handle_info.userlist_style */ #define HI_STYLE_DEF 'd' @@ -93,6 +94,7 @@ struct handle_info { struct handle_note *notes; struct language *language; char *website; + char *devnull; char *email_addr; char *epithet; char *infoline; @@ -137,6 +139,10 @@ struct modeNode *find_handle_in_channel(struct chanNode *channel, struct handle_ int nickserv_modify_handle_flags(struct userNode *user, struct userNode *bot, const char *str, unsigned long *add, unsigned long *remove); int oper_has_access(struct userNode *user, struct userNode *bot, unsigned int min_level, unsigned int quiet); void nickserv_show_oper_accounts(struct userNode *user, struct svccmd *cmd); +struct handle_info *checklogin(const char *user, const char *pass, const char *numeric, const char *hostmask); +char *getfakehost(const char *user); +void nickserv_devnull_delete(char *name); +void nickserv_devnull_rename(char *oldname, char *newname); /* auth_funcs are called when a user gets a new handle_info. They are * called *after* user->handle_info has been updated. */ diff --git a/src/opserv.c b/src/opserv.c index 38ad356..0702a10 100644 --- a/src/opserv.c +++ b/src/opserv.c @@ -76,6 +76,11 @@ #define KEY_BLOCK_GLINE_DURATION "block_gline_duration" #define KEY_ISSUER "issuer" #define KEY_ISSUED "issued" +#define KEY_DEVNULL_CLASSES "classes" +#define KEY_DEVNULL_NAME "class" +#define KEY_DEVNULL_MODE "modes" +#define KEY_DEVNULL_MAXCHAN "chanlimit" +#define KEY_DEVNULL_MAXSENDQ "sendq" #define IDENT_FORMAT "%s [%s@%s/%s]" #define IDENT_DATA(user) user->nick, user->ident, user->hostname, irc_ntoa(&user->ip) @@ -257,6 +262,36 @@ static const struct message_entry msgtab[] = { { "OSMSG_CSEARCH_CHANNEL_INFO", "%s [%d users] %s %s" }, { "OSMSG_TRACE_MAX_CHANNELS", "You may not use the 'channel' criterion more than %d times." }, { "OSMSG_FORCEKICK_LOCAL", "You cannot kick $b%s$b forcefully." }, + { "OSMSG_DEVNULL_USER" , "[%s] %s %s" }, + { "OSMSG_DEVNULL_MATCH" , "%d Users found." }, + { "OSMSG_DEVNULL_CLASS" , "%s is not a valid DevNull class." }, + { "OSMSG_DEVNULL_ADDED", "Added %s to DevNull list (class: %s)" }, + { "OSMSG_DEVNULL_DELETED", "Deleted %s from DevNull list (class: %s)" }, + { "OSMSG_DEVNULL_NOTADDED", "User %s is not listed on DevNull list." }, + { "OSMSG_DEVNULL_ACTION", "Unrecognized trace action $b%s$b" }, + { "OSMSG_DEVNULL_FOUND", "DevNull Class %s is already existing." }, + { "OSMSG_DEVNULL_NOTFOUND", "can't find DevNull class %s." }, + { "OSMSG_DEVNULL_ADDED", "DevNull Class %s added." }, + { "OSMSG_DEVNULL_REMOVED", "DevNull Class %s removed." }, + { "OSMSG_DEVNULL_SET", "Settings for DevNull Class %s" }, + { "OSMSG_DEVNULL_SET_A", "ChanLimit: %s" }, + { "OSMSG_DEVNULL_SET_A_i", "ChanLimit: %i" }, + { "OSMSG_DEVNULL_SET_B", "UnlimitTarget: %s" }, + { "OSMSG_DEVNULL_SET_C", "Flood: %s" }, + { "OSMSG_DEVNULL_SET_E", "ChanHide: %s" }, + { "OSMSG_DEVNULL_SET_F", "IdleHide: %s" }, + { "OSMSG_DEVNULL_SET_G", "ChServMode: %s" }, + { "OSMSG_DEVNULL_SET_H", "XtraOpMode: %s" }, + { "OSMSG_DEVNULL_SET_I", "NetServMode: %s" }, + { "OSMSG_DEVNULL_SET_J", "SeeIdle: %s" }, + { "OSMSG_DEVNULL_SET_K", "ForceIdleHide: %s" }, + { "OSMSG_DEVNULL_SET_L", "OverrideCC: %s" }, + { "OSMSG_DEVNULL_SET_M", "OverrideNoAmsg: %s" }, + { "OSMSG_DEVNULL_SET_N", "MaxSendQ: %s" }, + { "OSMSG_DEVNULL_SET_N_i", "MaxSendQ: %i" }, + { "OSMSG_DEVNULL_SET_DONE", "Done." }, + { "OSMSG_DEVNULL_RENAMED", "Devnull class %s renamed to %s" }, + { "OSMSG_DEVNULL_SET_INVALID", "Invalid Option for setting %s" }, { NULL, NULL } }; @@ -271,6 +306,7 @@ static dict_t opserv_reserved_nick_dict; /* data is struct userNode* */ static struct string_list *opserv_bad_words; static dict_t opserv_exempt_channels; /* data is not used */ static dict_t opserv_trusted_hosts; /* data is struct trusted_host* */ +static dict_t opserv_devnull_classes; /* data is struct devnull_class* */ static dict_t opserv_hostinfo_dict; /* data is struct opserv_hostinfo* */ static dict_t opserv_user_alerts; /* data is struct opserv_user_alert* */ static dict_t opserv_nick_based_alerts; /* data is struct opserv_user_alert* */ @@ -279,7 +315,9 @@ static dict_t opserv_account_alerts; /* data is struct opserv_user_alert* */ static struct module *opserv_module; static struct log_type *OS_LOG; static unsigned int new_user_flood; +const char *devnull_modes = DEVNULL_MODES; static char *level_strings[1001]; +static char devnull_inverse_modes[256]; static struct { struct chanNode *debug_channel; @@ -2763,6 +2801,57 @@ trusted_host_read(const char *host, void *data, UNUSED_ARG(void *extra)) return 0; } +static void +opserv_add_devnull_class(const char *name, unsigned long modes, unsigned long maxchan, unsigned long maxsendq) +{ + struct devnull_class *th; + th = calloc(1, sizeof(*th)); + if (!th) + return; + th->name = strdup(name); + th->modes = modes; + th->maxchan = maxchan; + th->maxsendq = maxsendq; + dict_insert(opserv_devnull_classes, th->name, th); +} + +static void +free_devnull_class(void *data) +{ + struct devnull_class *th = data; + free(th->name); + free(th); +} + +static int +devnull_class_read(const char *name, void *data, UNUSED_ARG(void *extra)) +{ + struct record_data *rd = data; + const char *nameb = name, *str; + unsigned long modes, maxchan, maxsendq; + unsigned int ii; + + if (rd->type == RECDB_OBJECT) { + dict_t obj = GET_RECORD_OBJECT(rd); + /* new style structure */ + nameb = database_get_data(obj, KEY_DEVNULL_NAME, RECDB_QSTRING); + str = database_get_data(obj, KEY_DEVNULL_MODE, RECDB_QSTRING); + modes = 0; + if (str) { + for (ii=0; str[ii]; ii++) + modes |= 1 << (devnull_inverse_modes[(unsigned char)str[ii]] - 1); + } + str = database_get_data(obj, KEY_DEVNULL_MAXCHAN, RECDB_QSTRING); + maxchan = str ? ParseInterval(str) : 0; + str = database_get_data(obj, KEY_DEVNULL_MAXSENDQ, RECDB_QSTRING); + maxsendq = str ? ParseInterval(str) : 0; + } else + return 0; + + opserv_add_devnull_class(nameb, modes, maxchan, maxsendq); + return 0; +} + static int opserv_saxdb_read(struct dict *conf_db) { @@ -2807,6 +2896,8 @@ opserv_saxdb_read(struct dict *conf_db) } if ((object = database_get_data(conf_db, KEY_TRUSTED_HOSTS, RECDB_OBJECT))) dict_foreach(object, trusted_host_read, opserv_trusted_hosts); + if ((object = database_get_data(conf_db, KEY_DEVNULL_CLASSES, RECDB_OBJECT))) + dict_foreach(object, devnull_class_read, opserv_devnull_classes); if ((object = database_get_data(conf_db, KEY_GAGS, RECDB_OBJECT))) dict_foreach(object, add_gag_helper, NULL); if ((object = database_get_data(conf_db, KEY_ALERTS, RECDB_OBJECT))) @@ -2864,6 +2955,28 @@ opserv_saxdb_write(struct saxdb_context *ctx) } saxdb_end_record(ctx); } + /* devnull_classes */ + if (dict_size(opserv_devnull_classes)) { + saxdb_start_record(ctx, KEY_DEVNULL_CLASSES, 1); + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + struct devnull_class *th = iter_data(it); + saxdb_start_record(ctx, iter_key(it), 0); + if (th->name) saxdb_write_string(ctx, KEY_DEVNULL_NAME, th->name); + if (th->modes) { + int ii, flen; + char flags[50]; + for (ii=flen=0; devnull_modes[ii]; ++ii) + if (th->modes & (1 << ii)) + flags[flen++] = devnull_modes[ii]; + flags[flen] = 0; + saxdb_write_string(ctx, KEY_DEVNULL_MODE, flags); + } + if (th->maxchan) saxdb_write_int(ctx, KEY_DEVNULL_MAXCHAN, th->maxchan); + if (th->maxsendq) saxdb_write_int(ctx, KEY_DEVNULL_MAXSENDQ, th->maxsendq); + saxdb_end_record(ctx); + } + saxdb_end_record(ctx); + } /* gags */ if (gagList) { struct gag_entry *gag; @@ -4135,6 +4248,454 @@ static MODCMD_FUNC(cmd_delalert) return 1; } +static MODCMD_FUNC(cmd_listdevnull) +{ + struct helpfile_table tbl; + unsigned int count = 0, ii = 0; + char *on,*off,*half; + on = "X"; + off = "-"; + half = "1/2"; + + dict_iterator_t it; + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + count++; + } + tbl.length = count+1; + tbl.width = 14; + tbl.flags = 0; + tbl.flags = TABLE_NO_FREE; + tbl.contents = malloc(tbl.length * sizeof(tbl.contents[0])); + tbl.contents[0] = malloc(tbl.width * sizeof(tbl.contents[0][0])); + tbl.contents[0][0] = "Name"; + tbl.contents[0][1] = "MC"; + tbl.contents[0][2] = "UT"; + tbl.contents[0][3] = "FL"; + tbl.contents[0][4] = "CH"; + tbl.contents[0][5] = "IH"; + tbl.contents[0][6] = "SI"; + tbl.contents[0][7] = "IH²"; + tbl.contents[0][8] = "oC"; + tbl.contents[0][9] = "oM"; + tbl.contents[0][10] = "+k"; + tbl.contents[0][11] = "+S"; + tbl.contents[0][12] = "+X"; + tbl.contents[0][13] = "MaxQ"; + if(!count) + { + table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); + reply("MSG_NONE"); + free(tbl.contents[0]); + free(tbl.contents); + return 0; + } + for (it = dict_first(opserv_devnull_classes); it; it = iter_next(it)) { + struct devnull_class *th = iter_data(it); + tbl.contents[++ii] = malloc(tbl.width * sizeof(tbl.contents[0][0])); + tbl.contents[ii][0] = th->name; + if(DEVNULL_FLAGGED(th, MODE_A)) { + tbl.contents[ii][1] = strtab(th->maxchan); + } else { + tbl.contents[ii][1] = off; + } + if(DEVNULL_FLAGGED(th, MODE_B)) { + tbl.contents[ii][2] = on; + } else { + tbl.contents[ii][2] = off; + } + if(DEVNULL_FLAGGED(th, MODE_D)) { + tbl.contents[ii][3] = on; + } else if(DEVNULL_FLAGGED(th, MODE_C)) { + tbl.contents[ii][3] = half; + } else { + tbl.contents[ii][3] = off; + } + if(DEVNULL_FLAGGED(th, MODE_E)) { + tbl.contents[ii][4] = on; + } else { + tbl.contents[ii][4] = off; + } + if(DEVNULL_FLAGGED(th, MODE_F)) { + tbl.contents[ii][5] = on; + } else { + tbl.contents[ii][5] = off; + } + if(DEVNULL_FLAGGED(th, MODE_J)) { + tbl.contents[ii][6] = on; + } else { + tbl.contents[ii][6] = off; + } + if(DEVNULL_FLAGGED(th, MODE_K)) { + tbl.contents[ii][7] = on; + } else { + tbl.contents[ii][7] = off; + } + if(DEVNULL_FLAGGED(th, MODE_L)) { + tbl.contents[ii][8] = on; + } else { + tbl.contents[ii][8] = off; + } + if(DEVNULL_FLAGGED(th, MODE_M)) { + tbl.contents[ii][9] = on; + } else { + tbl.contents[ii][9] = off; + } + if(DEVNULL_FLAGGED(th, MODE_G)) { + tbl.contents[ii][10] = on; + } else { + tbl.contents[ii][10] = off; + } + if(DEVNULL_FLAGGED(th, MODE_I)) { + tbl.contents[ii][11] = on; + } else { + tbl.contents[ii][11] = off; + } + if(DEVNULL_FLAGGED(th, MODE_H)) { + tbl.contents[ii][12] = on; + } else { + tbl.contents[ii][12] = off; + } + if(DEVNULL_FLAGGED(th, MODE_N)) { + tbl.contents[ii][13] = on; + } else { + tbl.contents[ii][13] = off; + } + } + table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); + for(ii = 1; ii < tbl.length; ++ii) + { + free(tbl.contents[ii]); + } + free(tbl.contents[0]); + free(tbl.contents); + send_message_type(4, user, opserv,"-"); + /* + tbl.contents[0][1] = "MC"; + tbl.contents[0][2] = "UT"; + tbl.contents[0][3] = "FL"; + tbl.contents[0][4] = "CH"; + tbl.contents[0][5] = "IH"; + tbl.contents[0][6] = "SI"; + tbl.contents[0][7] = "IH²"; + tbl.contents[0][8] = "oC"; + tbl.contents[0][9] = "oM"; + tbl.contents[0][10] = "+k"; + tbl.contents[0][11] = "+S"; + tbl.contents[0][12] = "+X"; + tbl.contents[0][13] = "MaxQ"; + */ + send_message_type(4, user, opserv,"MC = MaxChan"); + send_message_type(4, user, opserv,"UT = UnlimitTargets"); + send_message_type(4, user, opserv,"FL = Flood (1 = 1/2 flood, X = unlimited)"); + send_message_type(4, user, opserv,"CH = Channel Hide (mode +n)"); + send_message_type(4, user, opserv,"IH = Idle Hide (mode +I)"); + send_message_type(4, user, opserv,"SI = See Idle"); + send_message_type(4, user, opserv,"IH² = Idle Hide (override SI)"); + send_message_type(4, user, opserv,"oC = Color override (mode +c)"); + send_message_type(4, user, opserv,"oM = AMsg override"); + send_message_type(4, user, opserv,"+k = ChanServ Mode (mode +k)"); + send_message_type(4, user, opserv,"+S = NetServ Mode (mode +S)"); + send_message_type(4, user, opserv,"+X = XtraOp Mode (mode +X)"); + return 1; +} + +static MODCMD_FUNC(cmd_adddevnull) +{ + + if (dict_find(opserv_devnull_classes, argv[1], NULL)) { + reply("OSMSG_DEVNULL_FOUND", argv[1]); + return 0; + } + + opserv_add_devnull_class(argv[1], 0, 0, 0); + reply("OSMSG_DEVNULL_ADDED",argv[1]); + return 1; +} + + +static MODCMD_FUNC(cmd_deldevnull) +{ + unsigned int n; + + for (n=1; nname); + dict_remove(opserv_devnull_classes, argv[n]); + reply("OSMSG_DEVNULL_REMOVED",argv[n]); + } + return 1; +} + +static MODCMD_FUNC(cmd_renamedevnull) +{ + struct devnull_class *th; + if (dict_find(opserv_devnull_classes, argv[2], NULL)) { + reply("OSMSG_DEVNULL_FOUND", argv[2]); + return 0; + } + if ((th = dict_find(opserv_devnull_classes, argv[1], NULL))) { + opserv_add_devnull_class(argv[2], th->modes, th->maxchan, th->maxsendq); + nickserv_devnull_rename(th->name,argv[2]); + dict_remove(opserv_devnull_classes, argv[1]); + reply("OSMSG_DEVNULL_RENAMED",argv[1],argv[2]); + } else { + reply("OSMSG_DEVNULL_NOTFOUND", argv[1]); + return 0; + } + return 1; +} + +static MODCMD_FUNC(cmd_setdevnull) +{ + struct devnull_class *th; + unsigned int offset=0; + if ((th = dict_find(opserv_devnull_classes, argv[offset+1], NULL))) { + if (argc > 3) { + unsigned int ii; + for( ii = 0; argv[offset+2][ ii ]; ii++) + argv[offset+2][ ii ] = toupper( argv[offset+2][ ii ] ); + for( ii = 0; argv[offset+3][ ii ]; ii++) + argv[offset+3][ ii ] = toupper( argv[offset+3][ ii ] ); + if(!strcmp("CHANLIMIT",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_A); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_FLAG(th, MODE_A); + th->maxchan = strtoul(argv[offset+3], NULL, 0); + reply("OSMSG_DEVNULL_SET_DONE"); + } + } + else if(!strcmp("UNLIMITTARGET",argv[offset+2]) || !strcmp("UNLIMITEDTARGET",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_B); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_B); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("FLOOD",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_C); + DEVNULL_CLEAR_FLAG(th, MODE_D); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_D); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("HALF",argv[offset+3]) || !strcmp("2",argv[offset+3]) || !strcmp("1/2",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_C); + DEVNULL_CLEAR_FLAG(th, MODE_D); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("CHANHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_E); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_E); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("IDLEHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_F); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_F); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("CHSERVMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_G); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_G); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("XTRAOPMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_H); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_H); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("NETSERVMODE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_I); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_I); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("SEEIDLE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_J); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_J); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("FORCEIDLEHIDE",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_K); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_K); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("OVERRIDECC",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_L); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_L); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("OVERRIDENOAMSG",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_M); + reply("OSMSG_DEVNULL_SET_DONE"); + } else if (!strcmp("ON",argv[offset+3]) || !strcmp("1",argv[offset+3])) { + DEVNULL_SET_FLAG(th, MODE_M); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+3]); + } + } + else if(!strcmp("MAXSENDQ",argv[offset+2])) { + if (!strcmp("OFF",argv[offset+3]) || !strcmp("0",argv[offset+3])) { + DEVNULL_CLEAR_FLAG(th, MODE_N); + reply("OSMSG_DEVNULL_SET_DONE"); + } else { + DEVNULL_SET_FLAG(th, MODE_N); + th->maxsendq = strtoul(argv[offset+3], NULL, 0); + reply("OSMSG_DEVNULL_SET_DONE"); + } + } else { + reply("OSMSG_DEVNULL_SET_INVALID", argv[offset+2]); + } + + } else { + reply("OSMSG_DEVNULL_SET", th->name); + if(DEVNULL_FLAGGED(th, MODE_A)) { + reply("OSMSG_DEVNULL_SET_A_i", th->maxchan); + } else { + reply("OSMSG_DEVNULL_SET_A", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_B)) { + reply("OSMSG_DEVNULL_SET_B", "on"); + } else { + reply("OSMSG_DEVNULL_SET_B", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_D)) { + reply("OSMSG_DEVNULL_SET_C", "on"); + } else if(DEVNULL_FLAGGED(th, MODE_C)) { + reply("OSMSG_DEVNULL_SET_C", "half"); + } else { + reply("OSMSG_DEVNULL_SET_C", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_E)) { + reply("OSMSG_DEVNULL_SET_E", "on"); + } else { + reply("OSMSG_DEVNULL_SET_E", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_F)) { + reply("OSMSG_DEVNULL_SET_F", "on"); + } else { + reply("OSMSG_DEVNULL_SET_F", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_G)) { + reply("OSMSG_DEVNULL_SET_G", "on"); + } else { + reply("OSMSG_DEVNULL_SET_G", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_H)) { + reply("OSMSG_DEVNULL_SET_H", "on"); + } else { + reply("OSMSG_DEVNULL_SET_H", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_I)) { + reply("OSMSG_DEVNULL_SET_I", "on"); + } else { + reply("OSMSG_DEVNULL_SET_I", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_J)) { + reply("OSMSG_DEVNULL_SET_J", "on"); + } else { + reply("OSMSG_DEVNULL_SET_J", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_K)) { + reply("OSMSG_DEVNULL_SET_K", "on"); + } else { + reply("OSMSG_DEVNULL_SET_K", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_L)) { + reply("OSMSG_DEVNULL_SET_L", "on"); + } else { + reply("OSMSG_DEVNULL_SET_L", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_M)) { + reply("OSMSG_DEVNULL_SET_M", "on"); + } else { + reply("OSMSG_DEVNULL_SET_M", "off"); + } + if(DEVNULL_FLAGGED(th, MODE_N)) { + reply("OSMSG_DEVNULL_SET_N_i", th->maxsendq); + } else { + reply("OSMSG_DEVNULL_SET_N", "off"); + } + } + } else { + reply("OSMSG_DEVNULL_NOTFOUND", argv[offset+1]); + return 0; + } + return 1; +} + +int devnull_check(const char *name) { + if (dict_find(opserv_devnull_classes, name, NULL)) { + return 1; + } + return 0; +} + +struct devnull_class* + devnull_get(const char *name) { + return dict_find(opserv_devnull_classes, name, NULL); +} + static void opserv_conf_read(void) { @@ -4224,6 +4785,10 @@ opserv_db_init(void) { dict_delete(opserv_trusted_hosts); opserv_trusted_hosts = dict_new(); dict_set_free_data(opserv_trusted_hosts, free_trusted_host); + /* set up opserv_devnull_classes dict */ + dict_delete(opserv_devnull_classes); + opserv_devnull_classes = dict_new(); + dict_set_free_data(opserv_devnull_classes, free_devnull_class); /* set up opserv_chan_warn dict */ dict_delete(opserv_chan_warn); opserv_chan_warn = dict_new(); @@ -4259,6 +4824,7 @@ opserv_db_cleanup(void) free_string_list(opserv_bad_words); dict_delete(opserv_exempt_channels); dict_delete(opserv_trusted_hosts); + dict_delete(opserv_devnull_classes); unreg_del_user_func(opserv_user_cleanup); dict_delete(opserv_hostinfo_dict); dict_delete(opserv_nick_based_alerts); @@ -4283,6 +4849,13 @@ init_opserv(const char *nick) } conf_register_reload(opserv_conf_read); + unsigned int i; + /* set up handle_inverse_flags */ + memset(devnull_inverse_modes, 0, sizeof(devnull_inverse_modes)); + for (i=0; devnull_modes[i]; i++) { + devnull_inverse_modes[(unsigned char)devnull_modes[i]] = i + 1; + } + memset(level_strings, 0, sizeof(level_strings)); opserv_module = module_register("OpServ", OS_LOG, "opserv.help", opserv_help_expand); opserv_define_func("ACCESS", cmd_access, 0, 0, 0); @@ -4361,6 +4934,11 @@ init_opserv(const char *nick) #if defined(WITH_MALLOC_SRVX) || defined(WITH_MALLOC_SLAB) opserv_define_func("STATS MEMORY", cmd_stats_memory, 0, 0, 0); #endif + opserv_define_func("DEVNULL ADD", cmd_adddevnull, 200, 0, 2); + opserv_define_func("DEVNULL DEL", cmd_deldevnull, 200, 0, 2); + opserv_define_func("DEVNULL RENAME", cmd_renamedevnull, 200, 0, 3); + opserv_define_func("DEVNULL SET", cmd_setdevnull, 200, 0, 2); + opserv_define_func("DEVNULL LIST", cmd_listdevnull, 200, 0, 0); opserv_define_func("TRACE", cmd_trace, 100, 0, 3); opserv_define_func("TRACE PRINT", NULL, 0, 0, 0); opserv_define_func("TRACE COUNT", NULL, 0, 0, 0); diff --git a/src/opserv.h b/src/opserv.h index 7daff43..630e8b6 100644 --- a/src/opserv.h +++ b/src/opserv.h @@ -21,8 +21,42 @@ #ifndef _opserv_h #define _opserv_h +/* DEVNULL_MODE_* go into devnull_class.modes */ +#define DEVNULL_MODE_A 0x00000001 +#define DEVNULL_MODE_B 0x00000002 +#define DEVNULL_MODE_C 0x00000004 +#define DEVNULL_MODE_D 0x00000008 +#define DEVNULL_MODE_E 0x00000010 +#define DEVNULL_MODE_F 0x00000020 +#define DEVNULL_MODE_G 0x00000040 +#define DEVNULL_MODE_H 0x00000080 +#define DEVNULL_MODE_I 0x00000100 +#define DEVNULL_MODE_J 0x00000200 +#define DEVNULL_MODE_K 0x00000400 +#define DEVNULL_MODE_L 0x00000800 +#define DEVNULL_MODE_M 0x00001000 +#define DEVNULL_MODE_N 0x00002000 + +#define DEVNULL_MODES "abcdefghijklmn" + +#define DEVNULL_FLAGGED(hi, tok) ((hi)->modes & DEVNULL_##tok) +#define DEVNULL_SET_FLAG(hi, tok) ((hi)->modes |= DEVNULL_##tok) +#define DEVNULL_CLEAR_FLAG(hi, tok) ((hi)->modes &= ~DEVNULL_##tok) + +struct devnull_class { + char *name; + unsigned long modes; + unsigned long maxchan; + unsigned long maxsendq; +}; + void init_opserv(const char *nick); unsigned int gag_create(const char *mask, const char *owner, const char *reason, unsigned long expires); int opserv_bad_channel(const char *name); +void devnull_delete(const char *auth); +void devnull_rename(const char *oldauth, const char *newauth); +int devnull_check(const char *name); +struct devnull_class* devnull_get(const char *name); +struct userNode* GetOpServ(void); #endif diff --git a/src/proto-common.c b/src/proto-common.c index a7c159a..324058f 100644 --- a/src/proto-common.c +++ b/src/proto-common.c @@ -23,6 +23,7 @@ #include "ioset.h" #include "log.h" #include "nickserv.h" +#include "opserv.h" #include "spamserv.h" #include "timeq.h" #ifdef HAVE_SYS_SOCKET_H diff --git a/src/proto-p10.c b/src/proto-p10.c index 278762f..16de1cb 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -1737,7 +1737,42 @@ static CMD_FUNC(cmd_relay) } if(sNode->numeric == self->numeric) { //ok someone relayed something to us! - + if(strcmp("LQ", argv[2]) == 0) { + //oooh thats exciting - we've got a LOC Query! :D + //LQ !ABADE pk910 80.153.5.212 server.zoelle1.de ~watchcat :test + //ok let's check the login datas + struct handle_info *hi; + char tmp[MAXLEN]; + sprintf(tmp, "*!%s@%s",argv[7],argv[5]); + if((hi = checklogin(argv[4],argv[argc-1],&argv[3][1],tmp))) { + //login ok + struct devnull_class *th; + char devnull[512]; + if(hi->devnull && (th = devnull_get(hi->devnull))) { + const char *devnull_modes = DEVNULL_MODES; + int ii, flen; + char flags[50]; + for (ii=flen=0; devnull_modes[ii]; ++ii) + if (th->modes & (1 << ii)) + flags[flen++] = devnull_modes[ii]; + flags[flen] = 0; + sprintf(devnull, "+%s %s %lu %lu",flags,th->name,th->maxchan,th->maxsendq); + } else { + devnull[0] = 0; + } + if(getfakehost(argv[4])) { + sprintf(tmp,"%s LA %s %s %s\n",argv[3],hi->handle,getfakehost(argv[4]),devnull); + } else { + extern const char *hidden_host_suffix; + sprintf(tmp,"%s LA %s %s.%s %s\n",argv[3],hi->handle,hi->handle,hidden_host_suffix,devnull); + } + irc_relay(tmp); + } else { + //login rejected + sprintf(tmp,"%s LR\n",argv[3]); + irc_relay(tmp); + } + } } return 1; } -- 2.20.1