diff --git a/extensions/m_webirc.c b/extensions/m_webirc.c index 1b92ff018..6f57e9207 100644 --- a/extensions/m_webirc.c +++ b/extensions/m_webirc.c @@ -91,7 +91,7 @@ mr_webirc(struct Client *client_p, struct Client *source_p, int parc, const char client_p->localClient->ip.ss_family, NULL); if (aconf == NULL || !(aconf->status & CONF_CLIENT)) return 0; - if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->name, "webirc.")) + if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc.")) { /* XXX */ sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block"); diff --git a/include/operhash.h b/include/operhash.h new file mode 100644 index 000000000..643abf9d4 --- /dev/null +++ b/include/operhash.h @@ -0,0 +1,15 @@ +#ifndef INCLUDED_operhash_h +#define INCLUDED_operhash_h + +struct operhash_entry +{ + char *name; + int refcount; +}; + +void init_operhash(void); +const char *operhash_add(const char *name); +const char *operhash_find(const char *name); +void operhash_delete(const char *name); + +#endif diff --git a/include/s_conf.h b/include/s_conf.h index 949e47630..a46e3535d 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -60,7 +60,11 @@ struct ConfItem unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ unsigned int flags; int clients; /* Number of *LOCAL* clients using this */ - char *name; /* IRC name, nick, server name, or original u@h */ + union + { + char *name; /* IRC name, nick, server name, or original u@h */ + const char *oper; + } info; char *host; /* host part of user@host */ char *passwd; /* doubles as kline reason *ugh* */ char *spasswd; /* Password to send. */ @@ -110,6 +114,9 @@ struct ConfItem /* Macros for struct ConfItem */ +#define IsConfBan(x) ((x)->status & (CONF_KILL|CONF_XLINE|CONF_DLINE|\ + CONF_RESV_CHANNEL|CONF_RESV_NICK)) + #define IsNoTilde(x) ((x)->flags & CONF_FLAGS_NO_TILDE) #define IsNeedIdentd(x) ((x)->flags & CONF_FLAGS_NEED_IDENTD) #define IsConfExemptKline(x) ((x)->flags & CONF_FLAGS_EXEMPTKLINE) diff --git a/modules/m_dline.c b/modules/m_dline.c index 912091c25..bb928ac4c 100644 --- a/modules/m_dline.c +++ b/modules/m_dline.c @@ -43,6 +43,7 @@ #include "parse.h" #include "modules.h" #include "bandbi.h" +#include "operhash.h" static int mo_dline(struct Client *, struct Client *, int, const char **); static int me_dline(struct Client *, struct Client *, int, const char **); @@ -289,6 +290,7 @@ apply_dline(struct Client *source_p, const char *dlhost, int tdline_time, char * aconf->created = rb_current_time(); aconf->host = rb_strdup(dlhost); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) diff --git a/modules/m_kline.c b/modules/m_kline.c index 18dbdca77..b1cc350ea 100644 --- a/modules/m_kline.c +++ b/modules/m_kline.c @@ -44,6 +44,7 @@ #include "modules.h" #include "reject.h" #include "bandbi.h" +#include "operhash.h" static int mo_kline(struct Client *, struct Client *, int, const char **); static int ms_kline(struct Client *, struct Client *, int, const char **); @@ -174,6 +175,7 @@ mo_kline(struct Client *client_p, struct Client *source_p, int parc, const char aconf->user = rb_strdup(user); aconf->port = 0; aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) @@ -276,6 +278,7 @@ handle_remote_kline(struct Client *source_p, int tkline_time, aconf->user = rb_strdup(user); aconf->host = rb_strdup(host); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); /* Look for an oper reason */ if((oper_reason = strchr(reason, '|')) != NULL) diff --git a/modules/m_resv.c b/modules/m_resv.c index 16db1015d..01b41b799 100644 --- a/modules/m_resv.c +++ b/modules/m_resv.c @@ -38,6 +38,7 @@ #include "hash.h" #include "logger.h" #include "bandbi.h" +#include "operhash.h" static int mo_resv(struct Client *, struct Client *, int, const char **); static int ms_resv(struct Client *, struct Client *, int, const char **); @@ -221,6 +222,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); add_to_resv_hash(aconf->host, aconf); resv_chan_forcepart(aconf->host, aconf->passwd, temp_time); @@ -285,6 +287,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te aconf->created = rb_current_time(); aconf->host = rb_strdup(name); aconf->passwd = rb_strdup(reason); + aconf->info.oper = operhash_add(get_oper_name(source_p)); rb_dlinkAddAlloc(aconf, &resv_conf_list); if(temp_time > 0) diff --git a/modules/m_testline.c b/modules/m_testline.c index 7efc62ca8..05b7148b4 100644 --- a/modules/m_testline.c +++ b/modules/m_testline.c @@ -218,7 +218,7 @@ mo_testline(struct Client *client_p, struct Client *source_p, int parc, const ch if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), - aconf->name, EmptyString(aconf->spasswd) ? "" : aconf->spasswd, + aconf->info.name, EmptyString(aconf->spasswd) ? "" : aconf->spasswd, show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, aconf->className); return 0; diff --git a/modules/m_xline.c b/modules/m_xline.c index deb441f13..556ad005c 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -51,6 +51,7 @@ #include "s_newconf.h" #include "reject.h" #include "bandbi.h" +#include "operhash.h" static int mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); static int ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); @@ -280,6 +281,8 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, int t aconf->passwd = rb_strdup(reason); collapse(aconf->host); + aconf->info.oper = operhash_add(get_oper_name(source_p)); + if(temp_time > 0) { aconf->hold = rb_current_time() + temp_time; diff --git a/src/Makefile.in b/src/Makefile.in index c24cd7516..ab69afbb2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,6 +76,7 @@ SRCS = \ monitor.c \ newconf.c \ numeric.c \ + operhash.c \ packet.c \ parse.c \ privilege.c \ diff --git a/src/bandbi.c b/src/bandbi.c index 4de442253..eda44b304 100644 --- a/src/bandbi.c +++ b/src/bandbi.c @@ -46,6 +46,7 @@ #include "send.h" #include "ircd.h" #include "msg.h" /* XXX: MAXPARA */ +#include "operhash.h" static char bandb_add_letter[LAST_BANDB_TYPE] = { 'K', 'D', 'X', 'R' @@ -170,8 +171,7 @@ bandb_handle_ban(char *parv[], int parc) aconf->user = rb_strdup(parv[para++]); aconf->host = rb_strdup(parv[para++]); - /* We do not have the 'oper' field yet. */ - para++; + aconf->info.oper = operhash_add(parv[para++]); switch (parv[0][0]) { diff --git a/src/hostmask.c b/src/hostmask.c index 806ecb86f..1058df5ae 100644 --- a/src/hostmask.c +++ b/src/hostmask.c @@ -390,7 +390,7 @@ find_address_conf(const char *host, const char *sockhost, const char *user, /* if theres a spoof, check it against klines.. */ if(IsConfDoSpoofIp(iconf)) { - char *p = strchr(iconf->name, '@'); + char *p = strchr(iconf->info.name, '@'); /* note, we dont need to pass sockhost here, as its * guaranteed to not match by whats above.. --anfl @@ -398,11 +398,11 @@ find_address_conf(const char *host, const char *sockhost, const char *user, if(p) { *p = '\0'; - kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->name, NULL); + kconf = find_conf_by_address(p+1, NULL, NULL, ip, CONF_KILL, aftype, iconf->info.name, NULL); *p = '@'; } else - kconf = find_conf_by_address(iconf->name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL); + kconf = find_conf_by_address(iconf->info.name, NULL, NULL, ip, CONF_KILL, aftype, vuser, NULL); if(kconf) return kconf; diff --git a/src/newconf.c b/src/newconf.c index 782ed1aae..24749a833 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -902,8 +902,8 @@ conf_end_auth(struct TopConf *tc) rb_dlink_node *ptr; rb_dlink_node *next_ptr; - if(EmptyString(yy_aconf->name)) - yy_aconf->name = rb_strdup("NOMATCH"); + if(EmptyString(yy_aconf->info.name)) + yy_aconf->info.name = rb_strdup("NOMATCH"); /* didnt even get one ->host? */ if(EmptyString(yy_aconf->host)) @@ -937,7 +937,7 @@ conf_end_auth(struct TopConf *tc) yy_tmp->spasswd = rb_strdup(yy_aconf->spasswd); /* this will always exist.. */ - yy_tmp->name = rb_strdup(yy_aconf->name); + yy_tmp->info.name = rb_strdup(yy_aconf->info.name); if(yy_aconf->className) yy_tmp->className = rb_strdup(yy_aconf->className); @@ -1070,8 +1070,8 @@ conf_set_auth_spoof(void *data) return; } - rb_free(yy_aconf->name); - yy_aconf->name = rb_strdup(data); + rb_free(yy_aconf->info.name); + yy_aconf->info.name = rb_strdup(data); yy_aconf->flags |= CONF_FLAGS_SPOOF_IP; } @@ -1087,8 +1087,8 @@ static void conf_set_auth_redir_serv(void *data) { yy_aconf->flags |= CONF_FLAGS_REDIR; - rb_free(yy_aconf->name); - yy_aconf->name = rb_strdup(data); + rb_free(yy_aconf->info.name); + yy_aconf->info.name = rb_strdup(data); } static void diff --git a/src/operhash.c b/src/operhash.c new file mode 100644 index 000000000..5e416d0d7 --- /dev/null +++ b/src/operhash.c @@ -0,0 +1,130 @@ +/* ircd-ratbox: an advanced Internet Relay Chat Daemon(ircd). + * operhash.c - Hashes nick!user@host{oper} + * + * Copyright (C) 2005 Lee Hardy + * Copyright (C) 2005 ircd-ratbox development team + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1.Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2.Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3.The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $Id: operhash.c 26094 2008-09-19 15:33:46Z androsyn $ + */ +#include +#include "stdinc.h" +#include "match.h" +#include "hash.h" +#include "operhash.h" + +#define OPERHASH_MAX_BITS 7 +#define OPERHASH_MAX (1<data; + + if(!irccmp(ohash->name, name)) + { + ohash->refcount++; + return ohash->name; + } + } + + ohash = rb_malloc(sizeof(struct operhash_entry)); + ohash->refcount = 1; + ohash->name = rb_strdup(name); + + rb_dlinkAddAlloc(ohash, &operhash_table[hashv]); + + return ohash->name; +} + +const char * +operhash_find(const char *name) +{ + struct operhash_entry *ohash; + unsigned int hashv; + rb_dlink_node *ptr; + + if(EmptyString(name)) + return NULL; + + hashv = hash_opername(name); + + RB_DLINK_FOREACH(ptr, operhash_table[hashv].head) + { + ohash = ptr->data; + + if(!irccmp(ohash->name, name)) + return ohash->name; + } + + return NULL; +} + +void +operhash_delete(const char *name) +{ + struct operhash_entry *ohash; + unsigned int hashv; + rb_dlink_node *ptr; + + if(EmptyString(name)) + return; + + hashv = hash_opername(name); + + RB_DLINK_FOREACH(ptr, operhash_table[hashv].head) + { + ohash = ptr->data; + + if(irccmp(ohash->name, name)) + continue; + + ohash->refcount--; + + if(ohash->refcount == 0) + { + rb_free(ohash->name); + rb_free(ohash); + rb_dlinkDestroy(ptr, &operhash_table[hashv]); + return; + } + } +} diff --git a/src/s_conf.c b/src/s_conf.c index 9531e8351..ff87a309c 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -50,6 +50,7 @@ #include "privilege.h" #include "sslproc.h" #include "bandbi.h" +#include "operhash.h" struct config_server_hide ConfigServerHide; @@ -142,11 +143,15 @@ free_conf(struct ConfItem *aconf) rb_free(aconf->passwd); rb_free(aconf->spasswd); - rb_free(aconf->name); rb_free(aconf->className); rb_free(aconf->user); rb_free(aconf->host); + if(IsConfBan(aconf)) + operhash_delete(aconf->info.oper); + else + rb_free(aconf->info.name); + rb_bh_free(confitem_heap, aconf); } @@ -333,7 +338,7 @@ verify_access(struct Client *client_p, const char *username) if(aconf->flags & CONF_FLAGS_REDIR) { sendto_one_numeric(client_p, RPL_REDIR, form_str(RPL_REDIR), - aconf->name ? aconf->name : "", aconf->port); + aconf->info.name ? aconf->info.name : "", aconf->port); return (NOT_AUTHORISED); } @@ -350,24 +355,24 @@ verify_access(struct Client *client_p, const char *username) sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s spoofing: %s as %s", client_p->name, - show_ip(NULL, client_p) ? client_p->host : aconf->name, - aconf->name); + show_ip(NULL, client_p) ? client_p->host : aconf->info.name, + aconf->info.name); } /* user@host spoof */ - if((p = strchr(aconf->name, '@')) != NULL) + if((p = strchr(aconf->info.name, '@')) != NULL) { char *host = p+1; *p = '\0'; - rb_strlcpy(client_p->username, aconf->name, + rb_strlcpy(client_p->username, aconf->info.name, sizeof(client_p->username)); rb_strlcpy(client_p->host, host, sizeof(client_p->host)); *p = '@'; } else - rb_strlcpy(client_p->host, aconf->name, sizeof(client_p->host)); + rb_strlcpy(client_p->host, aconf->info.name, sizeof(client_p->host)); } return (attach_iline(client_p, aconf)); } @@ -1046,7 +1051,7 @@ get_printable_conf(struct ConfItem *aconf, char **name, char **host, static char null[] = ""; static char zero[] = "default"; - *name = EmptyString(aconf->name) ? null : aconf->name; + *name = EmptyString(aconf->info.name) ? null : aconf->info.name; *host = EmptyString(aconf->host) ? null : aconf->host; *pass = EmptyString(aconf->passwd) ? null : aconf->passwd; *user = EmptyString(aconf->user) ? null : aconf->user; diff --git a/src/s_user.c b/src/s_user.c index d8be934cc..d23a19335 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -336,7 +336,7 @@ register_local_user(struct Client *client_p, struct Client *source_p, const char } /* dont replace username if its supposed to be spoofed --fl */ - if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->name, '@')) + if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->info.name, '@')) { p = username;