示例#1
0
文件: listener.c 项目: Macs/NeoIRCd
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;
}
示例#2
0
static void
me_sasl(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p,
	int parc, const char *parv[])
{
	struct Client *target_p, *agent_p;

	/* Let propagate if not addressed to us, or if broadcast.
	 * Only SASL agents can answer global requests.
	 */
	if(strncmp(parv[2], me.id, 3))
		return;

	if((target_p = find_id(parv[2])) == NULL)
		return;

	if((agent_p = find_id(parv[1])) == NULL)
		return;

	if(source_p != agent_p->servptr) /* WTF?! */
		return;

	/* We only accept messages from SASL agents; these must have umode +S
	 * (so the server must be listed in a service{} block).
	 */
	if(!IsService(agent_p))
		return;

	/* Reject if someone has already answered. */
	if(*target_p->localClient->sasl_agent && strncmp(parv[1], target_p->localClient->sasl_agent, IDLEN))
		return;
	else if(!*target_p->localClient->sasl_agent)
		rb_strlcpy(target_p->localClient->sasl_agent, parv[1], IDLEN);

	if(*parv[3] == 'C')
	{
		sendto_one(target_p, "AUTHENTICATE %s", parv[4]);
		target_p->localClient->sasl_messages++;
	}
	else if(*parv[3] == 'D')
	{
		if(*parv[4] == 'F')
		{
			sendto_one(target_p, form_str(ERR_SASLFAIL), me.name, EmptyString(target_p->name) ? "*" : target_p->name);
			/* Failures with zero messages are just "unknown mechanism" errors; don't count those. */
			if(target_p->localClient->sasl_messages > 0)
			{
				if(*target_p->name)
				{
					target_p->localClient->sasl_failures++;
					target_p->localClient->sasl_next_retry = rb_current_time() + (1 << MIN(target_p->localClient->sasl_failures + 5, 13));
				}
				else if(throttle_add((struct sockaddr*)&target_p->localClient->ip))
				{
					exit_client(target_p, target_p, &me, "Too many failed authentication attempts");
					return;
				}
			}
		}
		else if(*parv[4] == 'S')
		{
			sendto_one(target_p, form_str(RPL_SASLSUCCESS), me.name, EmptyString(target_p->name) ? "*" : target_p->name);
			target_p->localClient->sasl_failures = 0;
			target_p->localClient->sasl_complete = 1;
			ServerStats.is_ssuc++;
		}
		*target_p->localClient->sasl_agent = '\0'; /* Blank the stored agent so someone else can answer */
		target_p->localClient->sasl_messages = 0;
	}
	else if(*parv[3] == 'M')
		sendto_one(target_p, form_str(RPL_SASLMECHS), me.name, EmptyString(target_p->name) ? "*" : target_p->name, parv[4]);
}