]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_oper.cpp
Move all local-only fields to LocalUser
[user/henk/code/inspircd.git] / src / commands / cmd_oper.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "hashcomp.h"
16
17 bool OneOfMatches(const char* host, const char* ip, const char* hostlist);
18
19 /** Handle /OPER. These command handlers can be reloaded by the core,
20  * and handle basic RFC1459 commands. Commands within modules work
21  * the same way, however, they can be fully unloaded, where these
22  * may not.
23  */
24 class CommandOper : public SplitCommand
25 {
26  public:
27         /** Constructor for oper.
28          */
29         CommandOper ( Module* parent) : SplitCommand(parent,"OPER",2,2) { syntax = "<username> <password>"; }
30         /** Handle command.
31          * @param parameters The parameters to the comamnd
32          * @param pcnt The number of parameters passed to teh command
33          * @param user The user issuing the command
34          * @return A value from CmdResult to indicate command success or failure.
35          */
36         CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser *user);
37 };
38
39 bool OneOfMatches(const char* host, const char* ip, const std::string& hostlist)
40 {
41         std::stringstream hl(hostlist);
42         std::string xhost;
43         while (hl >> xhost)
44         {
45                 if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
46                 {
47                         return true;
48                 }
49         }
50         return false;
51 }
52
53 CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, LocalUser *user)
54 {
55         char TheHost[MAXBUF];
56         char TheIP[MAXBUF];
57         std::string type;
58         bool found = false;
59         bool match_login = false;
60         bool match_pass = false;
61         bool match_hosts = false;
62
63         snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
64         snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
65
66         for (int i = 0;; i++)
67         {
68                 ConfigTag* tag = ServerInstance->Config->ConfValue("oper", i);
69                 if (!tag)
70                         break;
71                 if (tag->getString("name") != parameters[0])
72                         continue;
73                 match_login = true;
74                 match_pass = !ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash"));
75                 match_hosts = OneOfMatches(TheHost,TheIP,tag->getString("host"));
76
77                 if (match_pass && match_hosts)
78                 {
79                         type = tag->getString("type");
80                         ConfigTag* typeTag = ServerInstance->Config->opertypes[type];
81
82                         if (typeTag)
83                         {
84                                 /* found this oper's opertype */
85                                 if (!ServerInstance->IsNick(type.c_str(), ServerInstance->Config->Limits.NickMax))
86                                 {
87                                         user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str());
88                                         ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",type.c_str());
89                                         ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
90                                         return CMD_FAILURE;
91                                 }
92                                 std::string host = typeTag->getString("host");
93                                 if (!host.empty())
94                                         user->ChangeDisplayedHost(host.c_str());
95                                 std::string opClass = typeTag->getString("class");
96                                 if (!opClass.empty())
97                                 {
98                                         user->SetClass(opClass);
99                                         user->CheckClass();
100                                 }
101                                 found = true;
102                         }
103                 }
104                 break;
105         }
106         if (found)
107         {
108                 /* correct oper credentials */
109                 user->Oper(type, parameters[0]);
110         }
111         else
112         {
113                 char broadcast[MAXBUF];
114
115                 if (type.empty())
116                 {
117                         std::string fields;
118                         if (!match_login)
119                                 fields.append("login ");
120                         if (!match_pass)
121                                 fields.append("password ");
122                         if (!match_hosts)
123                                 fields.append("hosts");
124
125                         // tell them they suck, and lag them up to help prevent brute-force attacks
126                         user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
127                         user->Penalty += 10;
128
129                         snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
130                         ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
131                         ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
132
133                         ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str(), fields.c_str());
134                         return CMD_FAILURE;
135                 }
136                 else
137                 {
138                         user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str());
139
140                         snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),type.c_str());
141
142                         ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
143
144                         ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), parameters[0].c_str());
145                         return CMD_FAILURE;
146                 }
147         }
148         return CMD_SUCCESS;
149 }
150
151 COMMAND_INIT(CommandOper)