Continue with 0.4.13-dev
[oweals/minetest.git] / src / util / auth.cpp
1 /*
2 Minetest
3 Copyright (C) 2015 est31 <MTest31@outlook.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <algorithm>
21 #include <string>
22 #include "auth.h"
23 #include "base64.h"
24 #include "sha1.h"
25 #include "srp.h"
26 #include "string.h"
27
28 // Get an sha-1 hash of the player's name combined with
29 // the password entered. That's what the server uses as
30 // their password. (Exception : if the password field is
31 // blank, we send a blank password - this is for backwards
32 // compatibility with password-less players).
33 std::string translatePassword(const std::string &name,
34         const std::string &password)
35 {
36         if (password.length() == 0)
37                 return "";
38
39         std::string slt = name + password;
40         SHA1 sha1;
41         sha1.addBytes(slt.c_str(), slt.length());
42         unsigned char *digest = sha1.getDigest();
43         std::string pwd = base64_encode(digest, 20);
44         free(digest);
45         return pwd;
46 }
47
48 void getSRPVerifier(const std::string &name,
49         const std::string &password, char **salt, size_t *salt_len,
50         char **bytes_v, size_t *len_v)
51 {
52         std::string n_name = lowercase(name);
53         srp_create_salted_verification_key(SRP_SHA256, SRP_NG_2048,
54                 n_name.c_str(), (const unsigned char *)password.c_str(),
55                 password.size(), (unsigned char **)salt, salt_len,
56                 (unsigned char **)bytes_v, len_v, NULL, NULL);
57 }
58
59 // Get a db-ready SRP verifier
60 // If the salt param is NULL, one is automatically generated.
61 // Please free() it afterwards. You shouldn't use it for other purposes,
62 // as you will need the contents of salt_len too.
63 inline static std::string getSRPVerifier(const std::string &name,
64         const std::string &password, char ** salt, size_t salt_len)
65 {
66         char * bytes_v = NULL;
67         size_t len_v;
68         getSRPVerifier(name, password, salt, &salt_len,
69                 &bytes_v, &len_v);
70         std::string ret_val = encodeSRPVerifier(std::string(bytes_v, len_v),
71                 std::string(*salt, salt_len));
72         free(bytes_v);
73         return ret_val;
74 }
75
76 // Get a db-ready SRP verifier
77 std::string getSRPVerifier(const std::string &name,
78         const std::string &password)
79 {
80         char * salt = NULL;
81         std::string ret_val = getSRPVerifier(name,
82                 password, &salt, 0);
83         free(salt);
84         return ret_val;
85 }
86
87 // Get a db-ready SRP verifier
88 std::string getSRPVerifier(const std::string &name,
89         const std::string &password, const std::string &salt)
90 {
91         // The implementation won't change the salt if its set,
92         // therefore we can cast.
93         char *salt_cstr = (char *)salt.c_str();
94         return getSRPVerifier(name, password,
95                 &salt_cstr, salt.size());
96 }
97
98 // Make a SRP verifier db-ready
99 std::string encodeSRPVerifier(const std::string &verifier,
100         const std::string &salt)
101 {
102         std::ostringstream ret_str;
103         ret_str << "#1#"
104                 << base64_encode((unsigned char*) salt.c_str(), salt.size()) << "#"
105                 << base64_encode((unsigned char*) verifier.c_str(), verifier.size());
106         return ret_str.str();
107 }
108
109 bool decodeSRPVerifier(const std::string &enc_pwd,
110         std::string *salt, std::string *bytes_v)
111 {
112         std::vector<std::string> pwd_components = str_split(enc_pwd, '#');
113
114         if ((pwd_components.size() != 4)
115                         || (pwd_components[1] != "1") // 1 means srp
116                         || !base64_is_valid(pwd_components[2])
117                         || !base64_is_valid(pwd_components[3]))
118                 return false;
119
120         std::string salt_str = base64_decode(pwd_components[2]);
121         std::string bytes_v_str = base64_decode(pwd_components[3]);
122         *salt = salt_str;
123         *bytes_v = bytes_v_str;
124         return true;
125
126 }