1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2010 InspIRCd Development Team
6 * See: http://wiki.inspircd.org/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 /* $ModDesc: Allows for hashed oper passwords */
19 static std::string hmac(HashProvider* hp, const std::string& key, const std::string& msg)
21 std::string hmac1, hmac2;
22 for (size_t n = 0; n < key.length(); n++)
24 hmac1.push_back(static_cast<char>(key[n] ^ 0x5C));
25 hmac2.push_back(static_cast<char>(key[n] ^ 0x36));
28 hmac1.append(hp->sum(hmac2));
29 return hp->sum(hmac1);
34 class CommandMkpasswd : public Command
37 CommandMkpasswd(Module* Creator) : Command(Creator, "MKPASSWD", 2)
39 syntax = "<hashtype> <any-text>";
43 void MakeHash(User* user, const std::string& algo, const std::string& stuff)
45 if (algo.substr(0,5) == "hmac-")
47 std::string type = algo.substr(5);
48 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
51 user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
54 std::string salt = GenRandomStr(6, false);
55 std::string target = hmac(hp, salt, stuff);
56 std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0);
58 user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
59 user->nick.c_str(), algo.c_str(), stuff.c_str(), str.c_str());
61 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + algo);
64 /* Now attempt to generate a hash */
65 user->WriteServ("NOTICE %s :%s hashed password for %s is %s",
66 user->nick.c_str(), algo.c_str(), stuff.c_str(), hp->hexsum(stuff).c_str());
70 user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str());
74 CmdResult Handle (const std::vector<std::string>& parameters, User *user)
76 MakeHash(user, parameters[0], parameters[1]);
82 class ModuleOperHash : public Module
87 ModuleOperHash() : cmd(this)
89 /* Read the config file first */
92 ServerInstance->AddCommand(&cmd);
93 Implementation eventlist[] = { I_OnPassCompare };
94 ServerInstance->Modules->Attach(eventlist, this, 1);
97 virtual ModResult OnPassCompare(Extensible* ex, const std::string &data, const std::string &input, const std::string &hashtype)
99 if (hashtype.substr(0,5) == "hmac-")
101 std::string type = hashtype.substr(5);
102 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + type);
104 return MOD_RES_PASSTHRU;
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)
109 std::string salt = Base64ToBin(data.substr(0, sep));
110 std::string target = Base64ToBin(data.substr(sep + 1));
112 std::string hmac1, hmac2;
113 for (size_t n = 0; n < salt.length(); n++)
115 hmac1.push_back(static_cast<char>(salt[n] ^ 0x5C));
116 hmac2.push_back(static_cast<char>(salt[n] ^ 0x36));
119 hmac1.append(hp->sum(hmac2));
120 if (target == hp->sum(hmac1))
121 return MOD_RES_ALLOW;
126 HashProvider* hp = ServerInstance->Modules->FindDataService<HashProvider>("hash/" + hashtype);
128 /* Is this a valid hash name? */
131 /* Compare the hash in the config to the generated hash */
132 if (data == hp->hexsum(input))
133 return MOD_RES_ALLOW;
135 /* No match, and must be hashed, forbid */
139 /* Not a hash, fall through to strcmp in core */
140 return MOD_RES_PASSTHRU;
143 virtual Version GetVersion()
145 return Version("Allows for hashed oper passwords",VF_VENDOR);
149 MODULE_INIT(ModuleOperHash)