/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* IRC operator commands
*/
-#include "imp.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <time.h>
#include "ngircd.h"
#include "conn-func.h"
#include "conf.h"
#include "channel.h"
#include "class.h"
+#include "parse.h"
+#include "irc.h"
#include "irc-macros.h"
#include "irc-write.h"
+#include "lists.h"
#include "log.h"
#include "match.h"
#include "messages.h"
-#include "parse.h"
#include "op.h"
-#include <exp.h>
#include "irc-oper.h"
/**
static bool
Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
{
- Log(LOG_WARNING, "Got invalid OPER from \"%s\": \"%s\" -- %s",
+ Log(LOG_ERR|LOG_snotice, "Got invalid OPER from \"%s\": \"%s\" -- %s!",
Client_Mask(Client), errtoken, errmsg);
- return IRC_WriteErrClient(Client, ERR_PASSWDMISMATCH_MSG,
+ /* Increase penalty to slow down possible brute force attacks */
+ IRC_SetPenalty(Client, 10);
+ return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
Client_ID(Client));
} /* Bad_OperPass */
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 2 && Req->argc != 3 &&
- Req->argc != 5 && Req->argc != 6) {
- IRC_SetPenalty(Client, 2);
+ Req->argc != 5 && Req->argc != 6)
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
- }
/* Invalid port number? */
- if ((Req->argc > 1) && atoi(Req->argv[1]) < 1) {
- IRC_SetPenalty(Client, 2);
+ if ((Req->argc > 1) && atoi(Req->argv[1]) < 1)
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
- }
if (Client_Type(Client) != CLIENT_SERVER
&& !Client_HasMode(Client, 'o'))
from = Client;
break;
case CLIENT_SERVER:
+ _IRC_REQUIRE_PREFIX_OR_RETURN_(Client, Req)
from = Client_Search(Req->prefix);
break;
default:
GLOBAL bool
IRC_xLINE(CLIENT *Client, REQUEST *Req)
{
- CLIENT *from;
+ CLIENT *from, *c, *c_next;
+ char reason[COMMAND_LEN], class_c;
+ struct list_head *list;
+ time_t timeout;
int class;
- char class_c;
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of parameters? */
- if (Req->argc != 1 && Req->argc != 3) {
- IRC_SetPenalty(Client, 2);
+ if (Req->argc != 1 && Req->argc != 3)
return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
- }
- from = Op_Check(Client, Req);
+ if (!Conf_AllowRemoteOper && Client_Type(Client) == CLIENT_SERVER) {
+ /* Explicitly forbid remote servers to modify "x-lines" when
+ * the "AllowRemoteOper" configuration option isn't set, even
+ * when the command seems to originate from the remote server
+ * itself: this prevents GLINE's to become set during server
+ * handshake in this case (what wouldn't be possible during
+ * regular runtime when a remote IRC Op sends the command). */
+ from = NULL;
+ } else
+ from = Op_Check(Client, Req);
if (!from)
return Op_NoPrivileges(Client, Req);
}
} else {
/* Add new mask to list */
+ timeout = atol(Req->argv[1]);
+ if (timeout > 0)
+ timeout += time(NULL);
if (Class_AddMask(class, Req->argv[0],
- time(NULL) + atol(Req->argv[1]),
+ timeout,
Req->argv[2])) {
- Log(LOG_NOTICE|LOG_snotice,
- "\"%s\" added \"%s\" to %c-Line list: \"%s\" (%ld seconds).",
- Client_Mask(from), Req->argv[0], class_c,
- Req->argv[2], atol(Req->argv[1]));
+ if (Client_Type(from) != CLIENT_SERVER)
+ Log(LOG_NOTICE|LOG_snotice,
+ "\"%s\" added \"%s\" to %c-Line list: \"%s\" (%ld seconds).",
+ Client_Mask(from), Req->argv[0], class_c,
+ Req->argv[2], atol(Req->argv[1]));
if (class == CLASS_GLINE) {
/* Inform other servers */
IRC_WriteStrServersPrefix(Client, from,
Req->argv[0], Req->argv[1],
Req->argv[2]);
}
+
+ /* Check currently connected clients */
+ snprintf(reason, sizeof(reason), "%c-Line by \"%s\": \"%s\"",
+ class_c, Client_ID(from), Req->argv[2]);
+ list = Class_GetList(class);
+ c = Client_First();
+ while (c) {
+ c_next = Client_Next(c);
+ if ((class == CLASS_GLINE || Client_Conn(c) > NONE)
+ && Lists_Check(list, c))
+ IRC_KillClient(Client, NULL,
+ Client_ID(c), reason);
+ c = c_next;
+ }
}
}