Beispiel #1
0
void cr_sendresponse(struct Client * cptr, struct ConfItem * c_conf, char * chall, char* salt) {
  struct ConfItem* n_conf = find_conf_by_name(cptr->name, CONF_NOCONNECT_SERVER);
  char work[PASSWDLEN*2], hash[40];
  strncpy_irc(work, chall, PASSWDLEN + 1);
  strncpy_irc(work + strlen(work), c_conf->passwd ? libshadow_md5_crypt(c_conf->passwd, salt) : "", PASSWDLEN + 1);
  cr_hashstring(work, hash);
  if (!IsUnknown(cptr) || (strcmp(cptr->passwd, n_conf->passwd) == 0))
    {
      sendto_one(cptr, "RESP %s", hash);
      SetResponded(cptr);
      sendto_ops_flag(UMODE_EXTERNAL, "Sent password response to %s", cptr->name);
    }
  else
    {
      strncpy_irc(cptr->response, hash, 40);
    }
}
Beispiel #2
0
void cr_gotresponse(struct Client * cptr, char * resp) {
  struct ConfItem * n_conf;
  char work[PASSWDLEN*2], hash[36];
  n_conf = find_conf_by_name(cptr->name, CONF_NOCONNECT_SERVER);
  if (n_conf && cptr->passwd[0]) {
    strncpy_irc(work, cptr->passwd, PASSWDLEN + 1);
    strncpy_irc(work + strlen(work), n_conf->passwd ? n_conf->passwd : "", PASSWDLEN + 1);
    cr_hashstring(work, hash);
    if (!strcmp(resp, hash)) {
      strncpy_irc(cptr->passwd, n_conf->passwd, PASSWDLEN + 1);
      sendto_ops_flag(UMODE_SEEROUTING, "Got a good password response from %s", cptr->name);
      /* OK, do we have a response pending ourself? */
      if (cptr->response[0] && !Responded(cptr))
	{
	  sendto_one(cptr, "RESP %s", cptr->response);
	  cptr->response[0] = '\0';
	  SetResponded(cptr);
	  sendto_ops_flag(UMODE_EXTERNAL, "Sent password response to %s", cptr->name);
	}
    } else {
      sendto_ops_flag(UMODE_SEEROUTING, "Failed password response from %s", cptr->name);
    }
  }
}
/*
 * m_challenge - generate RSA challenge for wouldbe oper
 * parv[0] = sender prefix
 * parv[1] = operator to challenge for, or +response
 *
 */
