static void addserver(adns_state ads, struct in_addr addr) { int i; struct server *ss; if(addr.s_addr == 0) addr.s_addr = htonl(INADDR_LOOPBACK); for (i=0; i<ads->nservers; i++) { if (ads->servers[i].addr.s_addr == addr.s_addr) { adns__debug(ads,-1,0, "duplicate nameserver %s ignored",inetntoa((char *)&addr)); return; } } if (ads->nservers>=MAXSERVERS) { adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inetntoa((char *)&addr)); return; } ss= ads->servers+ads->nservers; ss->addr= addr; ads->nservers++; }
/* * * get_client_name * Return the name of the client for various * tracking and * admin purposes. The main purpose of this * function is to * return the "socket host" name of the client, * if that * differs from the advertised name (other than case). * * But, this can be used to any client structure. * * * Returns: * "name[user@ip#.port]" if 'showip' is true; * * "name[sockethost]", if name and sockhost are different and * * showip is false; else * "name". * * * NOTE 1: * Watch out the allocation of "nbuf", if either * sptr->name * or sptr->sockhost gets changed into pointers instead of * * directly allocated within the structure... * * * NOTE 2: * Function return either a pointer to the structure * (sptr) or * to internal buffer (nbuf). *NEVER* use the returned * pointer * to modify what it points!!! */ char * get_client_name(aClient *sptr, int showip) { static char nbuf[HOSTLEN * 2 + USERLEN + 5]; if (MyConnect(sptr)) { switch (showip) { case TRUE: #ifdef SHOW_UH (void) ircsprintf(nbuf, "%s[%s%s@%s]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : "(+)", sptr->user ? sptr->user->username : sptr->username, inetntoa((char *) &sptr->ip)); #else (void) sprintf(nbuf, "%s[%s@%s]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : sptr->username, inetntoa((char *) &sptr->ip)); #endif break; case HIDEME: #ifdef SHOW_UH (void) ircsprintf(nbuf, "%s[%s%s@%s]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : "(+)", sptr->user ? sptr->user->username : sptr->username, "0.0.0.0"); #else (void) sprintf(nbuf, "%s[%s@%s]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : sptr->username, "0.0.0.0"); #endif break; default: if (mycmp(sptr->name, sptr->sockhost)) #ifdef USERNAMES_IN_TRACE (void) ircsprintf(nbuf, "%s[%s@%s]", sptr->name, sptr->user ? sptr->user->username : sptr->username, sptr->sockhost); #else (void) ircsprintf(nbuf, "%s[%s]", sptr->name, sptr->sockhost); #endif else return sptr->name; } return nbuf; }
void adns__vdiag(adns_state ads, const char *pfx, adns_initflags prevent, int serv, adns_query qu, const char *fmt, va_list al) { /* Fix this to log to the ircd log interface */ #if 0 const char *bef, *aft; vbuf vb; vfprintf(ads->diagfile,fmt,al); bef= " ("; aft= "\n"; if (qu && qu->query_dgram) { adns__vbuf_init(&vb); fprintf(ads->diagfile,"%sQNAME=%s, QTYPE=%s", bef, adns__diag_domain(qu->ads,-1,0, &vb, qu->query_dgram,qu->query_dglen,DNS_HDRSIZE), qu->typei ? qu->typei->rrtname : "<unknown>"); if (qu->typei && qu->typei->fmtname) fprintf(ads->diagfile,"(%s)",qu->typei->fmtname); bef=", "; aft=")\n"; adns__vbuf_free(&vb); } if (serv>=0) { fprintf(ads->diagfile,"%sNS=%s",bef,inetntoa((unsigned char *)&ads->servers[serv].addr)); bef=", "; aft=")\n"; } fputs(aft,ads->diagfile); #endif }
/* const char * * inet_ntop4(src, dst, size) * format an IPv4 address * return: * `dst' (as a const) * notes: * (1) uses no statics * (2) takes a unsigned char* not an in_addr as input * author: * Paul Vixie, 1996. */ static const char * inet_ntop4(const unsigned char *src, char *dst, unsigned int size) { if (size < 16) return NULL; return strcpy(dst, inetntoa((const char *)src)); }
static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) { struct in_addr ia; if (!inet_aton(buf,&ia)) { configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf); return; } adns__debug(ads,-1,0,"using nameserver %s",inetntoa((const char *)&ia)); addserver(ads,ia); }
/* cipntoa - Return the client IP address as a string. */ char *cipntoa(aClient *cptr) { if (cptr->hostip[0] != '\0') return cptr->hostip; else if (cptr->ip_family == AF_INET) return inetntoa((char *)&cptr->ip.ip4); else if (cptr->ip_family == AF_INET6) return inet6ntoa((char *)&cptr->ip.ip6); else return "invalid.address.family.invalid"; }
char *get_client_name(aClient *sptr, int showip) { static char nbuf[HOSTLEN * 2 + USERLEN + 5]; if (MyConnect(sptr)) { #ifdef UNIXPORT if (IsUnixSocket(sptr)) { if (showip) sprintf(nbuf, "%s[%s]", sptr->name, sptr->sockhost); else sprintf(nbuf, "%s[%s]", sptr->name, me.sockhost); } else #endif { if (showip) (void)sprintf(nbuf, "%s[%.*s@%s]", sptr->name, USERLEN, (!(sptr->flags & FLAGS_GOTID)) ? "" : sptr->auth, sptr->user ? sptr->user->sip : #ifdef INET6 inetntop(AF_INET6, (char *)&sptr->ip, ipv6string, sizeof(ipv6string)) #else inetntoa((char *)&sptr->ip) #endif ); else { if (mycmp(sptr->name, sptr->sockhost)) /* Show username for clients and * ident for others. */ sprintf(nbuf, "%s[%.*s@%s]", sptr->name, USERLEN, IsPerson(sptr) ? sptr->user->username : sptr->auth, IsPerson(sptr) ? sptr->user->host : sptr->sockhost); else return sptr->name; } } return nbuf; } return sptr->name; }
/* * send_authports * * Send the ident server a query giving "theirport , ourport". * The write is only attempted *once* so it is deemed to be a fail if the * entire write doesn't write all the data given. This shouldnt be a * problem since the socket should have a write buffer far greater than * this message to store it in should problems arise. -avalon */ void send_authports(aClient *cptr) { struct SOCKADDR_IN us, them; char authbuf[32]; SOCK_LEN_TYPE ulen, tlen; Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d", cptr, cptr->fd, cptr->authfd, cptr->status)); tlen = ulen = sizeof(us); if (getsockname(cptr->fd, (struct SOCKADDR *)&us, &ulen) || getpeername(cptr->fd, (struct SOCKADDR *)&them, &tlen)) { #ifdef USE_SYSLOG syslog(LOG_ERR, "auth get{sock,peer}name error for %s:%m", get_client_name(cptr, TRUE)); #endif goto authsenderr; } sprintf(authbuf, "%u , %u\r\n", (unsigned int)ntohs(them.SIN_PORT), (unsigned int)ntohs(us.SIN_PORT)); #ifdef INET6 Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf, inet_ntop(AF_INET6, (char *)&them.sin6_addr, ipv6string, sizeof(ipv6string)))); #else Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf, inetntoa((char *)&them.sin_addr))); #endif if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf)) { authsenderr: ircstp->is_abad++; (void)close(cptr->authfd); if (cptr->authfd == highest_fd) while (!local[highest_fd]) highest_fd--; cptr->authfd = -1; cptr->flags &= ~(FLAGS_AUTH|FLAGS_WRAUTH); return; } cptr->flags &= ~FLAGS_WRAUTH; return; }
/* * send_authports * * Send the ident server a query giving "theirport , ourport". * The write is only attempted *once* so it is deemed to be a fail if the * entire write doesn't write all the data given. This shouldnt be a * problem since the socket should have a write buffer far greater than * this message to store it in should problems arise. -avalon */ void send_authports(aClient *cptr) { struct sockaddr_in us, them; char authbuf[32]; int ulen, tlen; Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d", cptr, cptr->fd, cptr->authfd, cptr->status)); tlen = ulen = sizeof(us); if (getsockname(cptr->fd, (struct sockaddr *)&us, &ulen) || getpeername(cptr->fd, (struct sockaddr *)&them, &tlen)) { #ifdef USE_SYSLOG syslog(LOG_DEBUG, "auth get{sock,peer}name error for %s:%m", get_client_name(cptr, TRUE)); #endif authsenderr(cptr); /* cptr->flags &= ~FLAGS_WRAUTH; */ return; } (void)ircsprintf(authbuf, "%u , %u\r\n", (unsigned int)ntohs(them.sin_port), (unsigned int)ntohs(us.sin_port)); Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf, inetntoa((char *)&them.sin_addr))); if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf)) { authsenderr(cptr); return; } cptr->flags &= ~FLAGS_WRAUTH; return; }
/* * Writes a G-Line to the appropriate file. */ void gs_write(int f, char type, struct userBan *ub) { char outbuf[1024]; char cidr[4] = ""; time_t expiretime = 0; char *user = "******"; char *reason = ""; char *host = ub->h; int len; /* userban.c */ unsigned int netmask_to_cidr(unsigned int); if (ub->flags & UBAN_TEMPORARY) expiretime = ub->timeset + ub->duration; if (ub->u) user = ub->u; if (ub->reason) reason = ub->reason; if (ub->flags & (UBAN_CIDR4|UBAN_CIDR4BIG)) { host = inetntoa((char *)&ub->cidr4ip); ircsprintf(cidr, "/%d", netmask_to_cidr(ntohl(ub->cidr4mask))); } if (type == '+') len = ircsprintf(outbuf, "%c %d %s %s%s %s\n", type, (int)expiretime, user, host, cidr, reason); else len = ircsprintf(outbuf, "%c %s %s%s\n", type, user, host, cidr); write(f, outbuf, len); }
/* * Writes a K-Line to the appropriate file. */ void ks_write(int f, char type, struct userBan *ub) { char outbuf[1024]; char cidr[4] = ""; time_t expiretime = 0; char *user = "******"; char *reason = ""; char *host = ub->h; int len; if (ub->flags & UBAN_TEMPORARY) expiretime = ub->timeset + ub->duration; if (ub->u) user = ub->u; if (ub->reason) reason = ub->reason; if (ub->flags & (UBAN_CIDR4|UBAN_CIDR4BIG)) { if (ub->cidr_family == AF_INET) host = inetntoa((char *)&ub->cidr_ip); else if (ub->cidr_family == AF_INET6) host = inet6ntoa((char *)&ub->cidr_ip); ircsprintf(cidr, "/%d", ub->cidr_bits); } if (type == '+') len = ircsprintf(outbuf, "%c %d %s@%s%s %s\n", type, (int)expiretime, user, host, cidr, reason); else len = ircsprintf(outbuf, "%c %s@%s%s\n", type, user, host, cidr); write(f, outbuf, len); }
static int inetport(struct Listener* listener) { struct SOCKADDR_IN port_sin; int fd; int opt = 1; /* * At first, open a new socket */ fd = socket(AFINET, SOCK_STREAM, 0); if (-1 == fd) { report_error("opening listener socket %s:%s", get_listener_name(listener), errno); return 0; } else if ((HARD_FDLIMIT - 10) < fd) { report_error("no more connections left for listener %s:%s", get_listener_name(listener), errno); CLOSE(fd); return 0; } /* * XXX - we don't want to do all this crap for a listener * set_sock_opts(listener); */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt))) { report_error("setting SO_REUSEADDR for listener %s:%s", get_listener_name(listener), errno); CLOSE(fd); return 0; } /* * Bind a port to listen for new connections if port is non-null, * else assume it is already open and try get something from it. */ memset(&port_sin, 0, sizeof(port_sin)); port_sin.SIN_FAMILY = AFINET; port_sin.SIN_PORT = htons(listener->port); #ifdef __CYGWIN__ port_sin.sin_addr = listener->addr; if (INADDR_ANY != listener->addr.S_ADDR) { strncpy_irc(listener->vhost, inetntoa((char *)&listener->addr), HOSTLEN); listener->name = listener->vhost; } #else #ifdef IPV6 bcopy((const char*)listener->addr.S_ADDR, (char*)port_sin.SIN_ADDR.S_ADDR, sizeof(struct IN_ADDR)); if ( bcmp((char*)listener->addr.S_ADDR, &INADDRANY, sizeof(struct IN_ADDR)) == 0 ) #else port_sin.sin_addr = listener->addr; if (INADDRANY != listener->addr.s_addr) #endif { struct addrinfo *ans; int ret; char port[5]; char tmp[HOSTLEN]; /* * XXX - blocking call to getaddrinfo */ sprintf( port, "%d", listener->port); #ifdef IPV6 inetntop(AFINET, &listener->addr, tmp, HOSTLEN); #else inet_ntop(AF_INET, &listener->addr, tmp, HOSTLEN); #endif ret = getaddrinfo(tmp, port, NULL, &ans ); if( ret == 0 && ans->ai_canonname) strncpy_irc(listener->vhost, ans->ai_canonname, HOSTLEN); } #endif if (bind(fd, (struct sockaddr*) &port_sin, sizeof(port_sin))) { report_error("binding listener socket %s:%s", get_listener_name(listener), errno); CLOSE(fd); return 0; } if (listen(fd, HYBRID_SOMAXCONN)) { report_error("listen failed for %s:%s", get_listener_name(listener), errno); CLOSE(fd); return 0; } /* * XXX - this should always work, performance will suck if it doesn't */ if (!set_non_blocking(fd)) report_error(NONB_ERROR_MSG, get_listener_name(listener), errno); listener->fd = fd; return 1; }
/* * start_auth * * Flag the client to show that an attempt to contact the ident server on * the client's host. The connect and subsequently the socket are all put * into 'non-blocking' mode. Should the connect or any later phase of the * identifing process fail, it is aborted and the user is given a username * of "unknown". */ void start_auth(aClient *cptr) { #ifndef NO_IDENT struct SOCKADDR_IN us, them; SOCK_LEN_TYPE ulen, tlen; # if defined(USE_IAUTH) if ((iauth_options & XOPT_REQUIRED) && adfd < 0) return; # endif Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d", cptr, cptr->fd, cptr->status)); if ((cptr->authfd = socket(AFINET, SOCK_STREAM, 0)) == -1) { # ifdef USE_SYSLOG syslog(LOG_ERR, "Unable to create auth socket for %s:%m", get_client_name(cptr,TRUE)); # endif Debug((DEBUG_ERROR, "Unable to create auth socket for %s:%s", get_client_name(cptr, TRUE), strerror(get_sockerr(cptr)))); ircstp->is_abad++; return; } if (cptr->authfd >= (MAXCONNECTIONS - 2)) { sendto_flag(SCH_ERROR, "Can't allocate fd for auth on %s", get_client_name(cptr, TRUE)); (void)close(cptr->authfd); return; } set_non_blocking(cptr->authfd, cptr); /* get remote host peer - so that we get right interface -- jrg */ tlen = ulen = sizeof(us); if (getpeername(cptr->fd, (struct sockaddr *)&them, &tlen) < 0) { /* we probably don't need this error message -kalt */ report_error("getpeername for auth request %s:%s", cptr); close(cptr->authfd); cptr->authfd = -1; return; } them.SIN_FAMILY = AFINET; /* We must bind the local end to the interface that they connected to: The local system might have more than one network address, and RFC931 check only sends port numbers: server takes IP addresses from query socket -- jrg */ (void)getsockname(cptr->fd, (struct sockaddr *)&us, &ulen); us.SIN_FAMILY = AFINET; # if defined(USE_IAUTH) if (adfd >= 0) { char abuf[BUFSIZ]; # ifdef INET6 sprintf(abuf, "%d C %s %u ", cptr->fd, inetntop(AF_INET6, (char *)&them.sin6_addr, ipv6string, sizeof(ipv6string)), ntohs(them.SIN_PORT)); sprintf(abuf+strlen(abuf), "%s %u", inetntop(AF_INET6, (char *)&us.sin6_addr, ipv6string, sizeof(ipv6string)), ntohs(us.SIN_PORT)); # else sprintf(abuf, "%d C %s %u ", cptr->fd, inetntoa((char *)&them.sin_addr),ntohs(them.SIN_PORT)); sprintf(abuf+strlen(abuf), "%s %u", inetntoa((char *)&us.sin_addr), ntohs(us.SIN_PORT)); # endif if (sendto_iauth(abuf) == 0) { close(cptr->authfd); cptr->authfd = -1; cptr->flags |= FLAGS_XAUTH; return; } } # endif # ifdef INET6 Debug((DEBUG_NOTICE,"auth(%x) from %s %x %x", cptr, inet_ntop(AF_INET6, (char *)&us.sin6_addr, ipv6string, sizeof(ipv6string)), us.sin6_addr.s6_addr[14], us.sin6_addr.s6_addr[15])); # else Debug((DEBUG_NOTICE,"auth(%x) from %s", cptr, inetntoa((char *)&us.sin_addr))); # endif them.SIN_PORT = htons(113); us.SIN_PORT = htons(0); /* bind assigns us a port */ if (bind(cptr->authfd, (struct SOCKADDR *)&us, ulen) >= 0) { (void)getsockname(cptr->fd, (struct SOCKADDR *)&us, &ulen); # ifdef INET6 Debug((DEBUG_NOTICE,"auth(%x) to %s", cptr, inet_ntop(AF_INET6, (char *)&them.sin6_addr, ipv6string, sizeof(ipv6string)))); # else Debug((DEBUG_NOTICE,"auth(%x) to %s", cptr, inetntoa((char *)&them.sin_addr))); # endif (void)alarm((unsigned)4); if (connect(cptr->authfd, (struct SOCKADDR *)&them, tlen) == -1 && errno != EINPROGRESS) { # ifdef INET6 Debug((DEBUG_ERROR, "auth(%x) connect failed to %s - %d", cptr, inet_ntop(AF_INET6, (char *)&them.sin6_addr, ipv6string, sizeof(ipv6string)), errno)); # else Debug((DEBUG_ERROR, "auth(%x) connect failed to %s - %d", cptr, inetntoa((char *)&them.sin_addr), errno)); # endif ircstp->is_abad++; /* * No error report from this... */ (void)alarm((unsigned)0); (void)close(cptr->authfd); cptr->authfd = -1; return; } (void)alarm((unsigned)0); } else { report_error("binding stream socket for auth request %s:%s", cptr); # ifdef INET6 Debug((DEBUG_ERROR,"auth(%x) bind failed on %s port %d - %d", cptr, inet_ntop(AF_INET6, (char *)&us.sin6_addr, ipv6string, sizeof(ipv6string)), ntohs(us.SIN_PORT), errno)); # else Debug((DEBUG_ERROR,"auth(%x) bind failed on %s port %d - %d", cptr, inetntoa((char *)&us.sin_addr), ntohs(us.SIN_PORT), errno)); # endif } cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH); if (cptr->authfd > highest_fd) highest_fd = cptr->authfd; #endif return; }
/* * read_iauth * * read and process data from the authentication slave process. */ void read_iauth(void) { static char obuf[READBUF_SIZE+1], last = '?'; static int olen = 0, ia_dbg = 0; char buf[READBUF_SIZE+1], *start, *end, tbuf[BUFSIZ]; aClient *cptr; int i; if (adfd == -1) { olen = 0; return; } while (1) { if (olen) bcopy(obuf, buf, olen); if ((i = recv(adfd, buf+olen, READBUF_SIZE-olen, 0)) <= 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { sendto_flag(SCH_AUTH, "Aiiie! lost slave authentication process (errno = %d)", errno); close(adfd); adfd = -1; olen = 0; start_iauth(0); } break; } olen += i; buf[olen] = '\0'; start = buf; while ((end = index(start, '\n'))) { *end++ = '\0'; last = *start; if (*start == '>') { sendto_flag(SCH_AUTH, "%s", start+1); start = end; continue; } if (*start == 'G') { ia_dbg = atoi(start+2); if (ia_dbg) sendto_flag(SCH_AUTH,"ia_dbg = %d",ia_dbg); start = end; continue; } if (*start == 'O') /* options */ { iauth_options = 0; if (strchr(start+2, 'A')) iauth_options |= XOPT_EARLYPARSE; if (strchr(start+2, 'R')) iauth_options |= XOPT_REQUIRED; if (strchr(start+2, 'T')) iauth_options |= XOPT_NOTIMEOUT; if (strchr(start+2, 'W')) iauth_options |= XOPT_EXTWAIT; if (iauth_options) sendto_flag(SCH_AUTH, "iauth options: %x", iauth_options); start = end; continue; } if (*start == 'V') /* version */ { if (iauth_version) MyFree(iauth_version); iauth_version = mystrdup(start+2); sendto_flag(SCH_AUTH, "iauth version %s running.", iauth_version); start = end; sendto_iauth("0 M %s", me.name); continue; } if (*start == 'a') { aExtCf *ectmp; while ((ectmp = iauth_conf)) { iauth_conf = iauth_conf->next; MyFree(ectmp->line); MyFree(ectmp); } /* little lie.. ;) */ sendto_flag(SCH_AUTH, "New iauth configuration."); start = end; continue; } if (*start == 'A') { aExtCf **ectmp = &iauth_conf; while (*ectmp) ectmp = &((*ectmp)->next); *ectmp = (aExtCf *) MyMalloc(sizeof(aExtCf)); (*ectmp)->line = mystrdup(start+2); (*ectmp)->next = NULL; start = end; continue; } if (*start == 's') { aExtData *ectmp; while ((ectmp = iauth_stats)) { iauth_stats = iauth_stats->next; MyFree(ectmp->line); MyFree(ectmp); } iauth_stats = (aExtData *) MyMalloc(sizeof(aExtData)); iauth_stats->line = MyMalloc(60); sprintf(iauth_stats->line, "iauth modules statistics (%s)", myctime(timeofday)); iauth_stats->next = (aExtData *) MyMalloc(sizeof(aExtData)); iauth_stats->next->line = MyMalloc(60); sprintf(iauth_stats->next->line, "spawned: %d, current options: %X (%.11s)", iauth_spawn, iauth_options, (iauth_version) ? iauth_version : "???"); iauth_stats->next->next = NULL; start = end; continue; } if (*start == 'S') { aExtData **ectmp = &iauth_stats; while (*ectmp) ectmp = &((*ectmp)->next); *ectmp = (aExtData *) MyMalloc(sizeof(aExtData)); (*ectmp)->line = mystrdup(start+2); (*ectmp)->next = NULL; start = end; continue; } if (*start != 'U' && *start != 'u' && *start != 'o' && *start != 'K' && *start != 'k' && *start != 'D') { sendto_flag(SCH_AUTH, "Garbage from iauth [%s]", start); sendto_iauth("-1 E Garbage [%s]", start); /* ** The above should never happen, but i've seen it ** occasionnally, so let's try to get more info ** about it! -kalt */ sendto_flag(SCH_AUTH, "last=%u start=%x end=%x buf=%x olen=%d i=%d", last, start, end, buf, olen, i); sendto_iauth( "-1 E last=%u start=%x end=%x buf=%x olen=%d i=%d", last, start, end, buf, olen, i); start = end; continue; } if ((cptr = local[i = atoi(start+2)]) == NULL) { /* this is fairly common and can be ignored */ if (ia_dbg) { sendto_flag(SCH_AUTH, "Client %d is gone.", i); sendto_iauth("%d E Gone [%s]", i, start); } start = end; continue; } #ifndef INET6 sprintf(tbuf, "%c %d %s %u ", start[0], i, inetntoa((char *)&cptr->ip), cptr->port); #else sprintf(tbuf, "%c %d %s %u ", start[0], i, inetntop(AF_INET6, (char *)&cptr->ip, ipv6string, sizeof(ipv6string)), cptr->port); #endif if (strncmp(tbuf, start, strlen(tbuf))) { /* this is fairly common and can be ignored */ if (ia_dbg) { sendto_flag(SCH_AUTH, "Client mismatch: %d [%s] != [%s]", i, start, tbuf); sendto_iauth("%d E Mismatch [%s] != [%s]", i, start, tbuf); } start = end; continue; } if (start[0] == 'U') { if (*(start+strlen(tbuf)) == '\0') { sendto_flag(SCH_AUTH, "Null U message! %d [%s]", i, start); sendto_iauth("%d E Null U [%s]", i, start); start = end; continue; } if (cptr->auth != cptr->username) { istat.is_authmem -= strlen(cptr->auth) + 1; istat.is_auth -= 1; MyFree(cptr->auth); } cptr->auth = mystrdup(start+strlen(tbuf)); set_clean_username(cptr); cptr->flags |= FLAGS_GOTID; } else if (start[0] == 'u') { if (*(start+strlen(tbuf)) == '\0') { sendto_flag(SCH_AUTH, "Null u message! %d [%s]", i, start); sendto_iauth("%d E Null u [%s]", i, start); start = end; continue; } if (cptr->auth != cptr->username) { istat.is_authmem -= strlen(cptr->auth) + 1; istat.is_auth -= 1; MyFree(cptr->auth); } cptr->auth = MyMalloc(strlen(start+strlen(tbuf)) + 2); *cptr->auth = '-'; strcpy(cptr->auth+1, start+strlen(tbuf)); set_clean_username(cptr); cptr->flags |= FLAGS_GOTID; } else if (start[0] == 'o') { if (!WaitingXAuth(cptr)) { sendto_flag(SCH_AUTH, "Early o message discarded!"); sendto_iauth("%d E Early o [%s]", i,start); start = end; continue; } if (cptr->user == NULL) { /* just to be safe */ sendto_flag(SCH_AUTH, "Ack! cptr->user is NULL"); start = end; continue; } strncpyzt(cptr->user->username, tbuf, USERLEN+1); } else if (start[0] == 'D') { /*authentication finished*/ ClearXAuth(cptr); SetDoneXAuth(cptr); if (WaitingXAuth(cptr)) { ClearWXAuth(cptr); register_user(cptr, cptr, cptr->name, cptr->user->username); } else ClearWXAuth(cptr); } else { char *reason; /* Copy kill reason received from iauth */ reason = strstr(start, " :"); if (reason && (reason + 2 != '\0')) { if (cptr->reason) { MyFree(cptr->reason); } cptr->reason = mystrdup(reason + 2); } /* ** mark for kill, because it cannot be killed ** yet: we don't even know if this is a server ** or a user connection! */ if (start[0] == 'K') cptr->exitc = EXITC_AREF; else cptr->exitc = EXITC_AREFQ; /* should also check to make sure it's still an unregistered client.. */ /* Finally, working after registration. --B. */ if (IsRegisteredUser(cptr)) { if (cptr->exitc == EXITC_AREF) { sendto_flag(SCH_LOCAL, "Denied after connection " "from %s.", get_client_host(cptr)); } (void) exit_client(cptr, cptr, &me, cptr->reason ? cptr->reason : "Denied access"); } } start = end; } olen -= start - buf; if (olen) memcpy(obuf, start, olen); } }
/* ** m_ltrace - LimitedTRACE... like m_trace() but doesn't return TRACEUSER, TRACEUNKNOWN, or TRACECLASS ** parv[0] = sender prefix ** parv[1] = servername */ int m_ltrace(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) { int i; struct Client *acptr = NULL; char *tname; int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS]; int cnt = 0, wilds, dow; static time_t now; if (check_registered(sptr)) return 0; #ifdef SERVERHIDE if (!IsAnOper(sptr)) return 0; #endif if (parc > 2) if (hunt_server(cptr, sptr, ":%s LTRACE %s :%s", 2, parc, parv)) return 0; if (parc > 1) tname = parv[1]; else tname = me.name; switch (hunt_server(cptr, sptr, ":%s LTRACE :%s", 1, parc, parv)) { case HUNTED_PASS: /* note: gets here only if parv[1] exists */ { struct Client *ac2ptr; ac2ptr = next_client(GlobalClientList, tname); if (ac2ptr) sendto_one(sptr, form_str(RPL_TRACELINK), me.name, parv[0], ircd_version, debugmode, tname, ac2ptr->from->name); else sendto_one(sptr, form_str(RPL_TRACELINK), me.name, parv[0], ircd_version, debugmode, tname, "ac2ptr_is_NULL!!"); return 0; } case HUNTED_ISME: break; default: return 0; } if(MyClient(sptr)) sendto_realops_flags(FLAGS_SPY, "ltrace requested by %s (%s@%s) [%s]", sptr->name, sptr->username, sptr->host, sptr->user->server); doall = (parv[1] && (parc > 1)) ? match(tname, me.name): TRUE; wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?'); dow = wilds || doall; if(!IsAnOper(sptr) || !dow) /* non-oper traces must be full nicks */ /* lets also do this for opers tracing nicks */ { const char* name; const char* ip; int c_class; acptr = hash_find_client(tname,(struct Client *)NULL); if(!acptr || !IsPerson(acptr)) { /* this should only be reached if the matching target is this server */ sendto_one(sptr, form_str(RPL_ENDOFTRACE),me.name, parv[0], tname); return 0; } name = get_client_name(acptr, FALSE); ip = inetntoa((char*) &acptr->ip); c_class = get_client_class(acptr); if (IsAnOper(acptr)) { sendto_one(sptr, form_str(RPL_TRACEOPERATOR), me.name, parv[0], c_class, name, IsAnOper(sptr)?ip:(IsIPHidden(acptr)?"255.255.255.255":ip), now - acptr->lasttime, (acptr->user)?(now - acptr->user->last):0); } sendto_one(sptr, form_str(RPL_ENDOFTRACE),me.name, parv[0], tname); return 0; } for (i = 0; i < MAXCONNECTIONS; i++) link_s[i] = 0, link_u[i] = 0; if (dow && LIFESUX && !IsOper(sptr)) { sendto_one(sptr,form_str(RPL_LOAD2HI),me.name,parv[0]); return 0; } /* * Count up all the servers and clients in a downlink. */ if (doall) { for (acptr = GlobalClientList; acptr; acptr = acptr->next) { if (IsServer(acptr)) ++link_s[acptr->from->fd]; } } /* report all direct connections */ now = time(NULL); for (i = 0; i <= highest_fd; i++) { const char* name; const char* ip; int c_class; if (!(acptr = local[i])) /* Local Connection? */ continue; if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsAnOper(sptr)) && !IsAnOper(acptr) && (acptr != sptr)) continue; if (!doall && wilds && !match(tname, acptr->name)) continue; if (!dow && irccmp(tname, acptr->name)) continue; name = get_client_name(acptr, FALSE); ip = inetntoa((const char*) &acptr->ip); c_class = get_client_class(acptr); switch(acptr->status) { case STAT_HANDSHAKE: #ifdef HIDE_SERVERS_IPS name=get_client_name(acptr, MASK_IP); #endif sendto_one(sptr, form_str(RPL_TRACEHANDSHAKE), me.name, parv[0], c_class, name); cnt++; break; case STAT_CONNECTING: #ifdef HIDE_SERVERS_IPS name=get_client_name(acptr, MASK_IP); #endif sendto_one(sptr, form_str(RPL_TRACECONNECTING), me.name, parv[0], c_class, name); cnt++; break; case STAT_ME: break; case STAT_CLIENT: /* Well, most servers don't have a LOT of OPERs... let's show them too */ if ((IsAnOper(sptr) && (MyClient(sptr) || !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) { if (IsAnOper(acptr)) sendto_one(sptr, form_str(RPL_TRACEOPERATOR), me.name, parv[0], c_class, name, IsAnOper(sptr)?ip:(IsIPHidden(acptr)?"255.255.255.255":ip), now - acptr->lasttime, (acptr->user)?(now - acptr->user->last):0); cnt++; } break; case STAT_SERVER: #if 0 if (acptr->serv->user) sendto_one(sptr, form_str(RPL_TRACESERVER), me.name, parv[0], c_class, link_s[i], link_u[i], name, acptr->serv->by, acptr->serv->user->username, acptr->serv->user->host, now - acptr->lasttime); else #endif #ifdef HIDE_SERVERS_IPS name=get_client_name(acptr, MASK_IP); #endif sendto_one(sptr, form_str(RPL_TRACESERVER), me.name, parv[0], c_class, link_s[i], link_u[i], name, *(acptr->serv->by) ? acptr->serv->by : "*", "*", me.name, now - acptr->lasttime); cnt++; break; default: /* ...we actually shouldn't come here... --msa */ sendto_one(sptr, form_str(RPL_TRACENEWTYPE), me.name, parv[0], name); cnt++; break; } } /* * Add these lines to summarize the above which can get rather long * and messy when done remotely - Avalon */ if (!IsAnOper(sptr) || !cnt) { if (cnt) return 0; /* let the user have some idea that its at the end of the * trace */ sendto_one(sptr, form_str(RPL_TRACESERVER), me.name, parv[0], 0, link_s[me.fd], link_u[me.fd], me.name, "*", "*", me.name); sendto_one(sptr, form_str(RPL_ENDOFTRACE),me.name, parv[0],tname); return 0; } sendto_one(sptr, form_str(RPL_ENDOFTRACE),me.name, parv[0],tname); return 0; }