static void list_bans(void) { static char buf[512]; struct rsdb_table table; int i, j; /* schedule a clear of anything already pending */ rb_helper_write_queue(bandb_helper, "C"); for(i = 0; i < LAST_BANDB_TYPE; i++) { rsdb_exec_fetch(&table, "SELECT mask1,mask2,oper,reason FROM %s WHERE 1", bandb_table[i]); for(j = 0; j < table.row_count; j++) { if(i == BANDB_KLINE) rb_snprintf(buf, sizeof(buf), "%c %s %s %s :%s", bandb_letter[i], table.row[j][0], table.row[j][1], table.row[j][2], table.row[j][3]); else rb_snprintf(buf, sizeof(buf), "%c %s %s :%s", bandb_letter[i], table.row[j][0], table.row[j][2], table.row[j][3]); rb_helper_write_queue(bandb_helper, "%s", buf); } rsdb_exec_fetch_end(&table); } rb_helper_write(bandb_helper, "F"); }
static int eb_extended(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type) { char buf[BUFSIZE]; int ret; (void)chptr; if (data == NULL) return EXTBAN_INVALID; rb_snprintf(buf, BUFSIZE, "%s!%s@%s#%s", client_p->name, client_p->username, client_p->host, client_p->info); ret = match(data, buf) ? EXTBAN_MATCH : EXTBAN_NOMATCH; if (ret == EXTBAN_NOMATCH && IsDynSpoof(client_p)) { rb_snprintf(buf, BUFSIZE, "%s!%s@%s#%s", client_p->name, client_p->username, client_p->orighost, client_p->info); ret = match(data, buf) ? EXTBAN_MATCH : EXTBAN_NOMATCH; } return ret; }
/* * ms_svinfo - SVINFO message handler * parv[1] = TS_CURRENT for the server * parv[2] = TS_MIN for the server * parv[3] = unused, send 0 * parv[4] = server's idea of UTC time */ static int ms_svinfo(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { signed long deltat; time_t theirtime; char squitreason[120]; /* SVINFO isnt remote. */ if(source_p != client_p) return 0; if(TS_CURRENT < atoi(parv[2]) || atoi(parv[1]) < TS_MIN) { /* TS version is too low on one of the sides, drop the link */ sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s dropped, wrong TS protocol version (%s,%s)", source_p->name, parv[1], parv[2]); rb_snprintf(squitreason, sizeof squitreason, "Incompatible TS version (%s,%s)", parv[1], parv[2]); exit_client(source_p, source_p, source_p, squitreason); return 0; } /* * since we're here, might as well set rb_current_time() while we're at it */ rb_set_time(); theirtime = atol(parv[4]); deltat = labs(theirtime - rb_current_time()); if(deltat > ConfigFileEntry.ts_max_delta) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Link %s dropped, excessive TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", source_p->name, (long) rb_current_time(), (long) theirtime, deltat); ilog(L_SERVER, "Link %s dropped, excessive TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", log_client_name(source_p, SHOW_IP), (long) rb_current_time(), (long) theirtime, deltat); rb_snprintf(squitreason, sizeof squitreason, "Excessive TS delta (my TS=%ld, their TS=%ld, delta=%ld)", (long) rb_current_time(), (long) theirtime, deltat); disable_server_conf_autoconn(source_p->name); exit_client(source_p, source_p, source_p, squitreason); return 0; } if(deltat > ConfigFileEntry.ts_warn_delta) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Link %s notable TS delta" " (my TS=%ld, their TS=%ld, delta=%ld)", source_p->name, (long) rb_current_time(), (long) theirtime, deltat); } return 0; }
/* mr_user() * parv[1] = username (login name, account) * parv[2] = client host name (ignored) * parv[3] = server host name (ignored) * parv[4] = users gecos */ static int mr_user(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { static char buf[BUFSIZE]; char *p; if (strlen(client_p->id) == 3) { exit_client(client_p, client_p, client_p, "Mixing client and server protocol"); return 0; } if(source_p->flags & FLAGS_SENTUSER) return 0; if((p = strchr(parv[1], '@'))) *p = '\0'; rb_snprintf(buf, sizeof(buf), "%s %s", parv[2], parv[3]); rb_free(source_p->localClient->fullcaps); source_p->localClient->fullcaps = rb_strdup(buf); do_local_user(client_p, source_p, parv[1], parv[4]); return 0; }
void server_reboot(void) { int i; char path[PATH_MAX+1]; sendto_realops_snomask(SNO_GENERAL, L_ALL, "Restarting server..."); ilog(L_MAIN, "Restarting server..."); /* * XXX we used to call flush_connections() here. But since this routine * doesn't exist anymore, we won't be flushing. This is ok, since * when close handlers come into existance, rb_close() will be called * below, and the data flushing will be implicit. * -- adrian * * bah, for now, the program ain't coming back to here, so forcibly * close everything the "wrong" way for now, and just LEAVE... */ for (i = 0; i < maxconnections; ++i) close(i); unlink(pidFileName); execv(SPATH, (void *)myargv); /* use this if execv of SPATH fails */ rb_snprintf(path, sizeof(path), "%s/bin/ircd", ConfigFileEntry.dpath); execv(path, (void *)myargv); exit(-1); }
static int eb_unidentified(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type) { (void)chptr; /* $u doesn't make sense for ban exceptions and invex. */ if(mode_type == CHFL_EXCEPTION || mode_type == CHFL_INVEX) return EXTBAN_INVALID; /* $u makes little sense without an argument, use $~a. */ if (data == NULL) { return EXTBAN_INVALID; } /* $u has an argument, check it. It should be n!u@h . */ else { char buf[BUFSIZE]; rb_snprintf(buf, BUFSIZE, "%s!%s@%s", client_p->name, client_p->username, client_p->host); if ((match(data, buf) != 0) && EmptyString(client_p->user->suser)) { return EXTBAN_MATCH; } else { return EXTBAN_NOMATCH; } } }
/* ** m_quit ** parv[1] = comment */ static int m_quit(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char *comment = LOCAL_COPY((parc > 1 && parv[1]) ? parv[1] : client_p->name); char reason[REASONLEN + 1]; source_p->flags |= FLAGS_NORMALEX; if(strlen(comment) > (size_t) REASONLEN) comment[REASONLEN] = '\0'; strip_colour(comment); if(ConfigFileEntry.client_exit && comment[0]) { rb_snprintf(reason, sizeof(reason), "Quit: %s", comment); comment = reason; } if(!IsOper(source_p) && !EmptyString(ConfigFileEntry.static_quit)) { exit_client(client_p, source_p, source_p, ConfigFileEntry.static_quit); return 0; } if(!IsOper(source_p) && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) > rb_current_time()) { exit_client(client_p, source_p, source_p, "Client Quit"); return 0; } exit_client(client_p, source_p, source_p, comment); return 0; }
/* ** m_quit ** parv[1] = comment */ static int m_quit(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char comment[REASONLEN + 1]; /* Better safe than sorry */ char reason[REASONLEN + 1]; source_p->flags |= FLAGS_NORMALEX; strip_colour((parc > 1 && parv[1]) ? parv[1] : client_p->name, comment, REASONLEN); if(ConfigFileEntry.client_exit && comment[0]) { rb_snprintf(reason, sizeof(reason), "Quit: %s", comment); rb_strlcpy(comment, reason, REASONLEN + 1); } if(!IsOper(source_p) && !EmptyString(ConfigFileEntry.static_quit)) { exit_client(client_p, source_p, source_p, ConfigFileEntry.static_quit); return 0; } if(!IsOper(source_p) && (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) > rb_current_time()) { exit_client(client_p, source_p, source_p, "Client Quit"); return 0; } exit_client(client_p, source_p, source_p, comment); return 0; }
/* ms_operspy() * * parv[1] - operspy command * parv[2] - optional params */ static int ms_operspy(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { static char buffer[BUFSIZE]; char *ptr; int cur_len = 0; int len, i; if (parc < 4) { report_operspy(source_p, parv[1], parc < 3 ? NULL : parv[2]); } /* buffer all remaining into one param */ else { ptr = buffer; cur_len = 0; for (i = 2; i < parc; i++) { len = strlen(parv[i]) + 1; if ((size_t)(cur_len + len) >= sizeof(buffer)) return 0; rb_snprintf(ptr, sizeof(buffer) - cur_len, "%s ", parv[i]); ptr += len; cur_len += len; } report_operspy(source_p, parv[1], buffer); } return 0; }
void ilog(ilogfile dest, const char *format, ...) { FILE *logfile = *log_table[dest].logfile; char buf[BUFSIZE]; char buf2[BUFSIZE]; va_list args; if(logfile == NULL) return; va_start(args, format); rb_vsnprintf(buf, sizeof(buf), format, args); va_end(args); rb_snprintf(buf2, sizeof(buf2), "%s %s\n", smalldate(rb_current_time()), buf); if(fputs(buf2, logfile) < 0) { fclose(logfile); *log_table[dest].logfile = NULL; return; } fflush(logfile); }
static int rb_epoll_sched_event_timerfd(struct ev_entry *event, int when) { struct itimerspec ts; static char buf[FD_DESC_SZ + 8]; int fd; rb_fde_t *F; if((fd = timerfd_create(CLOCK_REALTIME, 0)) < 0) { rb_lib_log("timerfd_create: %s\n", strerror(errno)); return 0; } memset(&ts, 0, sizeof(ts)); ts.it_value.tv_sec = when; ts.it_value.tv_nsec = 0; if(event->frequency != 0) ts.it_interval = ts.it_value; if(timerfd_settime(fd, 0, &ts, NULL) < 0) { rb_lib_log("timerfd_settime: %s\n", strerror(errno)); close(fd); return 0; } rb_snprintf(buf, sizeof(buf), "timerfd: %s", event->name); F = rb_open(fd, RB_FD_UNKNOWN, buf); rb_set_nb(F); event->comm_ptr = F; rb_setselect(F, RB_SELECT_READ, rb_read_timerfd, event); return 1; }
void rb_get_ssl_info(char *buf, size_t len) { rb_snprintf(buf, len, "Using SSL: %s compiled: 0x%lx, library 0x%lx", SSLeay_version(SSLEAY_VERSION), (long)OPENSSL_VERSION_NUMBER, SSLeay()); }
/* ms_encap() * * parv[1] - destination server * parv[2] - subcommand * parv[3] - parameters */ static int ms_encap(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { char buffer[BUFSIZE]; char *ptr; int cur_len = 0; int len; int i; ptr = buffer; for(i = 1; i < parc - 1; i++) { len = strlen(parv[i]) + 1; /* ugh, not even at the last parameter, just bail --fl */ if((size_t)(cur_len + len) >= sizeof(buffer)) return 0; rb_snprintf(ptr, sizeof(buffer) - cur_len, "%s ", parv[i]); cur_len += len; ptr += len; } len = strlen(parv[i]); /* if its a command without parameters, dont prepend a ':' */ if(parc == 3) rb_snprintf(ptr, sizeof(buffer) - cur_len, "%s", parv[2]); else rb_snprintf(ptr, sizeof(buffer) - cur_len, ":%s", parv[parc-1]); /* add a trailing \0 if it was too long */ if((cur_len + len) >= BUFSIZE) buffer[BUFSIZE-1] = '\0'; sendto_match_servs(source_p, parv[1], CAP_ENCAP, NOCAPS, "ENCAP %s", buffer); /* if it matches us, find a matching handler and call it */ if(match(parv[1], me.name)) handle_encap(client_p, source_p, parv[2], parc - 2, parv + 2); return 0; }
static void db_error_cb(const char *errstr) { char buf[256]; rb_snprintf(buf, sizeof(buf), "! :%s", errstr); rb_helper_write(bandb_helper, "%s", buf); rb_sleep(2 << 30, 0); exit(1); }
static void verify_logfile_access(const char *filename) { char *dirname, *d; char buf[512]; d = rb_dirname(filename); dirname = LOCAL_COPY(d); rb_free(d); if(access(dirname, F_OK) == -1) { rb_snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - parent directory %s does not exist", filename, dirname); if(testing_conf || server_state_foreground) fprintf(stderr, "%s\n", buf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf); return; } if(access(filename, F_OK) == -1) { if(access(dirname, W_OK) == -1) { rb_snprintf(buf, sizeof(buf), "WARNING: Unable to access logfile %s - access to parent directory %s failed: %s", filename, dirname, strerror(errno)); if(testing_conf || server_state_foreground) fprintf(stderr, "%s\n", buf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf); } return; } if(access(filename, W_OK) == -1) { rb_snprintf(buf, sizeof(buf), "WARNING: Access denied for logfile %s: %s", filename, strerror(errno)); if(testing_conf || server_state_foreground) fprintf(stderr, "%s\n", buf); sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s", buf); return; } return; }
/* * get_listener_name - return displayable listener name and port * returns "host.foo.org:6667" for a given listener */ const char * get_listener_name(const struct Listener *listener) { static char buf[HOSTLEN + HOSTLEN + PORTNAMELEN + 4]; s_assert(NULL != listener); if(listener == NULL) return NULL; rb_snprintf(buf, sizeof(buf), "%s[%s/%u]", me.name, listener->name, get_listener_port(listener)); return buf; }
const char * smalldate(time_t ltime) { static char buf[MAX_DATE_STRING]; struct tm *lt; lt = localtime(<ime); rb_snprintf(buf, sizeof(buf), "%d/%d/%d %02d.%02d", lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min); return buf; }
void server_reboot(void) { char path[PATH_MAX + 1]; sendto_realops_flags(UMODE_ALL, L_ALL, "Restarting server..."); ilog(L_MAIN, "Restarting server..."); /* set all the signal handlers to a dummy */ setup_reboot_signals(); /* * XXX we used to call flush_connections() here. But since this routine * doesn't exist anymore, we won't be flushing. This is ok, since * when close handlers come into existance, rb_close() will be called * below, and the data flushing will be implicit. * -- adrian * * bah, for now, the program ain't coming back to here, so forcibly * close everything the "wrong" way for now, and just LEAVE... */ #ifndef _WIN32 int i; for(i = 0; i < maxconnections; ++i) close(i); #endif unlink(pidFileName); #ifndef _WIN32 int fd = open("/dev/null", O_RDWR); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); #endif execv(SPATH, (void *)myargv); /* use this if execv of SPATH fails */ rb_snprintf(path, sizeof(path), "%s/bin/ircd", ConfigFileEntry.dpath); execv(path, (void *)myargv); exit(-1); }
/* * get_listener_name - return displayable listener name and port * returns "host.foo.org:6667" for a given listener */ const char * get_listener_name(const struct Listener *listener) { static char buf[HOSTLEN + HOSTLEN + PORTNAMELEN + 4]; int port = 0; s_assert(NULL != listener); if(listener == NULL) return NULL; #ifdef RB_IPV6 if(listener->addr.ss_family == AF_INET6) port = ntohs(((const struct sockaddr_in6 *)&listener->addr)->sin6_port); else #endif port = ntohs(((const struct sockaddr_in *)&listener->addr)->sin_port); rb_snprintf(buf, sizeof(buf), "%s[%s/%u]", me.name, listener->name, port); return buf; }
static int change_nick(struct Client *client_p, const char *newnick) { char note[NICKLEN + 10]; client_p->tsinfo = rb_current_time(); monitor_signoff(client_p); invalidate_bancache_user(client_p); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Forced nick change: From %s to %s [%s@%s]", client_p->name, newnick, client_p->username, client_p->host); sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s", client_p->name, client_p->username, client_p->host, newnick); add_history(client_p, 1); sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld", use_id(client_p), newnick, (long) client_p->tsinfo); del_from_client_hash(client_p->name, client_p); strcpy(client_p->name, newnick); add_to_client_hash(client_p->name, client_p); monitor_signon(client_p); del_all_accepts(client_p); rb_snprintf(note, NICKLEN + 10, "Nick: %s", client_p->name); rb_note(client_p->localClient->F, note); return 0; }
static void cap_req(struct Client *source_p, const char *arg) { char buf[BUFSIZE]; char pbuf[2][BUFSIZE]; struct clicap *cap; int buflen, plen; int i = 0; int capadd = 0, capdel = 0; int finished = 0, negate; if(!IsRegistered(source_p)) source_p->flags |= FLAGS_CLICAP; if(EmptyString(arg)) return; buflen = rb_snprintf(buf, sizeof(buf), ":%s CAP %s ACK", me.name, EmptyString(source_p->name) ? "*" : source_p->name); pbuf[0][0] = '\0'; plen = 0; for(cap = clicap_find(arg, &negate, &finished); cap; cap = clicap_find(NULL, &negate, &finished)) { /* filled the first array, but cant send it in case the * request fails. one REQ should never fill more than two * buffers --fl */ if(buflen + plen + cap->namelen + 6 >= BUFSIZE) { pbuf[1][0] = '\0'; plen = 0; i = 1; } if(negate) { if(cap->flags & CLICAP_FLAGS_STICKY) { finished = 0; break; } strcat(pbuf[i], "-"); plen++; capdel |= cap->cap_serv; } else { if(cap->flags & CLICAP_FLAGS_STICKY) { strcat(pbuf[i], "="); plen++; } capadd |= cap->cap_serv; } if(cap->cap_cli) { strcat(pbuf[i], "~"); plen++; } strcat(pbuf[i], cap->name); strcat(pbuf[i], " "); plen += (cap->namelen + 1); } if(!finished) { sendto_one(source_p, ":%s CAP %s NAK :%s", me.name, EmptyString(source_p->name) ? "*" : source_p->name, arg); return; } if(i) { sendto_one(source_p, "%s * :%s", buf, pbuf[0]); sendto_one(source_p, "%s :%s", buf, pbuf[1]); } else sendto_one(source_p, "%s :%s", buf, pbuf[0]); source_p->localClient->caps |= capadd; source_p->localClient->caps &= ~capdel; }
static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data) { struct Listener *listener = (struct Listener *)data; char buf[BUFSIZE]; struct ConfItem *aconf; static time_t last_oper_notice = 0; int len; if(listener->ssl && (!ssl_ok || !get_ssld_count())) { rb_close(F); return 0; } if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */ { ++ServerStats.is_ref; /* * slow down the whining to opers bit */ if((last_oper_notice + 20) <= rb_current_time()) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "All connections in use. (%s)", get_listener_name(listener)); last_oper_notice = rb_current_time(); } rb_write(F, "ERROR :All connections in use\r\n", 32); rb_close(F); /* Re-register a new IO request for the next accept .. */ return 0; } aconf = find_dline(addr, addr->sa_family); if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE)) return 1; /* Do an initial check we aren't connecting too fast or with too many * from this IP... */ if(aconf != NULL) { ServerStats.is_ref++; if(ConfigFileEntry.dline_with_reason) { len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf)); if (len >= (int)(sizeof(buf)-1)) { buf[sizeof(buf) - 3] = '\r'; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = '\0'; } } else strcpy(buf, "ERROR :You have been D-lined.\r\n"); rb_write(F, buf, strlen(buf)); rb_close(F); return 0; } if(check_reject(F, addr)) return 0; if(throttle_add(addr)) { rb_write(F, toofast, strlen(toofast)); rb_close(F); return 0; } return 1; }
static int mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct ConfItem *aconf; struct ConfItem *resv_p; struct rb_sockaddr_storage ip; const char *name = NULL; const char *username = NULL; const char *host = NULL; char *mask; char *p; int host_mask; int type; mask = LOCAL_COPY(parv[1]); if(IsChannelName(mask)) { resv_p = hash_find_resv(mask); if(resv_p != NULL) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (resv_p->flags & CONF_FLAGS_TEMPORARY) ? 'q' : 'Q', (resv_p->flags & CONF_FLAGS_TEMPORARY) ? (long)((resv_p->hold - rb_current_time ()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; } else sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; } if((p = strchr(mask, '!'))) { *p++ = '\0'; name = mask; mask = p; if(EmptyString(mask)) return 0; } if((p = strchr(mask, '@'))) { *p++ = '\0'; username = mask; host = p; if(EmptyString(host)) return 0; } else host = mask; /* parses as an IP, check for a dline */ if((type = parse_netmask(host, (struct sockaddr *)&ip, &host_mask)) != HM_HOST) { aconf = find_dline((struct sockaddr *)&ip); if(aconf && aconf->status & CONF_DLINE) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long)((aconf->hold - rb_current_time()) / 60) : 0L, aconf->host, aconf->passwd); return 0; } } /* now look for a matching I/K/G */ if((aconf = find_address_conf(host, NULL, username ? username : "******", (type != HM_HOST) ? (struct sockaddr *)&ip : NULL, (type != HM_HOST) ? ( #ifdef RB_IPV6 (type == HM_IPV6) ? AF_INET6 : #endif AF_INET) : 0))) { static char buf[HOSTLEN + USERLEN + 2]; if(aconf->status & CONF_KILL) { rb_snprintf(buf, sizeof(buf), "%s@%s", aconf->user, aconf->host); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long)((aconf->hold - rb_current_time()) / 60) : 0L, buf, aconf->passwd); return 0; } else if(aconf->status & CONF_GLINE) { rb_snprintf(buf, sizeof(buf), "%s@%s", aconf->user, aconf->host); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, 'G', (long)((aconf->hold - rb_current_time()) / 60), buf, aconf->passwd); return 0; } } /* they asked us to check a nick, so hunt for resvs.. */ if(name && (resv_p = find_nick_resv(name))) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (resv_p->flags & CONF_FLAGS_TEMPORARY) ? 'q' : 'Q', (resv_p->flags & CONF_FLAGS_TEMPORARY) ? (long)((resv_p->hold - rb_current_time()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; return 0; } /* no matching resv, we can print the I: if it exists */ if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), aconf->info.name, show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, get_class_name(aconf)); return 0; } /* nothing matches.. */ sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; }
void rb_get_ssl_info(char *buf, size_t len) { rb_snprintf(buf, len, "Not compiled with SSL support"); }
static int mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct ConfItem *aconf; struct ConfItem *resv_p; struct rb_sockaddr_storage ip; char user_trunc[USERLEN + 1], notildeuser_trunc[USERLEN + 1]; const char *name = NULL; const char *username = NULL; const char *host = NULL; char *mask; char *p; int host_mask; int type; int duration; char *puser, *phost, *reason, *operreason; char reasonbuf[BUFSIZE]; mask = LOCAL_COPY(parv[1]); if (IsChannelName(mask)) { resv_p = hash_find_resv(mask); if (resv_p != NULL) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, resv_p->hold ? 'q' : 'Q', resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; } else sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; } if((p = strchr(mask, '!'))) { *p++ = '\0'; name = mask; mask = p; if(EmptyString(mask)) return 0; } if((p = strchr(mask, '@'))) { *p++ = '\0'; username = mask; host = p; if(EmptyString(host)) return 0; } else host = mask; /* parses as an IP, check for a dline */ if((type = parse_netmask(host, (struct sockaddr *)&ip, &host_mask)) != HM_HOST) { #ifdef RB_IPV6 if(type == HM_IPV6) aconf = find_dline((struct sockaddr *)&ip, AF_INET6); else #endif aconf = find_dline((struct sockaddr *)&ip, AF_INET); if(aconf && aconf->status & CONF_DLINE) { get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason); rb_snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason, operreason ? "|" : "", operreason ? operreason : ""); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long) ((aconf->hold - rb_current_time()) / 60) : 0L, phost, reasonbuf); return 0; } /* Otherwise, aconf is an exempt{} */ if(aconf == NULL && (duration = is_reject_ip((struct sockaddr *)&ip))) sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, '!', duration / 60L, host, "Reject cache"); if(aconf == NULL && (duration = is_throttle_ip((struct sockaddr *)&ip))) sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, '!', duration / 60L, host, "Throttled"); } if (username != NULL) { rb_strlcpy(user_trunc, username, sizeof user_trunc); rb_strlcpy(notildeuser_trunc, *username == '~' ? username + 1 : username, sizeof notildeuser_trunc); } else { rb_strlcpy(user_trunc, "dummy", sizeof user_trunc); rb_strlcpy(notildeuser_trunc, "dummy", sizeof notildeuser_trunc); } /* now look for a matching I/K/G */ if((aconf = find_address_conf(host, NULL, user_trunc, notildeuser_trunc, (type != HM_HOST) ? (struct sockaddr *)&ip : NULL, (type != HM_HOST) ? ( #ifdef RB_IPV6 (type == HM_IPV6) ? AF_INET6 : #endif AF_INET) : 0, NULL))) { static char buf[HOSTLEN+USERLEN+2]; if(aconf->status & CONF_KILL) { get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason); rb_snprintf(buf, sizeof(buf), "%s@%s", puser, phost); rb_snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason, operreason ? "|" : "", operreason ? operreason : ""); sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, (aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K', (aconf->flags & CONF_FLAGS_TEMPORARY) ? (long) ((aconf->hold - rb_current_time()) / 60) : 0L, buf, reasonbuf); return 0; } } /* they asked us to check a nick, so hunt for resvs.. */ if(name && (resv_p = find_nick_resv(name))) { sendto_one(source_p, form_str(RPL_TESTLINE), me.name, source_p->name, resv_p->hold ? 'q' : 'Q', resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L, resv_p->host, resv_p->passwd); /* this is a false positive, so make sure it isn't counted in stats q * --nenolod */ resv_p->port--; return 0; } /* no matching resv, we can print the I: if it exists */ if(aconf && aconf->status & CONF_CLIENT) { sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd, show_iline_prefix(source_p, aconf, aconf->user), aconf->host, aconf->port, aconf->className); return 0; } /* nothing matches.. */ sendto_one(source_p, form_str(RPL_NOTESTLINE), me.name, source_p->name, parv[1]); return 0; }
void rb_get_ssl_info(char *buf, size_t len) { rb_snprintf(buf, len, "GNUTLS: compiled (%s), library(%s)", LIBGNUTLS_VERSION, gnutls_check_version(NULL)); }
static int m_displaymsg(struct Client *source_p, const char *channel, int underline, int action, const char *nick, const char *text) { struct Channel *chptr; struct membership *msptr; char nick2[NICKLEN+1]; char *nick3 = rb_strdup(nick); char text2[BUFSIZE]; if((chptr = find_channel(channel)) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), channel); return 0; } if(!(msptr = find_channel_membership(chptr, source_p))) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), chptr->chname); return 0; } if(!(chptr->mode.mode & chmode_flags['N'])) { sendto_one_numeric(source_p, 573, "%s :Roleplay commands are not enabled on this channel.", chptr->chname); return 0; } if(!can_send(chptr, source_p, msptr)) { sendto_one_numeric(source_p, 573, "%s :Cannot send to channel.", chptr->chname); return 0; } /* enforce flood stuff on roleplay commands */ if(flood_attack_channel(0, source_p, chptr, chptr->chname)) return 0; /* enforce target change on roleplay commands */ if(!is_chanop_voiced(msptr) && !IsOper(source_p) && !add_channel_target(source_p, chptr)) { sendto_one(source_p, form_str(ERR_TARGCHANGE), me.name, source_p->name, chptr->chname); return 0; } if(underline) rb_snprintf(nick2, sizeof(nick2), "\x1F%s\x1F", strip_unprintable(nick3)); else rb_snprintf(nick2, sizeof(nick2), "%s", strip_unprintable(nick3)); /* don't allow nicks to be empty after stripping * this prevents nastiness like fake factions, etc. */ if(EmptyString(nick3)) { sendto_one_numeric(source_p, 573, "%s :No visible non-stripped characters in nick.", chptr->chname); return 0; } if(action) rb_snprintf(text2, sizeof(text2), "\1ACTION %s\1", text); else rb_snprintf(text2, sizeof(text2), "%s", text); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected] PRIVMSG %s :%s (%s)", nick2, source_p->name, channel, text2, source_p->name); sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS, "ENCAP * ROLEPLAY %s %s :%s", channel, nick2, text2); return 0; }
/* ** m_kick ** parv[1] = channel ** parv[2] = client to kick ** parv[3] = kick comment */ static int m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct membership *msptr; struct Client *who; struct Channel *chptr; int chasing = 0; char *comment; const char *name; char *p = NULL; char text[10]; const char *user; static char buf[BUFSIZE]; int is_override = 0; if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); *buf = '\0'; if((p = strchr(parv[1], ','))) *p = '\0'; name = parv[1]; chptr = find_channel(name); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } user = parv[2]; /* strtoken(&p2, parv[2], ","); */ if(!(who = find_chasing(source_p, user, &chasing))) { return 0; } if(!IsServer(source_p)) { msptr = find_channel_membership(chptr, source_p); if((msptr == NULL) && MyConnect(source_p)) { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), name); return 0; } if(!can_kick_deop(msptr, find_channel_membership(chptr, who))) { if(MyConnect(source_p)) { if(IsOverride(source_p)) is_override = 1; else { sendto_one(source_p, ":%s 482 %s %s :You do not have the proper privileges to kick this user", me.name, source_p->name, name); return 0; } } /* If its a TS 0 channel, do it the old way */ else if(chptr->channelts == 0) { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), get_id(&me, source_p), get_id(source_p, source_p), name); return 0; } } /* Its a user doing a kick, but is not showing as chanop locally * its also not a user ON -my- server, and the channel has a TS. * There are two cases we can get to this point then... * * 1) connect burst is happening, and for some reason a legit * op has sent a KICK, but the SJOIN hasn't happened yet or * been seen. (who knows.. due to lag...) * * 2) The channel is desynced. That can STILL happen with TS * * Now, the old code roger wrote, would allow the KICK to * go through. Thats quite legit, but lets weird things like * KICKS by users who appear not to be chanopped happen, * or even neater, they appear not to be on the channel. * This fits every definition of a desync, doesn't it? ;-) * So I will allow the KICK, otherwise, things are MUCH worse. * But I will warn it as a possible desync. * * -Dianora */ } if((p = strchr(parv[2], ','))) *p = '\0'; msptr = find_channel_membership(chptr, who); if(msptr != NULL) { if(MyClient(source_p) && IsService(who)) { sendto_one(source_p, form_str(ERR_ISCHANSERVICE), me.name, source_p->name, who->name, chptr->chname); return 0; } if(MyClient(source_p) && chptr->mode.mode & MODE_NOKICK) { sendto_one_numeric(source_p, ERR_NOKICK, form_str(ERR_NOKICK), chptr->chname); return 0; } if (MyClient(source_p) && chptr->mode.mode & MODE_NOOPERKICK && IsOper(who)) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Overriding KICK from %s on %s in %s (channel is +M)", source_p->name, who->name, chptr->chname); sendto_one_numeric(source_p, ERR_ISCHANSERVICE, "%s %s :Cannot kick IRC operators from that channel.", who->name, chptr->chname); return 0; } if(MyClient(source_p)) { hook_data_channel_approval hookdata; hookdata.client = source_p; hookdata.chptr = chptr; hookdata.target = who; hookdata.approved = 1; call_hook(h_can_kick, &hookdata); if (!hookdata.approved) return 0; } comment = LOCAL_COPY((EmptyString(parv[3])) ? who->name : parv[3]); if(strlen(comment) > (size_t) REASONLEN) comment[REASONLEN] = '\0'; if(is_override) { sendto_wallops_flags(UMODE_WALLOP, &me, "%s is overriding KICK [%s] on [%s] [%s]", get_oper_name(source_p), who->name, chptr->chname, comment); sendto_server(NULL, chptr, NOCAPS, NOCAPS, ":%s WALLOPS :%s is overriding KICK [%s] on [%s] [%s]", me.name, get_oper_name(source_p), who->name, chptr->chname, comment); } /* jdc * - In the case of a server kicking a user (i.e. CLEARCHAN), * the kick should show up as coming from the server which did * the kick. * - Personally, flame and I believe that server kicks shouldn't * be sent anyways. Just waiting for some oper to abuse it... */ if(IsServer(source_p)) sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s", source_p->name, name, who->name, comment); else sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s KICK %s %s :%s", source_p->name, source_p->username, source_p->host, name, who->name, comment); sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s KICK %s %s :%s", use_id(source_p), chptr->chname, use_id(who), comment); remove_user_from_channel(msptr); rb_snprintf(text, sizeof(text), "K%s", who->id); /* we don't need to track NOREJOIN stuff unless it's our client being kicked */ if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN) channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN"); } else if (MyClient(source_p)) sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), user, name); return 0; }
static int me_svslogin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p, *exist_p; char nick[NICKLEN+1], login[NICKLEN+1]; char user[USERLEN+1], host[HOSTLEN+1]; int valid = 0; if(!(source_p->flags & FLAGS_SERVICE)) return 0; if((target_p = find_client(parv[1])) == NULL) return 0; if(!MyClient(target_p) && !IsUnknown(target_p)) return 0; if(clean_nick(parv[2])) { rb_strlcpy(nick, parv[2], NICKLEN + 1); valid |= NICK_VALID; } else if(*target_p->name) rb_strlcpy(nick, target_p->name, NICKLEN + 1); else strcpy(nick, "*"); if(clean_username(parv[3])) { rb_strlcpy(user, parv[3], USERLEN + 1); valid |= USER_VALID; } else rb_strlcpy(user, target_p->username, USERLEN + 1); if(clean_host(parv[4])) { rb_strlcpy(host, parv[4], HOSTLEN + 1); valid |= HOST_VALID; } else rb_strlcpy(host, target_p->host, HOSTLEN + 1); if(*parv[5] == '*') { if(target_p->user) rb_strlcpy(login, target_p->user->suser, NICKLEN + 1); else login[0] = '\0'; } else if(!strcmp(parv[5], "0")) login[0] = '\0'; else rb_strlcpy(login, parv[5], NICKLEN + 1); /* Login (mostly) follows nick rules. */ if(*login && !clean_nick(login)) return 0; if((exist_p = find_person(nick)) && target_p != exist_p) { char buf[BUFSIZE]; if(MyClient(exist_p)) sendto_one(exist_p, ":%s KILL %s :(Nickname regained by services)", me.name, exist_p->name); exist_p->flags |= FLAGS_KILLED; kill_client_serv_butone(NULL, exist_p, "%s (Nickname regained by services)", me.name); rb_snprintf(buf, sizeof(buf), "Killed (%s (Nickname regained by services))", me.name); exit_client(NULL, exist_p, &me, buf); } else if((exist_p = find_client(nick)) && IsUnknown(exist_p) && exist_p != target_p) { exit_client(NULL, exist_p, &me, "Overridden"); } if(*login) { /* Strip leading digits, unless it's purely numeric. */ const char *p = login; while(IsDigit(*p)) p++; if(!*p) p = login; sendto_one(target_p, form_str(RPL_LOGGEDIN), me.name, EmptyString(target_p->name) ? "*" : target_p->name, nick, user, host, p, p); } else sendto_one(target_p, form_str(RPL_LOGGEDOUT), me.name, EmptyString(target_p->name) ? "*" : target_p->name, nick, user, host); if(IsUnknown(target_p)) { struct User *user_p = make_user(target_p); if(valid & NICK_VALID) strcpy(target_p->preClient->spoofnick, nick); if(valid & USER_VALID) strcpy(target_p->preClient->spoofuser, user); if(valid & HOST_VALID) strcpy(target_p->preClient->spoofhost, host); rb_strlcpy(user_p->suser, login, NICKLEN + 1); } else { char note[NICKLEN + 10]; send_signon(NULL, target_p, nick, user, host, rb_current_time(), login); rb_snprintf(note, NICKLEN + 10, "Nick: %s", target_p->name); rb_note(target_p->localClient->F, note); } return 0; }
/* ** m_okick ** parv[1] = channel ** parv[2] = client to kick ** parv[3] = kick comment */ static int mo_okick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *who; struct Client *target_p; struct Channel *chptr; struct membership *msptr; int chasing = 0; char *comment; char *name; char *p = NULL; char *user; char text[10]; static char buf[BUFSIZE]; if(*parv[2] == '\0') { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "KICK"); return 0; } if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); comment = (EmptyString(LOCAL_COPY(parv[3]))) ? LOCAL_COPY(parv[2]) : LOCAL_COPY(parv[3]); if(strlen(comment) > (size_t) TOPICLEN) comment[TOPICLEN] = '\0'; *buf = '\0'; if((p = strchr(parv[1], ','))) *p = '\0'; name = LOCAL_COPY(parv[1]); chptr = find_channel(name); if(!chptr) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); return 0; } if((p = strchr(parv[2], ','))) *p = '\0'; user = LOCAL_COPY(parv[2]); // strtoken(&p2, parv[2], ","); if(!(who = find_chasing(source_p, user, &chasing))) { return 0; } if((target_p = find_client(user)) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, user); return 0; } if((msptr = find_channel_membership(chptr, target_p)) == NULL) { sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL), me.name, source_p->name, parv[1], parv[2]); return 0; } sendto_realops_snomask(SNO_GENERAL, L_ALL, "OKICK called for %s %s by %s!%s@%s", chptr->chname, target_p->name, source_p->name, source_p->username, source_p->host); ilog(L_MAIN, "OKICK called for %s %s by %s", chptr->chname, target_p->name, get_oper_name(source_p)); sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s", me.name, chptr->chname, who->name, comment); sendto_server(&me, chptr, CAP_TS6, NOCAPS, ":%s KICK %s %s :%s", me.id, chptr->chname, who->id, comment); remove_user_from_channel(msptr); rb_snprintf(text, sizeof(text), "K%s", who->id); /* we don't need to track NOREJOIN stuff unless it's our client being kicked */ if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN) channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN"); return 0; }