static void
m_challenge(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	char *challenge;
	dlink_node *ptr;
	struct ConfItem *aconf, *oconf;
	if(!(source_p->user) || !source_p->localClient)
		return;

	/* if theyre an oper, reprint oper motd and ignore */
	if(IsOper(source_p))
	{
		sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, parv[0]);
		SendMessageFile(source_p, &ConfigFileEntry.opermotd);
		return;
	}

	if(*parv[1] == '+')
	{
		/* Ignore it if we aren't expecting this... -A1kmm */
		if(!source_p->user->response)
			return;

		if(irccmp(source_p->user->response, ++parv[1]))
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			log_foper(source_p, source_p->user->auth_oper);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Failed OPER attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return;
		}

		if((aconf = find_conf_by_name(source_p->user->auth_oper, CONF_OPERATOR)) == NULL)
		{
			sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
			log_foper(source_p, source_p->user->auth_oper);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return;
		}

		ptr = source_p->localClient->confs.head;
		oconf = ptr->data;
		detach_conf(source_p, oconf);

		if(attach_conf(source_p, aconf) != 0)
		{
			sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
				   me.name, source_p->name);
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed CHALLENGE attempt by %s (%s@%s) can't attach conf!",
					     source_p->name, source_p->username, source_p->host);
			log_foper(source_p, source_p->user->auth_oper);

			attach_conf(source_p, oconf);
			return;
		}

		oper_up(source_p, aconf);

		ilog(L_TRACE, "OPER %s by %s!%s@%s",
		     source_p->user->auth_oper, source_p->name, source_p->username, source_p->host);
		log_oper(source_p, source_p->user->auth_oper);

		MyFree(source_p->user->response);
		MyFree(source_p->user->auth_oper);
		source_p->user->response = NULL;
		source_p->user->auth_oper = NULL;
		return;
	}

	MyFree(source_p->user->response);
	MyFree(source_p->user->auth_oper);
	source_p->user->response = NULL;
	source_p->user->auth_oper = NULL;

	if(!(aconf = find_conf_exact(parv[1], source_p->username, source_p->host,
				     CONF_OPERATOR)) &&
	   !(aconf = find_conf_exact(parv[1], source_p->username,
				     source_p->localClient->sockhost, CONF_OPERATOR)))
	{
		sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
		log_foper(source_p, parv[1]);

		if(ConfigFileEntry.failed_oper_notice)
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		return;
	}

	if(!aconf->rsa_public_key)
	{
		sendto_one(source_p, ":%s NOTICE %s :I'm sorry, PK authentication "
			   "is not enabled for your oper{} block.", me.name, parv[0]);
		return;
	}

	if(!generate_challenge(&challenge, &(source_p->user->response), aconf->rsa_public_key))
	{
		sendto_one(source_p, form_str(RPL_RSACHALLENGE), me.name, parv[0], challenge);
	}

	DupString(source_p->user->auth_oper, aconf->name);
	MyFree(challenge);
	return;
}
Beispiel #4
0
/*
 * mo_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
static void
mo_connect(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	int port;
	int tmpport;
	struct ConfItem *aconf;
	struct Client *target_p;

	/* always privileged with handlers */

	if(MyConnect(source_p) && !IsOperRemote(source_p) && parc > 3)
	{
		sendto_one(source_p, ":%s NOTICE %s :You need remote = yes;", me.name, parv[0]);
		return;
	}

	if(hunt_server(client_p, source_p, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
	{
		return;
	}

	if(*parv[1] == '\0')
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "CONNECT");
		return;
	}

	if((target_p = find_server(parv[1])))
	{
		sendto_one(source_p, ":%s NOTICE %s :Connect: Server %s already exists from %s.",
			   me.name, parv[0], parv[1], target_p->from->name);
		return;
	}

	/*
	 * try to find the name, then host, if both fail notify ops and bail
	 */
	if(!(aconf = find_conf_by_name(parv[1], CONF_SERVER)))
	{
		if(!(aconf = find_conf_by_host(parv[1], CONF_SERVER)))
		{
			sendto_one(source_p,
				   "NOTICE %s :Connect: Host %s not listed in ircd.conf",
				   parv[0], parv[1]);
			return;
		}
	}
	s_assert(0 != aconf);
	/*
	 * Get port number from user, if given. If not specified,
	 * use the default form configuration structure. If missing
	 * from there, then use the precompiled default.
	 */
	tmpport = port = aconf->port;
	if(parc > 2 && !EmptyString(parv[2]))
	{
		if((port = atoi(parv[2])) <= 0)
		{
			sendto_one(source_p, "NOTICE %s :Connect: Illegal port number", parv[0]);
			return;
		}
	}
	else if(port <= 0 && (port = PORTNUM) <= 0)
	{
		sendto_one(source_p, ":%s NOTICE %s :Connect: missing port number",
			   me.name, parv[0]);
		return;
	}
	/*
	 * Notify all operators about remote connect requests
	 */

	ilog(L_TRACE, "CONNECT From %s : %s %s", parv[0], parv[1], parv[2] ? parv[2] : "");

	aconf->port = port;
	/*
	 * at this point we should be calling connect_server with a valid
	 * C:line and a valid port in the C:line
	 */
	if(serv_connect(aconf, source_p))
	{
#ifndef HIDE_SERVERS_IPS
		if(IsOperAdmin(source_p))
			sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
				   me.name, parv[0], aconf->host, aconf->name, aconf->port);
		else
