]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_password_hash.cpp
Merge branch 'master+stfjoinforward'
[user/henk/code/inspircd.git] / src / modules / m_password_hash.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2008 Thomas Stagner <aquanight@inspircd.org>
6  *
7  * This file is part of InspIRCd.  InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "inspircd.h"
22 #include "modules/hash.h"
23
24 /* Handle /MKPASSWD
25  */
26 class CommandMkpasswd : public Command
27 {
28  public:
29         CommandMkpasswd(Module* Creator) : Command(Creator, "MKPASSWD", 2)
30         {
31                 syntax = "<hashtype> <any-text>";
32                 Penalty = 5;
33         }
34
35         void MakeHash(User* user, const std::string& algo, const std::string& stuff)
36         {
37                 if (!algo.compare(0, 5, "hmac-", 5))
38                 {
39                         std::string type(algo, 5);
40                         HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
41                         if (!hp)
42                         {
43                                 user->WriteNotice("Unknown hash type");
44                                 return;
45                         }
46
47                         if (hp->IsKDF())
48                         {
49                                 user->WriteNotice(type + " does not support HMAC");
50                                 return;
51                         }
52
53                         std::string salt = ServerInstance->GenRandomStr(hp->out_size, false);
54                         std::string target = hp->hmac(salt, stuff);
55                         std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0);
56
57                         user->WriteNotice(algo + " hashed password for " + stuff + " is " + str);
58                         return;
59                 }
60                 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + algo);
61                 if (hp)
62                 {
63                         /* Now attempt to generate a hash */
64                         std::string hexsum = hp->Generate(stuff);
65                         user->WriteNotice(algo + " hashed password for " + stuff + " is " + hexsum);
66                 }
67                 else
68                 {
69                         user->WriteNotice("Unknown hash type");
70                 }
71         }
72
73         CmdResult Handle (const std::vector<std::string>& parameters, User *user)
74         {
75                 MakeHash(user, parameters[0], parameters[1]);
76
77                 return CMD_SUCCESS;
78         }
79 };
80
81 class ModuleOperHash : public Module
82 {
83         CommandMkpasswd cmd;
84  public:
85
86         ModuleOperHash() : cmd(this)
87         {
88         }
89
90         ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype) CXX11_OVERRIDE
91         {
92                 if (!hashtype.compare(0, 5, "hmac-", 5))
93                 {
94                         std::string type(hashtype, 5);
95                         HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
96                         if (!hp)
97                                 return MOD_RES_PASSTHRU;
98
99                         if (hp->IsKDF())
100                         {
101                                 ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Tried to use HMAC with %s, which does not support HMAC", type.c_str());
102                                 return MOD_RES_DENY;
103                         }
104
105                         // this is a valid hash, from here on we either accept or deny
106                         std::string::size_type sep = data.find('$');
107                         if (sep == std::string::npos)
108                                 return MOD_RES_DENY;
109                         std::string salt = Base64ToBin(data.substr(0, sep));
110                         std::string target = Base64ToBin(data.substr(sep + 1));
111
112                         if (target == hp->hmac(salt, input))
113                                 return MOD_RES_ALLOW;
114                         else
115                                 return MOD_RES_DENY;
116                 }
117
118                 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + hashtype);
119
120                 /* Is this a valid hash name? */
121                 if (hp)
122                 {
123                         if (hp->Compare(input, data))
124                                 return MOD_RES_ALLOW;
125                         else
126                                 /* No match, and must be hashed, forbid */
127                                 return MOD_RES_DENY;
128                 }
129
130                 // We don't handle this type, let other mods or the core decide
131                 return MOD_RES_PASSTHRU;
132         }
133
134         Version GetVersion() CXX11_OVERRIDE
135         {
136                 return Version("Allows for hashed oper passwords",VF_VENDOR);
137         }
138 };
139
140 MODULE_INIT(ModuleOperHash)