]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_password_hash.cpp
fcc910073835b70001fb955d8e970cf4052cd3e9
[user/henk/code/inspircd.git] / src / modules / m_password_hash.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 /* $ModDesc: Allows for hashed oper passwords */
15 /* $ModDep: m_hash.h */
16
17 #include "inspircd.h"
18 #include "m_hash.h"
19
20 typedef std::map<irc::string, Module*> hashymodules;
21
22 /* Handle /MKPASSWD
23  */
24 class CommandMkpasswd : public Command
25 {
26         hashymodules &hashers;
27         std::deque<std::string> &names;
28  public:
29         CommandMkpasswd (InspIRCd* Instance, Module* Creator, hashymodules &h, std::deque<std::string> &n)
30                 : Command(Instance, Creator, "MKPASSWD", 0, 2), hashers(h), names(n)
31         {
32                 syntax = "<hashtype> <any-text>";
33         }
34
35         void MakeHash(User* user, const char* algo, const char* stuff)
36         {
37                 /* Lets see if they gave us an algorithm which has been implemented */
38                 hashymodules::iterator x = hashers.find(algo);
39                 if (x != hashers.end())
40                 {
41                         /* Yup, reset it first (Always ALWAYS do this) */
42                         HashResetRequest(creator, x->second).Send();
43                         /* Now attempt to generate a hash */
44                         user->WriteServ("NOTICE %s :%s hashed password for %s is %s",user->nick.c_str(), algo, stuff, HashSumRequest(creator, x->second, stuff).Send() );
45                 }
46                 else if (names.empty())
47                 {
48                         /* same idea as bug #569 */
49                         user->WriteServ("NOTICE %s :No hash provider modules are loaded", user->nick.c_str());
50                 }
51                 else
52                 {
53                         /* I dont do flying, bob. */
54                         user->WriteServ("NOTICE %s :Unknown hash type, valid hash types are: %s", user->nick.c_str(), irc::stringjoiner(", ", names, 0, names.size() - 1).GetJoined().c_str() );
55                 }
56         }
57
58         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
59         {
60                 MakeHash(user, parameters[0].c_str(), parameters[1].c_str());
61                 // this hashing could take some time, increasing server load.
62                 // Slow down the user if they are trying to flood mkpasswd requests
63                 user->IncreasePenalty(5);
64
65                 return CMD_LOCALONLY;
66         }
67 };
68
69 class ModuleOperHash : public Module
70 {
71
72         CommandMkpasswd cmd;
73         hashymodules hashers; /* List of modules which implement HashRequest */
74         std::deque<std::string> names; /* Module names which implement HashRequest */
75
76         bool diduseiface; /* If we've called UseInterface yet. */
77  public:
78
79         ModuleOperHash(InspIRCd* Me)
80                 : Module(Me), cmd(Me, this, hashers, names)
81         {
82                 diduseiface = false;
83
84                 /* Read the config file first */
85 //              Conf = NULL;
86                 OnRehash(NULL);
87
88                 /* Find all modules which implement the interface 'HashRequest' */
89                 modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest");
90
91                 /* Did we find any modules? */
92                 if (ml)
93                 {
94                         /* Yes, enumerate them all to find out the hashing algorithm name */
95                         for (modulelist::iterator m = ml->begin(); m != ml->end(); m++)
96                         {
97                                 /* Make a request to it for its name, its implementing
98                                  * HashRequest so we know its safe to do this
99                                  */
100                                 std::string name = HashNameRequest(this, *m).Send();
101                                 /* Build a map of them */
102                                 hashers[name.c_str()] = *m;
103                                 names.push_back(name);
104                         }
105                         /* UseInterface doesn't do anything if there are no providers, so we'll have to call it later if a module gets loaded later on. */
106                         ServerInstance->Modules->UseInterface("HashRequest");
107                         diduseiface = true;
108                 }
109
110                 ServerInstance->AddCommand(&cmd);
111                 Implementation eventlist[] = { I_OnPassCompare, I_OnLoadModule };
112                 ServerInstance->Modules->Attach(eventlist, this, 2);
113         }
114
115         virtual ~ModuleOperHash()
116         {
117                 if (diduseiface) ServerInstance->Modules->DoneWithInterface("HashRequest");
118         }
119
120
121         virtual void OnLoadModule(Module* mod, const std::string& name)
122         {
123                 if (ServerInstance->Modules->ModuleHasInterface(mod, "HashRequest"))
124                 {
125                         ServerInstance->Logs->Log("m_password-hash",DEBUG, "Post-load registering hasher: %s", name.c_str());
126                         std::string sname = HashNameRequest(this, mod).Send();
127                         hashers[sname.c_str()] = mod;
128                         names.push_back(sname);
129                         if (!diduseiface)
130                         {
131                                 ServerInstance->Modules->UseInterface("HashRequest");
132                                 diduseiface = true;
133                         }
134                 }
135         }
136
137         virtual ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
138         {
139                 /* First, lets see what hash theyre using on this oper */
140                 hashymodules::iterator x = hashers.find(hashtype.c_str());
141
142                 /* Is this a valid hash name? (case insensitive) */
143                 if (x != hashers.end())
144                 {
145                         /* Reset the hashing module */
146                         HashResetRequest(this, x->second).Send();
147                         /* Compare the hash in the config to the generated hash */
148                         if (!strcasecmp(data.c_str(), HashSumRequest(this, x->second, input.c_str()).Send()))
149                                 return MOD_RES_ALLOW;
150                         /* No match, and must be hashed, forbid */
151                         else
152                                 return MOD_RES_DENY;
153                 }
154
155                 /* Not a hash, fall through to strcmp in core */
156                 return MOD_RES_PASSTHRU;
157         }
158
159         virtual Version GetVersion()
160         {
161                 return Version("$Id$",VF_VENDOR,API_VERSION);
162         }
163 };
164
165 MODULE_INIT(ModuleOperHash)