1 /**
2 * SRP-6a File Handling
3 * 
4 * Copyright:
5 * (C) 2011 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.constructs.srp6_files;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_SRP6):
15 import botan.math.bigint.bigint;
16 import botan.utils.parsing;
17 import botan.utils.mem_ops;
18 import botan.codec.base64;
19 import memutils.hashmap;
20 import std.stdio;
21 import std.array;
22 
23 /**
24 * A GnuTLS compatible SRP6 authenticator file
25 */
26 final class SRP6AuthenticatorFile
27 {
28 public:
29     /**
30     * Params:
31     *  filename = will be opened and processed as a SRP
32     * authenticator file
33     */
34     this(in string filename)
35     {
36         auto file = File(filename);
37         auto range = file.byLine();
38         
39         foreach (line; range) {    
40             string[] parts = cast(string[])line.split(':');
41             
42             if (parts.length != 4)
43                 throw new DecodingError("Invalid line in SRP authenticator file");
44             
45             string username = parts[0];
46             BigInt v = BigInt.decode(base64Decode(parts[1]));
47             Vector!ubyte salt = unlock(base64Decode(parts[2]));
48             BigInt group_id_idx = BigInt.decode(base64Decode(parts[3]));
49             
50             string group_id;
51             
52             if (group_id_idx == 1)
53                 group_id = "modp/srp/1024";
54             else if (group_id_idx == 2)
55                 group_id = "modp/srp/1536";
56             else if (group_id_idx == 3)
57                 group_id = "modp/srp/2048";
58             else
59                 continue; // unknown group, ignored
60             
61             m_entries[username] = SRP6Data(&v, &salt, group_id);
62         }
63     }
64 
65     bool lookupUser(in string username,
66                     ref BigInt v,
67                     ref Vector!ubyte salt,
68                     ref string group_id) const
69     {
70         SRP6Data entry = m_entries.get(username);
71         if (*entry == SRP6DataImpl.init)
72             return false;
73 
74         v = entry.v.clone;
75         salt = entry.salt.clone;
76         group_id = entry.group_id;
77         
78         return true;
79     }
80 
81 private:
82     alias SRP6Data = RefCounted!SRP6DataImpl;
83     struct SRP6DataImpl
84     {
85 
86         this(BigInt* _v,
87              Vector!ubyte* _salt,
88              in string _group_id) 
89         {
90             v = (*_v).move();
91             salt = (*_salt).move(); 
92             group_id = _group_id;
93         }
94 
95         BigInt v;
96         Vector!ubyte salt;
97         string group_id;
98     }
99 
100     HashMapRef!(string, SRP6Data) m_entries;
101 }