#endif
			sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s.%d",
				   me.name, parv[0], aconf->name, aconf->port);

	}
	else
	{
		sendto_one(source_p, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
			   me.name, parv[0], aconf->name, aconf->port);

	}
	/*
	 * client is either connecting with all the data it needs or has been
	 * destroyed
	 */
	aconf->port = tmpport;
}
Beispiel #5
0
/*
 * ms_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
static void
ms_connect(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	int port;
	int tmpport;
	struct ConfItem *aconf;
	struct Client *target_p;

	if(hunt_server(client_p, source_p, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
	{
		return;
	}

	if(*parv[1] == '\0')
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "CONNECT");
		return;
	}

	if((target_p = find_server(parv[1])))
	{
		sendto_one(source_p, ":%s NOTICE %s :Connect: Server %s %s %s.",
			   me.name, parv[0], parv[1], "already exists from", target_p->from->name);
		return;
	}

	/*
	 * try to find the name, then host, if both fail notify ops and bail
	 */
	if(!(aconf = find_conf_by_name(parv[1], CONF_SERVER)))
	{
		if(!(aconf = find_conf_by_host(parv[1], CONF_SERVER)))
		{
			sendto_one(source_p,
				   ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
				   me.name, parv[0], parv[1]);
			return;
		}
	}
	s_assert(0 != aconf);
	/*
	 * Get port number from user, if given. If not specified,
	 * use the default form configuration structure. If missing
	 * from there, then use the precompiled default.
	 */
	tmpport = port = aconf->port;
	if(parc > 2 && !EmptyString(parv[2]))
	{
		port = atoi(parv[2]);

		/* if someone sends port 0, and we have a config port.. use it */
		if(port == 0 && aconf->port)
			port = aconf->port;
		else if(port <= 0)
		{
			sendto_one(source_p, ":%s NOTICE %s :Connect: Illegal port number",
				   me.name, parv[0]);
			return;
		}
	}
	else if(port <= 0 && (port = PORTNUM) <= 0)
	{
		sendto_one(source_p, ":%s NOTICE %s :Connect: missing port number",
			   me.name, parv[0]);
		return;
	}
	/*
	 * Notify all operators about remote connect requests
	 */
	sendto_wallops_flags(UMODE_WALLOP, &me,
			     "Remote CONNECT %s %d from %s", parv[1], port, source_p->name);
	sendto_server(NULL, NULL, NOCAPS, NOCAPS,
		      ":%s WALLOPS :Remote CONNECT %s %d from %s",
		      me.name, parv[1], port, source_p->name);

	ilog(L_TRACE, "CONNECT From %s : %s %d", parv[0], parv[1], port);

	aconf->port = port;
	/*
	 * at this point we should be calling connect_server with a valid
	 * C:line and a valid port in the C:line
	 */
	if(serv_connect(aconf, source_p))
		sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s.%d",
			   me.name, parv[0], aconf->name, aconf->port);
	else
		sendto_one(source_p, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
			   me.name, parv[0], aconf->name, aconf->port);
	/*
	 * client is either connecting with all the data it needs or has been
	 * destroyed
	 */
	aconf->port = tmpport;
}
int m_chall(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  static char blank[] = "";
  char* salt = parc > 4 ? parv[4] : blank;
  char* chall = parc > 3 ? parv[3] : blank;
  char* remote_host = parc > 2 ? parv[2] : blank;
  char* host = parc > 1 ? parv[1] : blank;
  struct ConfItem *n_conf, *c_conf;
  struct Client* acptr;

  if (IsPerson(sptr))
    {
      if (IsServer(cptr))
        {
          sendto_ops_flag(UMODE_SERVNOTICE,"CHALL command from remote user %s -- %s is a hacked server",
				 get_client_name(sptr,HIDE_IP),
				 get_client_name(cptr,HIDE_IP));
        }
      else
        {
          sendto_one(sptr, form_str(ERR_UNKNOWNCOMMAND),
                     me.name, parv[0], "CHALL");
        }
      return 0;
    }

  /* If we know this, we shouldn't be getting a chall */
  if (IsPerson(cptr) || IsServer(cptr)) 
    return 0;

  /* What are they trying to auth against, is it me? */
  if (irccmp(remote_host, me.name) != 0)
    {
      sendto_one(cptr, "ERROR :I am %s, not %s", me.name, remote_host);
      sendto_ops_flag(UMODE_SERVCONNECT, "Server claiming to be %s challenged thinking I was %s, rejected", host, remote_host);
      return exit_client(cptr, cptr, &me, "Sorry, wrong number");
    }

  if ((acptr = find_server(host)))
    {
      sendto_one(cptr,"ERROR :Server %s already exists", host);
      if (!(acptr->from->caps & CAP_SERVICES)) /* If it's connected to services, it's actually a server jupe. Silently ignore. */
	sendto_ops_flag(UMODE_EXTERNAL, "Challenge for %s rejected, server already exists",
			host);
      return exit_client(cptr, cptr, &me, "Server already exists");
    }

  sendto_ops_flag(UMODE_SERVCONNECT, "CHALL received, trying to use N:line for %s", host);

  if (parc < 5)
    {
      sendto_one(cptr, "ERROR: Invalid challenge");
      sendto_ops_flag(UMODE_SERVCONNECT, "Invalid CHALL from remote host for %s", host);
      return 0;
    }

  /* See if we got c and n lines. */
  if (!(n_conf = find_conf_by_name(host, CONF_NOCONNECT_SERVER))) {
    sendto_ops_flag(UMODE_SERVCONNECT, "Challenge rejected. No N line for server %s", host);
    logprintf(L_NOTICE, "Challenge rejected. No N line for server %s", host);
    sendto_one(cptr, "ERROR :Access denied. No N line"); 
    return exit_client(cptr, cptr, cptr, "Access denied. No N line");    
  } 

  if (!(c_conf = find_conf_by_name(host, CONF_CONNECT_SERVER))) {
    sendto_ops_flag(UMODE_SERVCONNECT, "Challenge rejected. No C line for server %s", host);
    logprintf(L_NOTICE, "Challenge rejected. No C line for server %s", host);
    sendto_one(cptr, "ERROR :Access denied. No C line");
    return exit_client(cptr, cptr, cptr, "Access denied. No C line");    
  }
  
  /* Check if the ip matches the c/n IPs */
#ifdef IPV6
  if((memcmp((char*)cptr->ip.S_ADDR, (char*)c_conf->ipnum.S_ADDR, sizeof(struct IN_ADDR) != 0)) ||
        (memcmp((char*)cptr->ip.S_ADDR, (char*)n_conf->ipnum.S_ADDR,  sizeof(struct IN_ADDR)) != 0))
  {
#else
  if ( (cptr->ip.s_addr != c_conf->ipnum.s_addr) || (cptr->ip.s_addr != n_conf->ipnum.s_addr)) {
#endif
    sendto_ops_flag(UMODE_SERVCONNECT, "Challenge rejected. C/N line IP doesn't match connection");
    logprintf(L_NOTICE, "Challenge rejected. C/N line IP doesn't match connection");
    sendto_one(cptr, "ERROR :Access denied. C/N line don't match you"); 
    return exit_client(cptr, cptr, cptr, "Access denied. C/N line don't match");        
  }
  
  /* Ok, it got c/n lines and correct ip, lets challenge it back */
  if (!Challenged(cptr))
    cr_sendchallenge(cptr, n_conf);

  /* And send a response. */
  cr_sendresponse(cptr, c_conf, chall, salt);

  /* check for TS as in m_pass */
  if (parc > 5)
    {
      if (0 == irccmp(parv[5], "TS"))
        cptr->tsinfo = TS_DOESTS;
    }
  return 0;
}
Beispiel #7
0
/*
 * m_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
int m_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  int              port;
  int              tmpport;
  struct ConfItem* aconf;
  struct Client*   acptr;

  if (!IsPrivileged(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return -1;
    }

  if (IsLocOp(sptr) && parc > 3) {
    /* 
     * Only allow LocOps to make local CONNECTS --SRB
     */
    return 0;
  }

  if (MyConnect(sptr) && !IsOperRemote(sptr) && parc > 3)
    {
      sendto_one(sptr,":%s NOTICE %s :You have no R flag", me.name, parv[0]);
      return 0;
    }

  if (hunt_server(cptr, sptr,
                  ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
    return 0;

  if (parc < 2 || *parv[1] == '\0')
    {
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "CONNECT");
      return -1;
    }

  if ((acptr = find_server(parv[1])))
    {
      sendto_one(sptr, ":%s NOTICE %s :Connect: Server %s %s %s.",
                 me.name, parv[0], parv[1], "already exists from",
                 acptr->from->name);
      return 0;
    }

  /*
   * try to find the name, then host, if both fail notify ops and bail
   */
  if (!(aconf = find_conf_by_name(parv[1], CONF_CONNECT_SERVER))) {
#ifndef HIDE_SERVERS_IPS
    if (!(aconf = find_conf_by_host(parv[1], CONF_CONNECT_SERVER))) {
#endif
      sendto_one(sptr,
                 "NOTICE %s :Connect: Host %s not listed in ircd.conf",
                 parv[0], parv[1]);
      return 0;
#ifndef HIDE_SERVERS_IPS
    }
#endif
  }
  assert(0 != aconf);
  /*
   * Get port number from user, if given. If not specified,
   * use the default form configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = aconf->port;
  if (parc > 2 && !EmptyString(parv[2]))
    {
#ifdef NEG_PORT
      if ((port = atoi(parv[2])) < 0)
#else    
      if ((port = atoi(parv[2])) <= 0)
#endif      
        {
          sendto_one(sptr, "NOTICE %s :Connect: Illegal port number",
                     parv[0]);
          return 0;
        }
    }
#ifdef NEG_PORT
  else if (port < 0 && (port = PORTNUM) <= 0)
#else    
  else if (port <= 0 && (port = PORTNUM) <= 0)
#endif  
    {
      sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number",
                 me.name, parv[0]);
      return 0;
    }
#ifdef NEG_PORT
  if (port == 0)
    port = tmpport; /* From conf */
  if (port == 0)
    port = PORTNUM; /* Default if there wasn't one set in conf */
#endif
    
  /*
   * Notify all operators about remote connect requests
   */
  if (!IsAnOper(cptr))
    {
      sendto_ops_butone(NULL, &me,
                        ":%s WALLOPS :Remote CONNECT %s %s from %s",
                        me.name, parv[1], parv[2] ? parv[2] : "",
                        get_client_name(sptr, FALSE));

      irclog(L_TRACE, "CONNECT From %s : %s %s", 
          parv[0], parv[1], parv[2] ? parv[2] : "");
    }

  aconf->port = port;
  /*
   * at this point we should be calling connect_server with a valid
   * C:line and a valid port in the C:line
   */
  if (connect_server(aconf, sptr, 0))
#if (defined SERVERHIDE) || (defined HIDE_SERVERS_IPS)
    sendto_one(sptr, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
               me.name, parv[0], "255.255.255.255", aconf->name, aconf->port);
  else
    sendto_one(sptr, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
               me.name, parv[0], "255.255.255.255",aconf->port);
#else
    sendto_one(sptr, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
               me.name, parv[0], aconf->host, aconf->name, aconf->port);
  else