]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_password_hash.cpp
Add HMAC implementation to HashProvider
[user/henk/code/inspircd.git] / src / modules / m_password_hash.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2010 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
16 #include "inspircd.h"
17 #include "hash.h"
18
19 /* Handle /MKPASSWD
20  */
21 class CommandMkpasswd : public Command
22 {
23  public:
24         CommandMkpasswd(Module* Creator) : Command(Creator, "MKPASSWD", 2)
25         {
26                 syntax = "<hashtype> <any-text>";
27                 Penalty = 5;
28         }
29
30         void MakeHash(User* user, const std::string& algo, const std::string& stuff)
31         {
32                 if (algo.substr(0,5) == "hmac-")
33                 {
34                         std::string type = algo.substr(5);
35                         HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
36                         if (!hp)
37                         {
38                                 user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
39                                 return;
40                         }
41                         std::string salt = ServerInstance->GenRandomStr(6, false);
42                         std::string target = hp->hmac(salt, stuff);
43                         std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0);
44
45                         user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
46                                 user->nick.c_str(), algo.c_str(), stuff.c_str(), str.c_str());
47                 }
48                 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + algo);
49                 if (hp)
50                 {
51                         /* Now attempt to generate a hash */
52                         user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
53                                 user->nick.c_str(), algo.c_str(), stuff.c_str(), hp->hexsum(stuff).c_str());
54                 }
55                 else
56                 {
57                         user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
58                 }
59         }
60
61         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
62         {
63                 MakeHash(user, parameters[0], parameters[1]);
64
65                 return CMD_SUCCESS;
66         }
67 };
68
69 class ModuleOperHash : public Module
70 {
71         CommandMkpasswd cmd;
72  public:
73
74         ModuleOperHash() : cmd(this)
75         {
76                 /* Read the config file first */
77                 OnRehash(NULL);
78
79                 ServerInstance->AddCommand(&cmd);
80                 Implementation eventlist[] = { I_OnPassCompare };
81                 ServerInstance->Modules->Attach(eventlist, this, 1);
82         }
83
84         virtual ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
85         {
86                 if (hashtype.substr(0,5) == "hmac-")
87                 {
88                         std::string type = hashtype.substr(5);
89                         HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
90                         if (!hp)
91                                 return MOD_RES_PASSTHRU;
92                         // this is a valid hash, from here on we either accept or deny
93                         std::string::size_type sep = data.find('$');
94                         if (sep == std::string::npos)
95                                 return MOD_RES_DENY;
96                         std::string salt = Base64ToBin(data.substr(0, sep));
97                         std::string target = Base64ToBin(data.substr(sep + 1));
98
99                         if (target == hp->hmac(salt, input))
100                                 return MOD_RES_ALLOW;
101                         else
102                                 return MOD_RES_DENY;
103                 }
104
105                 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + hashtype);
106
107                 /* Is this a valid hash name? */
108                 if (hp)
109                 {
110                         /* Compare the hash in the config to the generated hash */
111                         if (data == hp->hexsum(input))
112                                 return MOD_RES_ALLOW;
113                         else
114                                 /* No match, and must be hashed, forbid */
115                                 return MOD_RES_DENY;
116                 }
117
118                 /* Not a hash, fall through to strcmp in core */
119                 return MOD_RES_PASSTHRU;
120         }
121
122         virtual Version GetVersion()
123         {
124                 return Version("Allows for hashed oper passwords",VF_VENDOR);
125         }
126 };
127
128 MODULE_INIT(ModuleOperHash)