X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/d19aab337593dfa3288d6f80f079db8ebbe4b97e..9dd98618d044c63ba4d30c79350f4b6a4a2c3453:/ircd/client.c diff --git a/ircd/client.c b/ircd/client.c index 312df13f..f9336b3d 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -1,11 +1,11 @@ /* - * charybdis: an advanced ircd. + * Solanum: a slightly advanced ircd * client.c: Controls clients. * * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 2002-2005 ircd-ratbox development team - * Copyright (C) 2007 William Pitcock + * Copyright (C) 2007 Ariadne Conill * * 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 @@ -80,12 +80,6 @@ static uint32_t current_connid = 0; rb_dictionary *nd_dict = NULL; -enum -{ - D_LINED, - K_LINED -}; - rb_dlink_list dead_list; #ifdef DEBUG_EXITED_CLIENTS static rb_dlink_list dead_remote_list; @@ -140,8 +134,8 @@ init_client(void) uint32_t connid_get(struct Client *client_p) { - s_assert(MyClient(client_p)); - if (!MyClient(client_p)) + s_assert(MyConnect(client_p)); + if (!MyConnect(client_p)) return 0; /* find a connid that is available */ @@ -194,8 +188,10 @@ client_release_connids(struct Client *client_p) { rb_dlink_node *ptr, *ptr2; - s_assert(MyClient(client_p)); - if (!MyClient(client_p)) + if (client_p->localClient->connids.head) + s_assert(MyConnect(client_p)); + + if (!MyConnect(client_p)) return; RB_DLINK_FOREACH_SAFE(ptr, ptr2, client_p->localClient->connids.head) @@ -245,7 +241,7 @@ make_client(struct Client *from) } SetUnknown(client_p); - strcpy(client_p->username, "unknown"); + rb_strlcpy(client_p->username, "unknown", sizeof(client_p->username)); return client_p; } @@ -304,16 +300,12 @@ free_local_client(struct Client *client_p) rb_free(client_p->localClient->auth_user); rb_free(client_p->localClient->challenge); rb_free(client_p->localClient->fullcaps); - rb_free(client_p->localClient->opername); rb_free(client_p->localClient->mangledhost); - if (client_p->localClient->privset) - privilegeset_unref(client_p->localClient->privset); if (IsSSL(client_p)) ssld_decrement_clicount(client_p->localClient->ssl_ctl); - if (IsCapable(client_p, CAP_ZIP)) - ssld_decrement_clicount(client_p->localClient->z_ctl); + rb_free(client_p->localClient->cipher_string); if (client_p->localClient->ws_ctl != NULL) wsockd_decrement_clicount(client_p->localClient->ws_ctl); @@ -322,7 +314,7 @@ free_local_client(struct Client *client_p) client_p->localClient = NULL; } -void +static void free_client(struct Client *client_p) { s_assert(NULL != client_p); @@ -402,7 +394,7 @@ check_pings_list(rb_dlink_list * list) { if(IsServer(client_p)) { - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "No response from %s, closing link", client_p->name); ilog(L_SERVER, @@ -469,7 +461,7 @@ check_unknowns_list(rb_dlink_list * list) { if(IsAnyServer(client_p)) { - sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "No response from %s, closing link", client_p->name); ilog(L_SERVER, @@ -481,7 +473,7 @@ check_unknowns_list(rb_dlink_list * list) } } -static void +void notify_banned_client(struct Client *client_p, struct ConfItem *aconf, int ban) { static const char conn_closed[] = "Connection closed"; @@ -526,19 +518,6 @@ check_banned_lines(void) check_xlines(); } -/* check_klines_event() - * - * inputs - - * outputs - - * side effects - check_klines() is called, kline_queued unset - */ -void -check_klines_event(void *unused) -{ - kline_queued = false; - check_klines(); -} - /* check_klines * * inputs - @@ -564,16 +543,16 @@ check_klines(void) { if(IsExemptKline(client_p)) { - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "KLINE over-ruled for %s, client is kline_exempt [%s@%s]", get_client_name(client_p, HIDE_IP), aconf->user, aconf->host); continue; } - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "KLINE active for %s", - get_client_name(client_p, HIDE_IP)); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Disconnecting K-Lined user %s (%s@%s)", + get_client_name(client_p, HIDE_IP), aconf->user, aconf->host); notify_banned_client(client_p, aconf, K_LINED); continue; @@ -581,6 +560,88 @@ check_klines(void) } } + +/* check_one_kline() + * + * This process needs to be kept in sync with find_kline() aka find_conf_by_address(). + * + * inputs - pointer to kline to check + * outputs - + * side effects - all clients will be checked against given kline + */ +void +check_one_kline(struct ConfItem *kline) +{ + struct Client *client_p; + rb_dlink_node *ptr; + rb_dlink_node *next_ptr; + int masktype; + int bits; + struct rb_sockaddr_storage sockaddr; + struct sockaddr_in ip4; + + masktype = parse_netmask(kline->host, (struct sockaddr_storage *)&sockaddr, &bits); + + RB_DLINK_FOREACH_SAFE(ptr, next_ptr, lclient_list.head) + { + int matched = 0; + + client_p = ptr->data; + + if(IsMe(client_p) || !IsPerson(client_p)) + continue; + + if(!match(kline->user, client_p->username)) + continue; + + /* match one kline */ + switch (masktype) { + case HM_IPV4: + case HM_IPV6: + if (IsConfDoSpoofIp(client_p->localClient->att_conf) && + IsConfKlineSpoof(client_p->localClient->att_conf)) + break; + if (client_p->localClient->ip.ss_family == AF_INET6 && sockaddr.ss_family == AF_INET && + rb_ipv4_from_ipv6((struct sockaddr_in6 *)&client_p->localClient->ip, &ip4) + && comp_with_mask_sock((struct sockaddr *)&ip4, (struct sockaddr *)&sockaddr, bits)) + matched = 1; + else if (client_p->localClient->ip.ss_family == sockaddr.ss_family && + comp_with_mask_sock((struct sockaddr *)&client_p->localClient->ip, + (struct sockaddr *)&sockaddr, bits)) + matched = 1; + break; + case HM_HOST: + if (match(kline->host, client_p->orighost)) + matched = 1; + if (IsConfDoSpoofIp(client_p->localClient->att_conf) && + IsConfKlineSpoof(client_p->localClient->att_conf)) + break; + if (match(kline->host, client_p->sockhost)) + matched = 1; + break; + } + + if (!matched) + continue; + + if(IsExemptKline(client_p)) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "KLINE over-ruled for %s, client is kline_exempt [%s@%s]", + get_client_name(client_p, HIDE_IP), + kline->user, kline->host); + continue; + } + + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Disconnecting K-Lined user %s (%s@%s)", + get_client_name(client_p, HIDE_IP), kline->user, kline->host); + + notify_banned_client(client_p, kline, K_LINED); + } +} + + /* check_dlines() * * inputs - @@ -607,9 +668,9 @@ check_dlines(void) if(aconf->status & CONF_EXEMPTDLINE) continue; - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "DLINE active for %s", - get_client_name(client_p, HIDE_IP)); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Disconnecting D-Lined user %s (%s)", + get_client_name(client_p, HIDE_IP), aconf->host); notify_banned_client(client_p, aconf, D_LINED); continue; @@ -656,15 +717,16 @@ check_xlines(void) { if(IsExemptKline(client_p)) { - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "XLINE over-ruled for %s, client is kline_exempt [%s]", get_client_name(client_p, HIDE_IP), aconf->host); continue; } - sendto_realops_snomask(SNO_GENERAL, L_ALL, "XLINE active for %s", - get_client_name(client_p, HIDE_IP)); + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Disconnecting X-Lined user %s (%s)", + get_client_name(client_p, HIDE_IP), aconf->host); (void) exit_client(client_p, client_p, &me, "Bad user info"); continue; @@ -706,11 +768,11 @@ resv_nick_fnc(const char *mask, const char *reason, int temp_time) nick = client_p->id; /* Tell opers. */ - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "RESV forced nick change for %s!%s@%s to %s; nick matched [%s] (%s)", client_p->name, client_p->username, client_p->host, nick, mask, reason); - sendto_realops_snomask(SNO_NCHANGE, L_ALL, + sendto_realops_snomask(SNO_NCHANGE, L_NETWIDE, "Nick change: From %s to %s [%s@%s]", client_p->name, nick, client_p->username, client_p->host); @@ -1081,7 +1143,7 @@ free_exited_clients(void *unused) target_p->name, (unsigned int) target_p->status, (unsigned long long)target_p->flags, target_p->handler); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Please report this to the charybdis developers!"); + "Please report this to the solanum developers!"); found++; } } @@ -1225,7 +1287,7 @@ exit_aborted_clients(void *unused) abt->client->name, (unsigned int) abt->client->status, (unsigned long long)abt->client->flags, abt->client->handler); sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Please report this to the charybdis developers!"); + "Please report this to the solanum developers!"); continue; } } @@ -1235,7 +1297,7 @@ exit_aborted_clients(void *unused) rb_dlinkDelete(ptr, &abort_list); if(IsAnyServer(abt->client)) - sendto_realops_snomask(SNO_GENERAL, L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Closing link to %s: %s", abt->client->name, abt->notice); @@ -1352,10 +1414,18 @@ exit_remote_client(struct Client *client_p, struct Client *source_p, struct Clie */ static int -exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Client *from, - const char *comment) +exit_unknown_client(struct Client *client_p, /* The local client originating the + * exit or NULL, if this exit is + * generated by this server for + * internal reasons. + * This will not get any of the + * generated messages. */ + struct Client *source_p, /* Client exiting */ + struct Client *from, /* Client firing off this Exit, + * never NULL! */ + const char *comment) { - authd_abort_client(client_p); + authd_abort_client(source_p); rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list); if(!IsIOError(source_p)) @@ -1369,7 +1439,8 @@ exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Cli del_from_id_hash(source_p->id, source_p); del_from_hostname_hash(source_p->host, source_p); - del_from_client_hash(source_p->name, source_p); + if (!IsAnyServer(source_p)) + del_from_client_hash(source_p->name, source_p); remove_client_from_list(source_p); SetDead(source_p); rb_dlinkAddAlloc(source_p, &dead_list); @@ -1398,13 +1469,9 @@ exit_remote_server(struct Client *client_p, struct Client *source_p, struct Clie snprintf(newcomment, sizeof(newcomment), "by %s: %s", from->name, comment); - if(source_p->serv != NULL) - remove_dependents(client_p, source_p, from, IsPerson(from) ? newcomment : comment, comment1); + remove_dependents(client_p, source_p, from, IsPerson(from) ? newcomment : comment, comment1); - if(source_p->servptr && source_p->servptr->serv) - rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers); - else - s_assert(0); + rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers); rb_dlinkFindDestroy(source_p, &global_serv_list); target_p = source_p->from; @@ -1422,6 +1489,7 @@ exit_remote_server(struct Client *client_p, struct Client *source_p, struct Clie del_from_client_hash(source_p->name, source_p); remove_client_from_list(source_p); + scache_split(source_p->serv->nameinfo); SetDead(source_p); @@ -1614,6 +1682,8 @@ exit_client(struct Client *client_p, /* The local client originating the const char *comment /* Reason for the exit */ ) { + int ret = -1; + hook_data_client_exit hdata; if(IsClosing(source_p)) return -1; @@ -1634,23 +1704,25 @@ exit_client(struct Client *client_p, /* The local client originating the { /* Local clients of various types */ if(IsPerson(source_p)) - return exit_local_client(client_p, source_p, from, comment); + ret = exit_local_client(client_p, source_p, from, comment); else if(IsServer(source_p)) - return exit_local_server(client_p, source_p, from, comment); + ret = exit_local_server(client_p, source_p, from, comment); /* IsUnknown || IsConnecting || IsHandShake */ else if(!IsReject(source_p)) - return exit_unknown_client(client_p, source_p, from, comment); + ret = exit_unknown_client(client_p, source_p, from, comment); } else { /* Remotes */ if(IsPerson(source_p)) - return exit_remote_client(client_p, source_p, from, comment); + ret = exit_remote_client(client_p, source_p, from, comment); else if(IsServer(source_p)) - return exit_remote_server(client_p, source_p, from, comment); + ret = exit_remote_server(client_p, source_p, from, comment); } - return -1; + call_hook(h_after_client_exit, NULL); + + return ret; } /* @@ -1757,11 +1829,11 @@ show_ip(struct Client *source_p, struct Client *target_p) * to local opers. */ if(!ConfigFileEntry.hide_spoof_ips && - (source_p == NULL || MyOper(source_p))) + (source_p == NULL || HasPrivilege(source_p, "auspex:hostname"))) return 1; return 0; } - else if(IsDynSpoof(target_p) && (source_p != NULL && !IsOper(source_p))) + else if(IsDynSpoof(target_p) && (source_p != NULL && !HasPrivilege(source_p, "auspex:hostname"))) return 0; else return 1; @@ -1855,6 +1927,9 @@ free_user(struct User *user, struct Client *client_p) { if(user->away) rb_free((char *) user->away); + rb_free(user->opername); + if (user->privset) + privilegeset_unref(user->privset); /* * sanity check */ @@ -2056,7 +2131,7 @@ error_exit_client(struct Client *client_p, int error) { if(error == 0) { - sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) && !IsServer(client_p) ? L_NETWIDE : L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Server %s closed the connection", client_p->name); @@ -2065,7 +2140,7 @@ error_exit_client(struct Client *client_p, int error) } else { - sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) && !IsServer(client_p) ? L_NETWIDE : L_ALL, + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Lost connection to %s: %s", client_p->name, strerror(current_error)); ilog(L_SERVER, "Lost connection to %s: %s",