#include "hash.h"
#include "ircd.h"
#include "ircd_alloc.h"
-#include "ircd_auth.h"
#include "ircd_chattr.h"
#include "ircd_log.h"
#include "ircd_reply.h"
#include "opercmds.h"
#include "parse.h"
#include "res.h"
+#include "s_auth.h"
#include "s_bsd.h"
#include "s_debug.h"
#include "s_misc.h"
aconf = (struct ConfItem*) MyMalloc(sizeof(struct ConfItem));
assert(0 != aconf);
-#ifdef DEBUGMODE
++GlobalConfCount;
-#endif
memset(aconf, 0, sizeof(struct ConfItem));
aconf->status = type;
aconf->next = GlobalConfList;
aconf->address.port));
if (aconf->dns_pending)
delete_resolver_queries(aconf);
+ MyFree(aconf->username);
MyFree(aconf->host);
+ MyFree(aconf->origin_name);
if (aconf->passwd)
memset(aconf->passwd, 0, strlen(aconf->passwd));
MyFree(aconf->passwd);
MyFree(aconf->name);
+ MyFree(aconf->hub_limit);
MyFree(aconf);
-#ifdef DEBUGMODE
--GlobalConfCount;
-#endif
}
/** Disassociate configuration from the client.
aconf->addrbits = addrbits;
else
aconf->addrbits = -1;
- MyFree(host);
}
/** Copies a completed DNS query into its ConfItem.
* @param vptr Pointer to struct ConfItem for the block.
* @param hp DNS reply, or NULL if the lookup failed.
*/
-static void conf_dns_callback(void* vptr, struct DNSReply* hp)
+static void conf_dns_callback(void* vptr, const struct irc_in_addr *addr, const char *h_name)
{
struct ConfItem* aconf = (struct ConfItem*) vptr;
assert(aconf);
aconf->dns_pending = 0;
- if (hp) {
- memcpy(&aconf->address.addr, &hp->addr, sizeof(aconf->address.addr));
- MyFree(hp);
- }
+ if (addr)
+ memcpy(&aconf->address.addr, addr, sizeof(aconf->address.addr));
}
/** Start a nameserver lookup of the conf host. If the conf entry is
{
if (!aconf->dns_pending) {
char buf[HOSTLEN + 1];
- struct DNSQuery query;
- query.vptr = aconf;
- query.callback = conf_dns_callback;
- host_from_uh(buf, aconf->host, HOSTLEN);
- buf[HOSTLEN] = '\0';
- gethost_byname(buf, &query);
+ host_from_uh(buf, aconf->host, HOSTLEN);
+ gethost_byname(buf, conf_dns_callback, aconf);
aconf->dns_pending = 1;
}
}
}
}
-/** Check client limits and attach Client block.
- * If there are more connections from the IP than \a aconf->maximum
- * allows, return ACR_TOO_MANY_FROM_IP. Otherwise, attach \a aconf to
- * \a cptr.
- * @param cptr Client getting \a aconf.
- * @param aconf Configuration item to attach.
- * @return Authorization check result.
- */
-static enum AuthorizationCheckResult
-check_limit_and_attach(struct Client* cptr, struct ConfItem* aconf)
-{
- if (IPcheck_nr(cptr) > aconf->maximum)
- return ACR_TOO_MANY_FROM_IP;
- return attach_conf(cptr, aconf);
-}
-
/** Find the first (best) Client block to attach.
* @param cptr Client for whom to check rules.
* @return Authorization check result.
enum AuthorizationCheckResult attach_iline(struct Client* cptr)
{
struct ConfItem* aconf;
- struct DNSReply* hp;
assert(0 != cptr);
- hp = cli_dns_reply(cptr);
for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
if (aconf->status != CONF_CLIENT)
continue;
*/
if (aconf->address.port && aconf->address.port != cli_listener(cptr)->addr.port)
continue;
- if (aconf->username) {
- SetFlag(cptr, FLAG_DOID);
- if (match(aconf->username, cli_username(cptr)))
- continue;
- }
- if (aconf->host && (!hp || match(aconf->host, hp->h_name)))
+ if (aconf->username && match(aconf->username, cli_username(cptr)))
+ continue;
+ if (aconf->host && match(aconf->host, cli_sockhost(cptr)))
continue;
if ((aconf->addrbits >= 0)
&& !ipmask_check(&cli_ip(cptr), &aconf->address.addr, aconf->addrbits))
continue;
- return check_limit_and_attach(cptr, aconf);
+ if (IPcheck_nr(cptr) > aconf->maximum)
+ return ACR_TOO_MANY_FROM_IP;
+ if (aconf->username)
+ SetFlag(cptr, FLAG_DOID);
+ return attach_conf(cptr, aconf);
}
return ACR_NO_AUTHORIZATION;
}
{
struct irc_in_addr address;
struct ConfItem *aconf;
+ struct DenyConf *deny;
char *sep;
unsigned short listener;
- char username[USERLEN+1], hostname[HOSTLEN+1];
+ char username[USERLEN+1], hostname[HOSTLEN+1], realname[REALLEN+1];
/* Initialize variables. */
listener = 0;
memset(&address, 0, sizeof(address));
memset(&username, 0, sizeof(username));
memset(&hostname, 0, sizeof(hostname));
+ memset(&realname, 0, sizeof(realname));
/* Parse client specifier. */
while (*client) {
continue;
}
+ /* Realname? */
+ if (client[0] == '$' && client[1] == 'R') {
+ client += 2;
+ for (tmp = 0; *client != '\0' && *client != ',' && tmp < REALLEN; ++client, ++tmp) {
+ if (*client == '\\')
+ realname[tmp] = *++client;
+ else
+ realname[tmp] = *client;
+ }
+ continue;
+ }
+
/* Else must be a hostname. */
tmp = strcspn(client, ",");
if (tmp > HOSTLEN)
(aconf->username ? aconf->username : "(null)"),
(aconf->host ? aconf->host : "(null)"),
(aconf->name ? aconf->name : "(null)"),
- ConfClass(aconf), aconf->maximum, aconf->passwd);
- return aconf;
+ ConfClass(aconf), aconf->maximum,
+ (aconf->passwd ? aconf->passwd : "(null)"));
+ break;
}
- fprintf(stdout, "No matches found.\n");
- return NULL;
+ /* If no authorization, say so and exit. */
+ if (!aconf)
+ {
+ fprintf(stdout, "No authorization found.\n");
+ return NULL;
+ }
+
+ /* Look for a Kill block with the user's name on it. */
+ for (deny = denyConfList; deny; deny = deny->next) {
+ if (deny->usermask && match(deny->usermask, username))
+ continue;
+ if (deny->realmask && match(deny->realmask, realname))
+ continue;
+ if (deny->bits > 0) {
+ if (!ipmask_check(&address, &deny->address, deny->bits))
+ continue;
+ } else if (deny->hostmask && match(deny->hostmask, hostname))
+ continue;
+
+ /* Looks like a match; report it. */
+ fprintf(stdout, "Denied! usermask=%s realmask=\"%s\" hostmask=%s (bits=%u)\n",
+ deny->usermask ? deny->usermask : "(null)",
+ deny->realmask ? deny->realmask : "(null)",
+ deny->hostmask ? deny->hostmask : "(null)",
+ deny->bits);
+ }
+
+ return aconf;
}
/** Check whether a particular ConfItem is already attached to a
else if (!ipmask_check(&cli_ip(cptr), &tmp->address.addr, tmp->addrbits))
continue;
if ((tmp->status & CONF_OPERATOR)
+ && (MaxLinks(tmp->conn_class) > 0)
&& (tmp->clients >= MaxLinks(tmp->conn_class)))
continue;
return tmp;
MyFree(p->hostmask);
MyFree(p->usermask);
MyFree(p->message);
+ MyFree(p->realmask);
MyFree(p);
}
denyConfList = 0;
static int conf_error;
/** When non-zero, indicates that the configuration file was loaded at least once. */
static int conf_already_read;
-extern FILE *yyin;
extern void yyparse(void);
-extern void init_lexer(void);
+extern int init_lexer(void);
+extern void deinit_lexer(void);
/** Read configuration file.
* @return Zero on failure, non-zero on success. */
{
conf_error = 0;
feature_unmark(); /* unmark all features for resetting later */
- /* Now just open an fd. The buffering isn't really needed... */
- init_lexer();
+ clear_nameservers(); /* clear previous list of DNS servers */
+ if (!init_lexer())
+ return 0;
yyparse();
- fclose(yyin);
- yyin = NULL;
+ deinit_lexer();
feature_mark(); /* reset unmarked features */
conf_already_read = 1;
return 1;
attach_conf_uworld(lp->value.cptr);
}
+/** Free all memory associated with service mapping \a smap.
+ * @param smap[in] The mapping to free.
+ */
+void free_mapping(struct s_map *smap)
+{
+ struct nick_host *nh, *next;
+ for (nh = smap->services; nh; nh = next)
+ {
+ next = nh->next;
+ MyFree(nh);
+ }
+ MyFree(smap->name);
+ MyFree(smap->command);
+ MyFree(smap->prepend);
+ MyFree(smap);
+}
+
+/** Unregister and free all current service mappings. */
+static void close_mappings(void)
+{
+ struct s_map *map, *next;
+
+ for (map = GlobalServiceMapList; map; map = next) {
+ next = map->next;
+ unregister_mapping(map);
+ free_mapping(map);
+ }
+ GlobalServiceMapList = NULL;
+}
+
/** Reload the configuration file.
* @param cptr Client that requested rehash (if a signal, &me).
* @param sig Type of rehash (0 = oper-requested, 1 = signal, 2 =
clear_quarantines();
- if (sig != 2)
- restart_resolver();
-
class_mark_delete();
mark_listeners_closing();
- iauth_mark_closing();
+ auth_mark_closing();
+ close_mappings();
read_configuration_file();
+ if (sig != 2)
+ restart_resolver();
+
log_reopen(); /* reopen log files */
- iauth_close_unused();
+ auth_close_unused();
close_listeners();
class_delete_marked(); /* unless it fails */
* -- Isomer
*/
for (deny = denyConfList; deny; deny = deny->next) {
- if (0 != match(deny->usermask, name))
+ if (deny->usermask && match(deny->usermask, name))
+ continue;
+ if (deny->realmask && match(deny->realmask, realname))
+ continue;
+ if (deny->bits > 0) {
+ if (!ipmask_check(&cli_ip(cptr), &deny->address, deny->bits))
+ continue;
+ } else if (deny->hostmask && match(deny->hostmask, host))
continue;
- if (EmptyString(deny->hostmask))
- break;
-
- if (deny->flags & DENY_FLAGS_REALNAME) { /* K: by real name */
- if (0 == match(deny->hostmask + 2, realname))
- break;
- } else if (deny->flags & DENY_FLAGS_IP) { /* k: by IP */
-#ifdef DEBUGMODE
- char tbuf1[SOCKIPLEN], tbuf2[SOCKIPLEN];
- Debug((DEBUG_DEBUG, "ip: %s network: %s/%u",
- ircd_ntoa_r(tbuf1, &cli_ip(cptr)), ircd_ntoa_r(tbuf2, &deny->address), deny->bits));
-#endif
- if (ipmask_check(&cli_ip(cptr), &deny->address, deny->bits))
- break;
- }
- else if (0 == match(deny->hostmask, host))
- break;
- }
- if (deny) {
if (EmptyString(deny->message))
send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
":Connection from your host is refused on this server.");
else
send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", deny->message);
}
+ return -1;
}
- else if ((agline = gline_lookup(cptr, 0))) {
+
+ if (!feature_bool(FEAT_DISABLE_GLINES) && (agline = gline_lookup(cptr, 0))) {
/*
* find active glines
* added a check against the user's IP address to find_gline() -Kev
*/
send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", GlineReason(agline));
- }
-
- if (deny)
- return -1;
- if (agline)
return -2;
+ }
return 0;
}
if (IsConnecting(cptr) || IsHandshake(cptr)) {
c_conf = find_conf_byname(lp, cli_name(cptr), CONF_SERVER);
if (!c_conf) {
- sendto_opmask_butone(0, SNO_OLDSNO, "Connect Error: lost C:line for %s",
+ sendto_opmask_butone(0, SNO_OLDSNO,
+ "Connect Error: lost Connect block for %s",
cli_name(cptr));
det_confs_butmask(cptr, 0);
return -1;
}
}
- if (!c_conf) {
- if (cli_dns_reply(cptr)) {
- struct DNSReply* hp = cli_dns_reply(cptr);
- const char* name = hp->h_name;
- /*
- * If we are missing a C or N line from above, search for
- * it under all known hostnames we have for this ip#.
- */
- if ((c_conf = find_conf_byhost(lp, hp->h_name, CONF_SERVER)))
- ircd_strncpy(cli_sockhost(cptr), name, HOSTLEN);
- else
- c_conf = find_conf_byip(lp, &hp->addr, CONF_SERVER);
- }
- else {
- /*
- * Check for C lines with the hostname portion the ip number
- * of the host the server runs on. This also checks the case where
- * there is a server connecting from 'localhost'.
- */
- c_conf = find_conf_byhost(lp, cli_sockhost(cptr), CONF_SERVER);
- }
- }
+ /* Try finding the Connect block by DNS name and IP next. */
+ if (!c_conf && !(c_conf = find_conf_byhost(lp, cli_sockhost(cptr), CONF_SERVER)))
+ c_conf = find_conf_byip(lp, &cli_ip(cptr), CONF_SERVER);
+
/*
* Attach by IP# only if all other checks have failed.
* It is quite possible to get here with the strange things that can