summaryrefslogtreecommitdiffhomepage
path: root/auth.cpp
blob: 501eb07c17098f0f176b9108ad85c3cd5496989d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "auth.h"

#include <crypt.h>
#include <string.h>

#include <algorithm>
#include <iostream>
#include <random>
#include <stdexcept>

// crypt specified password
std::string Auth::generate(const std::string& pw)
{
 struct crypt_data data;
 memset((void *)&data, '\0', sizeof(data));

 std::random_device rd;
 std::mt19937 rng{rd()};
 std::uniform_int_distribution<int> uid(0, 63);

 std::string chars{std::string(std::string::size_type(64), char('a'))};
 std::iota(chars.begin()     , chars.begin() + 26, 'a');
 std::iota(chars.begin() + 26, chars.begin() + 52, 'A');
 std::iota(chars.begin() + 52, chars.begin() + 62, '0');
 chars[62] = '.';
 chars[63] = '/';

 std::string salt{{chars[uid(rng)], chars[uid(rng)]}};

 char* result;

 if ((result = crypt_r(pw.data(), salt.data(), &data)) == nullptr)
  throw std::runtime_error("Error on crypt_r()");

 return result;
}

// validate specified password against crypted hash
bool Auth::validate(const std::string& crypted, const std::string& pw)
{
 struct crypt_data data;
 memset((void *)&data, '\0', sizeof(data));

 if (crypted.size() < 2) {
  std::cerr << "Warning: Bad password hash configured (size)" << std::endl;
  return false;
 }

 std::string salt{crypted.substr(0, 2)};

 char* output;
 if ((output = crypt_r(pw.data(), salt.data(), &data)) == nullptr) {
  std::cerr << "Warning: Error on crypt_r()" << std::endl;
  return false;
 }

 return crypted == output;
}