]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_oper.cpp
Clean up Command constructor
[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 Command
25 {
26  public:
27         /** Constructor for oper.
28          */
29         CommandOper ( Module* parent) : Command(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 Handle(const std::vector<std::string>& parameters, User *user);
37 };
38
39 bool OneOfMatches(const char* host, const char* ip, const char* 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::Handle (const std::vector<std::string>& parameters, User *user)
54 {
55         char LoginName[MAXBUF];
56         char Password[MAXBUF];
57         char OperType[MAXBUF];
58         char TypeName[MAXBUF];
59         char HostName[MAXBUF];
60         char ClassName[MAXBUF];
61         char TheHost[MAXBUF];
62         char TheIP[MAXBUF];
63         char HashType[MAXBUF];
64         int j;
65         bool found = false;
66         bool type_invalid = false;
67
68         bool match_login = false;
69         bool match_pass = false;
70         bool match_hosts = false;
71
72         snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
73         snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
74
75         for (int i = 0; i < ServerInstance->Config->ConfValueEnum("oper"); i++)
76         {
77                 ServerInstance->Config->ConfValue("oper", "name", i, LoginName, MAXBUF);
78                 ServerInstance->Config->ConfValue("oper", "password", i, Password, MAXBUF);
79                 ServerInstance->Config->ConfValue("oper", "type", i, OperType, MAXBUF);
80                 ServerInstance->Config->ConfValue("oper", "host", i, HostName, MAXBUF);
81                 ServerInstance->Config->ConfValue("oper", "hash", i, HashType, MAXBUF);
82
83                 match_login = (LoginName == parameters[0]);
84                 match_pass = !ServerInstance->PassCompare(user, Password, parameters[1], HashType);
85                 match_hosts = OneOfMatches(TheHost,TheIP,HostName);
86
87                 if (match_login && match_pass && match_hosts)
88                 {
89                         type_invalid = true;
90                         for (j =0; j < ServerInstance->Config->ConfValueEnum("type"); j++)
91                         {
92                                 ServerInstance->Config->ConfValue("type", "name", j, TypeName, MAXBUF);
93                                 ServerInstance->Config->ConfValue("type", "class", j, ClassName, MAXBUF);
94
95                                 if (!strcmp(TypeName,OperType))
96                                 {
97                                         /* found this oper's opertype */
98                                         if (!ServerInstance->IsNick(TypeName, ServerInstance->Config->Limits.NickMax))
99                                         {
100                                                 user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str());
101                                                 ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",OperType);
102                                                 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());
103                                                 return CMD_FAILURE;
104                                         }
105                                         ServerInstance->Config->ConfValue("type","host", j, HostName, MAXBUF);
106                                         if (*HostName)
107                                                 user->ChangeDisplayedHost(HostName);
108                                         if (*ClassName)
109                                         {
110                                                 user->SetClass(ClassName);
111                                                 user->CheckClass();
112                                         }
113                                         found = true;
114                                         type_invalid = false;
115                                         break;
116                                 }
117                         }
118                 }
119                 if (match_login || found)
120                         break;
121         }
122         if (found)
123         {
124                 /* correct oper credentials */
125                 user->Oper(OperType, LoginName);
126         }
127         else
128         {
129                 char broadcast[MAXBUF];
130
131                 if (!type_invalid)
132                 {
133                         std::string fields;
134                         if (!match_login)
135                                 fields.append("login ");
136                         else
137                         {
138                                 if (!match_pass)
139                                         fields.append("password ");
140                                 if (!match_hosts)
141                                         fields.append("hosts");
142                         }
143
144                         // tell them they suck, and lag them up to help prevent brute-force attacks
145                         user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
146                         user->IncreasePenalty(10);
147
148                         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());
149                         ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
150                         ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
151
152                         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());
153                         return CMD_FAILURE;
154                 }
155                 else
156                 {
157                         user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str());
158
159                         snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),OperType);
160
161                         ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
162
163                         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());
164                         return CMD_FAILURE;
165                 }
166         }
167         return CMD_SUCCESS;
168 }
169
170 COMMAND_INIT(CommandOper)