Пример #1
0
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++;
}
Пример #2
0
/*
 * * 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;
   }
Пример #3
0
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
}
Пример #4
0
/* 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));
}
Пример #5
0
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);
}
Пример #6
0
/* 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";
}
Пример #7
0
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;
}
Пример #8
0
/*
 * 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;
}
Пример #9
0
/*
 * 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;
}
Пример #10
0
/*
 * 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);
}
Пример #11
0
/*
 * 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);
}
Пример #12
0
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;
}
Пример #13
0
/*
 * 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;
}
Пример #14
0
/*
 * 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);
	}
}
Пример #15
0
/*
** 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;
}