X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/d3455e2c7e2f9040e1b7628d9cf52b26a24dcefc..50aa2dd31d070cbad762c1aedb46d544b53376f3:/modules/m_xline.c diff --git a/modules/m_xline.c b/modules/m_xline.c index fb615ad..edda41e 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -42,8 +42,7 @@ #include "logger.h" #include "s_serv.h" #include "whowas.h" -#include "irc_string.h" -#include "sprintf_irc.h" +#include "match.h" #include "hash.h" #include "msg.h" #include "parse.h" @@ -71,7 +70,8 @@ struct Message unxline_msgtab = { mapi_clist_av1 xline_clist[] = { &xline_msgtab, &unxline_msgtab, NULL }; DECLARE_MODULE_AV1(xline, NULL, NULL, xline_clist, NULL, NULL, "$Revision: 3161 $"); -static int valid_xline(struct Client *, const char *, const char *); +static char *escape_perm_xline(const char *); +static int valid_xline(struct Client *, const char *, const char *, int); static void apply_xline(struct Client *client_p, const char *name, const char *reason, int temp_time); static void write_xline(struct Client *source_p, struct ConfItem *aconf); @@ -100,6 +100,7 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char { struct ConfItem *aconf; const char *name; + char *escapedname; const char *reason; const char *target_server = NULL; int temp_time; @@ -144,28 +145,46 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char reason = parv[loc]; + if (temp_time == 0) + { + escapedname = escape_perm_xline(name); + if (strcmp(escapedname, name)) + sendto_one_notice(source_p, ":Changed xline from [%s] to [%s]", + name, escapedname); + } + else + escapedname = rb_strdup(name); + if(target_server != NULL) { propagate_xline(source_p, target_server, temp_time, - name, "2", reason); + escapedname, "2", reason); if(!match(target_server, me.name)) + { + rb_free(escapedname); return 0; + } } else if(rb_dlink_list_length(&cluster_conf_list) > 0) - cluster_xline(source_p, temp_time, name, reason); + cluster_xline(source_p, temp_time, escapedname, reason); - if((aconf = find_xline_mask(name)) != NULL) + if((aconf = find_xline_mask(escapedname)) != NULL) { sendto_one(source_p, ":%s NOTICE %s :[%s] already X-Lined by [%s] - %s", - me.name, source_p->name, name, aconf->name, aconf->passwd); + me.name, source_p->name, escapedname, aconf->name, aconf->passwd); + rb_free(escapedname); return 0; } - if(!valid_xline(source_p, name, reason)) + if(!valid_xline(source_p, escapedname, reason, temp_time)) + { + rb_free(escapedname); return 0; + } - apply_xline(source_p, name, reason, temp_time); + apply_xline(source_p, escapedname, reason, temp_time); + rb_free(escapedname); return 0; } @@ -177,8 +196,8 @@ mo_xline(struct Client *client_p, struct Client *source_p, int parc, const char static int ms_xline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - /* parv[0] parv[1] parv[2] parv[3] parv[4] - * oper target serv xline type reason + /* source_p parv[1] parv[2] parv[3] parv[4] + * oper target serv xline type reason */ propagate_xline(source_p, parv[1], 0, parv[2], parv[3], parv[4]); @@ -215,7 +234,7 @@ handle_remote_xline(struct Client *source_p, int temp_time, (temp_time > 0) ? SHARED_TXLINE : SHARED_PXLINE)) return; - if(!valid_xline(source_p, name, reason)) + if(!valid_xline(source_p, name, reason, temp_time)) return; /* already xlined */ @@ -228,15 +247,38 @@ handle_remote_xline(struct Client *source_p, int temp_time, apply_xline(source_p, name, reason, temp_time); } +/* escape_perm_xline() + * + * inputs - gecos + * outputs - escaped gecos (allocated with rb_malloc()) + * side effects - none + */ +static char * +escape_perm_xline(const char *gecos) +{ + char *result; + int i, j; + + result = rb_malloc(2 * strlen(gecos) + 1); + for (i = 0, j = 0; gecos[i] != '\0'; i++) + { + result[j++] = gecos[i]; + if (gecos[i] == '"' && gecos[i + 1] == ',') + result[j++] = '\\'; + } + result[j] = '\0'; + return result; +} + /* valid_xline() * - * inputs - client xlining, gecos, reason and whether to warn + * inputs - client xlining, gecos, reason and temp time * outputs - * side effects - checks the xline for validity, erroring if needed */ static int valid_xline(struct Client *source_p, const char *gecos, - const char *reason) + const char *reason, int temp_time) { if(EmptyString(reason)) { @@ -246,6 +288,13 @@ valid_xline(struct Client *source_p, const char *gecos, return 0; } + if(temp_time == 0 && strstr(gecos, "\",") != NULL) + { + sendto_one_notice(source_p, + ":Invalid character sequence '\",' in xline, please replace with '\"\\,'"); + return 0; + } + if(strchr(reason, ':') != NULL) { sendto_one_notice(source_p, @@ -281,41 +330,7 @@ apply_xline(struct Client *source_p, const char *name, const char *reason, aconf = make_conf(); aconf->status = CONF_XLINE; - if(strstr(name, "\\s")) - { - char *tmp = LOCAL_COPY(name); - char *orig = tmp; - char *new = tmp; - - while(*orig) - { - if(*orig == '\\' && *(orig + 1) != '\0') - { - if(*(orig + 1) == 's') - { - *new++ = ' '; - orig += 2; - } - /* otherwise skip that and the escaped - * character after it, so we dont mistake - * \\s as \s --fl - */ - else - { - *new++ = *orig++; - *new++ = *orig++; - } - } - else - *new++ = *orig++; - } - - *new = '\0'; - aconf->name = rb_strdup(tmp); - } - else - aconf->name = rb_strdup(name); - + aconf->name = rb_strdup(name); aconf->passwd = rb_strdup(reason); collapse(aconf->name); @@ -361,6 +376,40 @@ write_xline(struct Client *source_p, struct ConfItem *aconf) char buffer[BUFSIZE * 2]; FILE *out; const char *filename; + char *mangle_gecos; + + if(strstr(aconf->name, "\\s")) + { + char *tmp = LOCAL_COPY(aconf->name); + char *orig = tmp; + char *new = tmp; + while(*orig) + { + if(*orig == '\\' && *(orig + 1) != '\0') + { + if(*(orig + 1) == 's') + { + *new++ = ' '; + orig += 2; + } + /* otherwise skip that and the escaped + * character after it, so we dont mistake + * \\s as \s --fl + */ + else + { + *new++ = *orig++; + *new++ = *orig++; + } + } + else + *new++ = *orig++; + } + + *new = '\0'; + mangle_gecos = tmp; + } else + mangle_gecos = aconf->name; filename = ConfigFileEntry.xlinefile; @@ -372,7 +421,7 @@ write_xline(struct Client *source_p, struct ConfItem *aconf) } rb_sprintf(buffer, "\"%s\",\"0\",\"%s\",\"%s\",%ld\n", - aconf->name, aconf->passwd, + mangle_gecos, aconf->passwd, get_oper_name(source_p), (long) rb_current_time()); if(fputs(buffer, out) == -1) @@ -489,8 +538,8 @@ mo_unxline(struct Client *client_p, struct Client *source_p, int parc, const cha static int ms_unxline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - /* parv[0] parv[1] parv[2] - * oper target server gecos + /* source_p parv[1] parv[2] + * oper target server gecos */ propagate_generic(source_p, "UNXLINE", parv[1], CAP_CLUSTER, "%s", parv[2]); @@ -533,38 +582,43 @@ remove_xline(struct Client *source_p, const char *name) { struct ConfItem *aconf; rb_dlink_node *ptr; + char *encoded; + + encoded = xline_encode_spaces(name); RB_DLINK_FOREACH(ptr, xline_conf_list.head) { aconf = ptr->data; - if(!irccmp(aconf->name, name)) + if(!irccmp(aconf->name, encoded)) { if (!aconf->hold) { - if (!remove_xline_from_file(source_p, name)) + if (!remove_xline_from_file(source_p, encoded)) return; } else { sendto_one_notice(source_p, ":X-Line for [%s] is removed", - name); + encoded); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the temporary X-Line for: [%s]", - get_oper_name(source_p), name); + get_oper_name(source_p), encoded); ilog(L_KLINE, "UX %s %s", - get_oper_name(source_p), name); + get_oper_name(source_p), encoded); } remove_reject_mask(aconf->name, NULL); free_conf(aconf); rb_dlinkDestroy(ptr, &xline_conf_list); + rb_free(encoded); return; } } - sendto_one_notice(source_p, ":No X-Line for %s", name); + sendto_one_notice(source_p, ":No X-Line for %s", encoded); + rb_free(encoded); return; } @@ -587,6 +641,7 @@ remove_xline_from_file(struct Client *source_p, const char *huntgecos) const char *gecos; mode_t oldumask; char *p; + char *encoded; int error_on_write = 0; int found_xline = 0; @@ -622,7 +677,7 @@ remove_xline_from_file(struct Client *source_p, const char *huntgecos) break; } - strlcpy(buff, buf, sizeof(buff)); + rb_strlcpy(buff, buf, sizeof(buff)); if((p = strchr(buff, '\n')) != NULL) *p = '\0'; @@ -640,10 +695,12 @@ remove_xline_from_file(struct Client *source_p, const char *huntgecos) } /* matching.. */ - if(irccmp(gecos, huntgecos) == 0) + encoded = xline_encode_spaces(gecos); + if(irccmp(encoded, huntgecos) == 0) found_xline++; else error_on_write = (fputs(buf, out) < 0) ? YES : NO; + rb_free(encoded); } fclose(in);