git.fiddlerwoaroof.com
token.cc
7684972a
 /* Copyright (C) CJ Affiliate
  *
  * You may use, distribute and modify this code under  the
bef74c28
  * terms of the  GNU General Public License version 2  or
7684972a
  * later.
  *
  * You should have received a copy of the license with this
  * file. If not, you will find a copy in the "LICENSE" file
  * at https://github.com/cjdev/dual-control.
  */
 
55259c47
 #include <string>
 #include <vector>
 #include <memory>
4bf199d2
 #include <fstream>
af3a4cd4
 #include <iostream>
 #include <functional>
1c7f8bf0
 
bef74c28
 #include "token.h"
 #include "user.h"
43889d2c
 #include "base32.h"
215ea751
 #include "sys_fstream.h"
4a6aca25
 #include "random_source.h"
bef74c28
 
 namespace
 {
e064ffa9
 class tokens_impl : public tokens_ifc
0e218820
 {
 private:
215ea751
     fstreams fstreams_;
194e6869
     totp_generator generator_;
b6eb15ba
     random_source rand_;
0e218820
 public:
8adb1737
     tokens_impl (const fstreams &fstreams, const totp_generator generator,
                  const random_source rand) :
b6eb15ba
         fstreams_ (fstreams), generator_ (generator), rand_ (rand) {}
af3a4cd4
     std::string token (const user &user) const override
0e218820
     {
43889d2c
         // Get key
8c62e61c
         std::string line = read_key (user);
 
3f7d4dd6
         if (line == "") {
             return "";
         }
 
         base32 codec;
8c62e61c
         std::vector<uint8_t> key = codec.decode (line);
3f7d4dd6
 
40fd6c82
         return generator_.generate_token (key);
3f7d4dd6
     }
 
 private:
8c62e61c
     std::string get_key_path (const user &user) const
     {
3f7d4dd6
         return user.home_directory() + "/.dual_control";
     }
 
8c62e61c
     bool key_exists (const user &user) const
     {
3f7d4dd6
         // check if file exists
8c62e61c
         std::string file_path = get_key_path (user);
         fstreams::pstream stream (fstreams_.open_fstream (file_path));
3f7d4dd6
         return stream->good();
     }
 
8c62e61c
     std::string read_key (const user &user) const
     {
         std::string file_path = get_key_path (user);
43889d2c
         fstreams::pstream stream (fstreams_.open_fstream (file_path));
4bf199d2
 
8c62e61c
         std::vector<char> line_v (16);
         stream->read (line_v.data(), line_v.size());
4bf199d2
 
43889d2c
         if (stream->fail()) {
             return "";
         }
4bf199d2
 
8c62e61c
         std::string line (line_v.begin(), line_v.end());
3f7d4dd6
         return line;
     }
 public:
b6eb15ba
     std::string generate_key() const override
     {
         base32 codec;
         // get randomness
         int length = 10;
8adb1737
         std::vector<uint8_t> random_bytes (rand_.get_random_bytes (length));
b6eb15ba
         // base32encode it
         std::string key = codec.encode (random_bytes);
         return key;
     }
 
8c62e61c
     std::string ensure_key (const user &user) const override
     {
         if (!key_exists (user)) {
3f7d4dd6
             std::string key = generate_key();
8c62e61c
             save (user, key);
3f7d4dd6
             return key;
         } else {
8c62e61c
             return read_key (user);
3f7d4dd6
         }
0e218820
     }
3f7d4dd6
 
b6eb15ba
     void save (const user &user, const std::string &key) const override
d10906ee
     {
8c62e61c
         std::string file_path = get_key_path (user);
d10906ee
         fstreams::postream stream (fstreams_.open_ofstream (file_path,
                                    std::ios_base::trunc));
b6eb15ba
         *stream << key<< std::endl;
af3a4cd4
     }
0e218820
 };
bef74c28
 }
194e6869
 
8c62e61c
 tokens tokens::create (const fstreams &fstreams,
b6eb15ba
                        const totp_generator &generator,
                        const random_source &rand)
bef74c28
 {
e064ffa9
     return tokens (tokens::delegate
b6eb15ba
                    (new tokens_impl (fstreams, generator, rand)));
bef74c28
 }
0d8b9a17