X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/63860dd1a7e06f181cf037101490270ae89e7ad1..c387fc41ae496de901a556928e0c65736d5ced4f:/modules/m_xline.c diff --git a/modules/m_xline.c b/modules/m_xline.c index 1aff1c9..edda41e 100644 --- a/modules/m_xline.c +++ b/modules/m_xline.c @@ -70,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); @@ -99,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; @@ -143,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; } @@ -214,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 */ @@ -227,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)) { @@ -245,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, @@ -326,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; @@ -337,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)