]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/commands/cmd_oper.cpp
Change cmd_*.so to use the Module object API
[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
16 #ifndef __CMD_OPER_H__
17 #define __CMD_OPER_H__
18
19 // include the common header files
20
21 #include "users.h"
22 #include "channels.h"
23
24 bool OneOfMatches(const char* host, const char* ip, const char* hostlist);
25
26 /** Handle /OPER. These command handlers can be reloaded by the core,
27  * and handle basic RFC1459 commands. Commands within modules work
28  * the same way, however, they can be fully unloaded, where these
29  * may not.
30  */
31 class CommandOper : public Command
32 {
33  public:
34         /** Constructor for oper.
35          */
36         CommandOper (InspIRCd* Instance, Module* parent) : Command(Instance,parent,"OPER",0,2,false,2) { syntax = "<username> <password>"; }
37         /** Handle command.
38          * @param parameters The parameters to the comamnd
39          * @param pcnt The number of parameters passed to teh command
40          * @param user The user issuing the command
41          * @return A value from CmdResult to indicate command success or failure.
42          */
43         CmdResult Handle(const std::vector<std::string>& parameters, User *user);
44 };
45
46 #endif
47
48 #include "hashcomp.h"
49
50 bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
51 {
52         std::stringstream hl(hostlist);
53         std::string xhost;
54         while (hl >> xhost)
55         {
56                 if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
57                 {
58                         return true;
59                 }
60         }
61         return false;
62 }
63
64 CmdResult CommandOper::Handle (const std::vector<std::string>& parameters, User *user)
65 {
66         char LoginName[MAXBUF];
67         char Password[MAXBUF];
68         char OperType[MAXBUF];
69         char TypeName[MAXBUF];
70         char HostName[MAXBUF];
71         char ClassName[MAXBUF];
72         char TheHost[MAXBUF];
73         char TheIP[MAXBUF];
74         char HashType[MAXBUF];
75         int j;
76         bool found = false;
77         bool type_invalid = false;
78
79         bool match_login = false;
80         bool match_pass = false;
81         bool match_hosts = false;
82
83         snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(),user->host.c_str());
84         snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(),user->GetIPString());
85
86         for (int i = 0; i < ServerInstance->Config->ConfValueEnum("oper"); i++)
87         {
88                 ServerInstance->Config->ConfValue("oper", "name", i, LoginName, MAXBUF);
89                 ServerInstance->Config->ConfValue("oper", "password", i, Password, MAXBUF);
90                 ServerInstance->Config->ConfValue("oper", "type", i, OperType, MAXBUF);
91                 ServerInstance->Config->ConfValue("oper", "host", i, HostName, MAXBUF);
92                 ServerInstance->Config->ConfValue("oper", "hash", i, HashType, MAXBUF);
93
94                 match_login = (LoginName == parameters[0]);
95                 match_pass = !ServerInstance->PassCompare(user, Password, parameters[1], HashType);
96                 match_hosts = OneOfMatches(TheHost,TheIP,HostName);
97
98                 if (match_login && match_pass && match_hosts)
99                 {
100                         type_invalid = true;
101                         for (j =0; j < ServerInstance->Config->ConfValueEnum("type"); j++)
102                         {
103                                 ServerInstance->Config->ConfValue("type", "name", j, TypeName, MAXBUF);
104                                 ServerInstance->Config->ConfValue("type", "class", j, ClassName, MAXBUF);
105
106                                 if (!strcmp(TypeName,OperType))
107                                 {
108                                         /* found this oper's opertype */
109                                         if (!ServerInstance->IsNick(TypeName, ServerInstance->Config->Limits.NickMax))
110                                         {
111                                                 user->WriteNumeric(491, "%s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick.c_str());
112                                                 ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",OperType);
113                                                 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());
114                                                 return CMD_FAILURE;
115                                         }
116                                         ServerInstance->Config->ConfValue("type","host", j, HostName, MAXBUF);
117                                         if (*HostName)
118                                                 user->ChangeDisplayedHost(HostName);
119                                         if (*ClassName)
120                                         {
121                                                 user->SetClass(ClassName);
122                                                 user->CheckClass();
123                                         }
124                                         found = true;
125                                         type_invalid = false;
126                                         break;
127                                 }
128                         }
129                 }
130                 if (match_login || found)
131                         break;
132         }
133         if (found)
134         {
135                 /* correct oper credentials */
136                 user->Oper(OperType, LoginName);
137         }
138         else
139         {
140                 char broadcast[MAXBUF];
141
142                 if (!type_invalid)
143                 {
144                         std::string fields;
145                         if (!match_login)
146                                 fields.append("login ");
147                         else
148                         {
149                                 if (!match_pass)
150                                         fields.append("password ");
151                                 if (!match_hosts)
152                                         fields.append("hosts");
153                         }
154
155                         // tell them they suck, and lag them up to help prevent brute-force attacks
156                         user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
157                         user->IncreasePenalty(10);
158
159                         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());
160                         ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
161                         ServerInstance->PI->SendSNONotice("o", std::string("OPER: ") + broadcast);
162
163                         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());
164                         return CMD_FAILURE;
165                 }
166                 else
167                 {
168                         user->WriteNumeric(491, "%s :Your oper block does not have a valid opertype associated with it",user->nick.c_str());
169
170                         snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0].c_str(),OperType);
171
172                         ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
173
174                         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());
175                         return CMD_FAILURE;
176                 }
177         }
178         return CMD_SUCCESS;
179 }
180
181 COMMAND_INIT(CommandOper)