/* apply_tdline() * * inputs - * output - NONE * side effects - tkline as given is placed */ static void apply_dline(struct Client *source_p, struct MaskItem *conf, time_t tkline_time) { if (tkline_time) { conf->until = CurrentTime + tkline_time; sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s added temporary %d min. D-Line for [%s] [%s]", get_oper_name(source_p), tkline_time/60, conf->host, conf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. D-Line [%s]", MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from), source_p->name, tkline_time/60, conf->host); ilog(LOG_TYPE_DLINE, "%s added temporary %d min. D-Line for [%s] [%s]", get_oper_name(source_p), tkline_time/60, conf->host, conf->reason); } else { sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), conf->host, conf->reason); sendto_one(source_p, ":%s NOTICE %s :Added D-Line [%s]", MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from), source_p->name, conf->host); ilog(LOG_TYPE_DLINE, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), conf->host, conf->reason); } SetConfDatabase(conf); conf->setat = CurrentTime; add_conf_by_address(CONF_DLINE, conf); rehashed_klines = 1; }
void parse_k_file(FBFILE *file) { struct ConfItem *aconf; char* user_field=(char *)NULL; char* reason_field=(char *)NULL; char* host_field=(char *)NULL; char line[BUFSIZE]; char* p; while (fbgets(line, sizeof(line), file)) { if ((p = strchr(line, '\n')) != NULL) *p = '\0'; if ((*line == '\0') || (*line == '#')) continue; if ((user_field = getfield(line)) == NULL) continue; if ((host_field = getfield(NULL)) == NULL) continue; if ((reason_field = getfield(NULL)) == NULL) continue; aconf = make_conf(); aconf->status = CONF_KILL; conf_add_fields(aconf,host_field,reason_field,user_field,0,NULL); if (aconf->host != NULL) add_conf_by_address(aconf->host, CONF_KILL, aconf->user, aconf); } }
void parse_k_file(FILE * file) { struct ConfItem *aconf; char *user_field = NULL; char *reason_field = NULL; char *operreason_field = NULL; char *host_field = NULL; char line[BUFSIZE]; char *p; while (fgets(line, sizeof(line), file)) { if((p = strpbrk(line, "\r\n")) != NULL) *p = '\0'; if((*line == '\0') || (*line == '#')) continue; user_field = getfield(line); if(EmptyString(user_field)) continue; host_field = getfield(NULL); if(EmptyString(host_field)) continue; reason_field = getfield(NULL); if(EmptyString(reason_field)) continue; operreason_field = getfield(NULL); aconf = make_conf(); aconf->status = CONF_KILL; conf_add_fields(aconf, host_field, reason_field, user_field, operreason_field); if(aconf->host != NULL) add_conf_by_address(aconf->host, CONF_KILL, aconf->user, aconf); } }
/* ms_ban() * * parv[1] - type * parv[2] - username mask or * * parv[3] - hostname mask * parv[4] - creation TS * parv[5] - duration (relative to creation) * parv[6] - lifetime (relative to creation) * parv[7] - oper or * * parv[8] - reason (possibly with |operreason) */ static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { rb_dlink_node *ptr; struct ConfItem *aconf; unsigned int ntype; const char *oper, *stype; time_t now, created, hold, lifetime; char *p; int act; int valid; now = rb_current_time(); if (strlen(parv[1]) != 1) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", parv[1], source_p->name); return 0; } switch (parv[1][0]) { case 'K': ntype = CONF_KILL; stype = "K-Line"; break; case 'X': ntype = CONF_XLINE; stype = "X-Line"; break; case 'R': ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL : CONF_RESV_NICK; stype = "RESV"; break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", parv[1], source_p->name); return 0; } created = atol(parv[4]); hold = created + atoi(parv[5]); lifetime = created + atoi(parv[6]); if (!strcmp(parv[7], "*")) oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p); else oper = parv[7]; ptr = find_prop_ban(ntype, parv[2], parv[3]); if (ptr != NULL) { /* We already know about this ban mask. */ aconf = ptr->data; if (aconf->created > created || (aconf->created == created && aconf->lifetime >= lifetime)) { if (IsPerson(source_p)) sendto_one_notice(source_p, ":Your %s [%s%s%s] has been superseded", stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); return 0; } /* act indicates if something happened (from the oper's * point of view). This is the case if the ban was * previously active (not deleted) or if the new ban * is not a removal and not already expired. */ act = !(aconf->status & CONF_ILLEGAL) || (hold != created && hold > now); if (lifetime > aconf->lifetime) aconf->lifetime = lifetime; /* already expired, hmm */ if (aconf->lifetime <= now) return 0; /* Deactivate, it will be reactivated later if appropriate. */ deactivate_conf(aconf, ptr, now); rb_free(aconf->user); aconf->user = NULL; rb_free(aconf->host); aconf->host = NULL; operhash_delete(aconf->info.oper); aconf->info.oper = NULL; rb_free(aconf->passwd); aconf->passwd = NULL; rb_free(aconf->spasswd); aconf->spasswd = NULL; } else { /* New ban mask. */ aconf = make_conf(); aconf->status = CONF_ILLEGAL | ntype; aconf->lifetime = lifetime; rb_dlinkAddAlloc(aconf, &prop_bans); act = hold != created && hold > now; } aconf->flags &= ~CONF_FLAGS_MYOPER; aconf->flags |= CONF_FLAGS_TEMPORARY; aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL; aconf->host = rb_strdup(parv[3]); aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) aconf->passwd = rb_strdup(parv[parc - 1]); else { aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } /* The ban is fully filled in and in the prop_bans list * but still deactivated. Now determine if it should be activated * and send the server notices. */ /* We only reject *@* and the like here. * Otherwise malformed bans are fairly harmless and can be removed. */ switch (ntype) { case CONF_KILL: valid = valid_wild_card(aconf->user, aconf->host); break; case CONF_RESV_CHANNEL: valid = 1; break; default: valid = valid_wild_card_simple(aconf->host); break; } if (act && hold != created && !valid) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", (int)((hold - now) / 60), stype, IsServer(source_p) ? source_p->name : get_oper_name(source_p), strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : "", aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); if(IsPerson(source_p)) sendto_one_notice(source_p, ":Your %s [%s%s%s] has too few non-wildcard characters", stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); /* Propagate it, but do not apply it locally. */ } else if (act && hold != created) { /* Keep the notices in sync with modules/m_kline.c etc. */ sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. %s%s%s for [%s%s%s] [%s]", IsServer(source_p) ? source_p->name : get_oper_name(source_p), (int)((hold - now) / 60), stype, strcmp(parv[7], "*") ? " from " : "", strcmp(parv[7], "*") ? parv[7] : "", aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, parv[parc - 1]); ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), (int)((hold - now) / 60), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host, parv[parc - 1]); aconf->status &= ~CONF_ILLEGAL; } else if (act) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the global %s for: [%s%s%s]%s%s", IsServer(source_p) ? source_p->name : get_oper_name(source_p), stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : ""); ilog(L_KLINE, "U%s %s %s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host); } /* If CONF_ILLEGAL is still set at this point, remove entries from the * reject cache (for klines and xlines). * If CONF_ILLEGAL is not set, add the ban to the type-specific data * structure and take action on matched clients/channels. */ switch (ntype) { case CONF_KILL: if (aconf->status & CONF_ILLEGAL) remove_reject_mask(aconf->user, aconf->host); else { add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); if(ConfigFileEntry.kline_delay || (IsServer(source_p) && !HasSentEob(source_p))) { if(kline_queued == 0) { rb_event_addonce("check_klines", check_klines_event, NULL, ConfigFileEntry.kline_delay ? ConfigFileEntry.kline_delay : 1); kline_queued = 1; } } else check_klines(); } break; case CONF_XLINE: if (aconf->status & CONF_ILLEGAL) remove_reject_mask(aconf->host, NULL); else { rb_dlinkAddAlloc(aconf, &xline_conf_list); check_xlines(); } break; case CONF_RESV_CHANNEL: if (!(aconf->status & CONF_ILLEGAL)) { add_to_resv_hash(aconf->host, aconf); resv_chan_forcepart(aconf->host, aconf->passwd, hold - now); } break; case CONF_RESV_NICK: if (!(aconf->status & CONF_ILLEGAL)) rb_dlinkAddAlloc(aconf, &resv_conf_list); break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", source_p->id, parv[1], parv[2], parv[3], parv[4], parv[5], parv[6], parv[7], parv[parc - 1]); return 0; }
/* parse_csv_file() * * inputs - FILE pointer * - type of conf to parse * output - none * side effects - */ void parse_csv_file(FBFILE *file, ConfType conf_type) { struct ConfItem *conf; struct AccessItem *aconf; struct MatchItem *match_item; struct MatchItem *nresv; struct ResvChannel *cresv; char *name_field=NULL; char *user_field=NULL; char *reason_field=NULL; char *oper_reason=NULL; char *host_field=NULL; char *duration_field=NULL; char *temp=NULL; char line[IRCD_BUFSIZE]; char *p; while (fbgets(line, sizeof(line), file) != NULL) { duration_field = NULL; if ((p = strchr(line, '\n')) != NULL) *p = '\0'; if ((line[0] == '\0') || (line[0] == '#')) continue; switch(conf_type) { case KLINE_TYPE: parse_csv_line(line, &user_field, &host_field, &reason_field, &oper_reason, &temp, &temp, &temp, &duration_field, NULL); conf = make_conf_item(KLINE_TYPE); aconf = map_to_conf(conf); if (host_field != NULL) DupString(aconf->host, host_field); if (reason_field != NULL) DupString(aconf->reason, reason_field); if (oper_reason != NULL) DupString(aconf->oper_reason, oper_reason); if (user_field != NULL) DupString(aconf->user, user_field); if (duration_field != NULL) aconf->hold = atoi(duration_field); if (aconf->host != NULL) { if(duration_field == NULL) add_conf_by_address(CONF_KILL, aconf); else add_temp_line(conf); } break; case RKLINE_TYPE: { const char *errptr = NULL; pcre *exp_user = NULL, *exp_host = NULL; parse_csv_line(line, &user_field, &host_field, &reason_field, &oper_reason, &temp, &temp, &temp, &duration_field, NULL); if (host_field == NULL || user_field == NULL) break; if (!(exp_user = ircd_pcre_compile(user_field, &errptr)) || !(exp_host = ircd_pcre_compile(host_field, &errptr))) { sendto_realops_flags(UMODE_ALL, L_ALL, "Failed to add regular expression based K-Line: %s", errptr); break; } conf = make_conf_item(RKLINE_TYPE); aconf = map_to_conf(conf); aconf->regexuser = exp_user; aconf->regexhost = exp_host; DupString(aconf->user, user_field); DupString(aconf->host, host_field); if (reason_field != NULL) DupString(aconf->reason, reason_field); else DupString(aconf->reason, "No reason"); if (oper_reason != NULL) DupString(aconf->oper_reason, oper_reason); if(duration_field != NULL) { aconf->hold = atoi(duration_field); add_temp_line(conf); } } break; case DLINE_TYPE: parse_csv_line(line, &host_field, &reason_field, &temp, &temp, &temp, &temp, &duration_field, NULL); conf = make_conf_item(DLINE_TYPE); aconf = (struct AccessItem *)map_to_conf(conf); if (host_field != NULL) DupString(aconf->host, host_field); if (reason_field != NULL) DupString(aconf->reason, reason_field); if(duration_field != NULL) { aconf->hold = atoi(duration_field); add_temp_line(conf); } else conf_add_d_conf(aconf); break; case XLINE_TYPE: parse_csv_line(line, &name_field, &reason_field, &oper_reason, &temp, &temp, &temp, &temp, &duration_field, NULL); conf = make_conf_item(XLINE_TYPE); match_item = (struct MatchItem *)map_to_conf(conf); if (name_field != NULL) DupString(conf->name, name_field); if (reason_field != NULL) DupString(match_item->reason, reason_field); if(duration_field != NULL) { match_item->hold = atoi(duration_field); add_temp_line(conf); } break; case RXLINE_TYPE: { const char *errptr = NULL; pcre *exp_p = NULL; parse_csv_line(line, &name_field, &reason_field, &oper_reason, &temp, &temp, &temp, &temp, &duration_field, NULL); if (name_field == NULL) break; if (!(exp_p = ircd_pcre_compile(name_field, &errptr))) { sendto_realops_flags(UMODE_ALL, L_ALL, "Failed to add regular expression based X-Line: %s", errptr); break; } conf = make_conf_item(RXLINE_TYPE); conf->regexpname = exp_p; match_item = map_to_conf(conf); DupString(conf->name, name_field); if (reason_field != NULL) DupString(match_item->reason, reason_field); else DupString(match_item->reason, "No reason"); if(duration_field != NULL) { match_item->hold = atoi(duration_field); add_temp_line(conf); } } break; case CRESV_TYPE: parse_csv_line(line, &name_field, &reason_field, &duration_field, NULL); conf = create_channel_resv(name_field, reason_field, 0); if(duration_field != NULL) { cresv = map_to_conf(conf); cresv->hold = atoi(duration_field); add_temp_line(conf); } break; case NRESV_TYPE: parse_csv_line(line, &name_field, &reason_field, &duration_field, NULL); conf = create_nick_resv(name_field, reason_field, 0); if(duration_field != NULL) { nresv = map_to_conf(conf); nresv->hold = atoi(duration_field); add_temp_line(conf); } break; case GLINE_TYPE: case GDENY_TYPE: case CONF_TYPE: case OPER_TYPE: case CLIENT_TYPE: case SERVER_TYPE: case CLUSTER_TYPE: case HUB_TYPE: case LEAF_TYPE: case ULINE_TYPE: case EXEMPTDLINE_TYPE: case CLASS_TYPE: break; } } }