OpenVPN 3 Core Library
Loading...
Searching...
No Matches
sess_id.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// A general-purpose Session ID class
13
14#ifndef OPENVPN_COMMON_SESS_ID_H
15#define OPENVPN_COMMON_SESS_ID_H
16
17#include <string>
18#include <cstring>
19#include <cstdint> // for std::uint8_t, std::uint64_t
20
29
30namespace openvpn {
31template <size_t SIZE>
33{
34 public:
35 template <size_t S>
36 friend class SessionIDType;
37
38 // Create a zeroed Sesson ID.
40 {
41 // compile-time size constraints
42 static_assert(sizeof(u.data) >= sizeof(std::uint64_t), "SessionIDType SIZE too small");
43 static_assert(SIZE % sizeof(std::uint64_t) == size_t(0), "SessionIDType SIZE must be an integer multiple of 64 bits");
44 std::memset(u.data, 0, sizeof(u.data));
45 }
46
47 // Create a random Session ID.
49 {
50 rng.rand_bytes(u.data, sizeof(u.data));
51 }
52
53 // Create a Session ID from a base64 (URL-safe) string.
54 explicit SessionIDType(const std::string &b64)
55 {
56 Buffer srcbuf(u.data, sizeof(u.data), false);
57 try
58 {
59 base64_urlsafe->decode(srcbuf, b64);
60 }
61 catch (const std::exception &e)
62 {
63 throw Exception("SessionID: base64 decode: " + std::string(e.what()));
64 }
65 if (srcbuf.size() != sizeof(u.data))
66 throw Exception("SessionID: wrong input size, actual=" + std::to_string(srcbuf.size()) + " expected=" + std::to_string(sizeof(u.data)));
67 }
68
69 // Create a Session ID from a byte string of size size().
70 explicit SessionIDType(const std::uint8_t *bytes)
71 {
72 std::memcpy(u.data, bytes, SIZE);
73 }
74
75 // Create a Session ID from another Session ID of possibly
76 // different size. If the other Session ID is larger,
77 // truncate, if it's smaller, zero our tail.
78 template <size_t S>
79 explicit SessionIDType(const SessionIDType<S> &other)
80 {
81 for (size_t i = 0; i < array_size(u.dataz); ++i)
82 u.dataz[i] = (i < array_size(other.u.dataz)) ? other.u.dataz[i] : 0;
83 }
84
85 // Create an encrypted Session ID.
86 // Intended to be used with TokenEncrypt.
87 template <typename CRYPT>
88 explicit SessionIDType(const SessionIDType &other, CRYPT &crypt)
89 {
90 crypt(u.data, other.u.data, SIZE);
91 }
92
93 // Session ID is considered to be undefined if all bits are zero.
94 bool defined() const
95 {
96 for (size_t i = 0; i < array_size(u.dataz); ++i)
97 if (u.dataz[i])
98 return true;
99 return false;
100 }
101
102 // Return the lower 64 bits of Session ID regardless of the size.
103 std::uint64_t shortform() const
104 {
105 return u.dataz[0];
106 }
107
108 template <typename HASH>
109 void hash(HASH &h) const
110 {
111 h(u.dataz[0]);
112 }
113
114 // Use a URL-safe base64 encoding.
115 std::string to_string() const
116 {
117 return base64_urlsafe->encode(u.data, sizeof(u.data));
118 }
119
120 bool operator==(const SessionIDType &other) const
121 {
122 return std::memcmp(u.data, other.u.data, sizeof(u.data)) == 0;
123 }
124
125 bool operator!=(const SessionIDType &other) const
126 {
127 return !operator==(other);
128 }
129
130 bool operator<(const SessionIDType &other) const
131 {
132 return std::memcmp(u.data, other.u.data, sizeof(u.data)) < 0;
133 }
134
135 // Weak equality means that the lower 64 bits compare equal.
136 template <size_t S>
137 bool eq_weak(const SessionIDType<S> &other) const
138 {
139 return shortform() == other.shortform();
140 }
141
142 // True if the string looks like a Session ID.
143 static bool is(const std::string &str)
144 {
145 return base64_urlsafe->is_base64(str, SIZE);
146 }
147
148 static constexpr size_t size()
149 {
150 return SIZE;
151 }
152
153 const std::uint8_t *c_data() const
154 {
155 return u.data;
156 }
157
158 // Find an element in an unordered map (keyed by Session ID)
159 // using weak equality. If conflict is true, only return
160 // element that is present by weak equality, but which is
161 // not equal to *this by strong equality.
162 template <typename UNORDERED_MAP>
163 const SessionIDType *find_weak(const UNORDERED_MAP &m, const bool conflict) const
164 {
165 if (m.bucket_count())
166 {
167 const size_t bi = m.bucket(*this);
168 for (auto i = m.cbegin(bi); i != m.cend(bi); ++i)
169 if (shortform() == i->first.shortform() && (!conflict || *this != i->first))
170 return &i->first;
171 }
172 return nullptr;
173 }
174
175 private:
176 union {
177 std::uint64_t dataz[SIZE / sizeof(std::uint64_t)];
178 std::uint8_t data[SIZE];
179 } u;
180};
181
182// Create two concrete types: 64 and 128-bit Session IDs.
185
188} // namespace openvpn
189
192
193#endif
bool is_base64(const V &data, const size_t expected_decoded_length) const
Definition base64.hpp:219
std::string encode(const V &data) const
Definition base64.hpp:139
size_t decode(void *data, size_t len, const std::string &str) const
Definition base64.hpp:186
size_t size() const
Returns the size of the buffer in T objects.
Definition buffer.hpp:1225
virtual void rand_bytes(unsigned char *buf, size_t size)=0
Fill a buffer with random bytes.
SessionIDType(const SessionIDType &other, CRYPT &crypt)
Definition sess_id.hpp:88
std::uint8_t data[SIZE]
Definition sess_id.hpp:178
SessionIDType(const SessionIDType< S > &other)
Definition sess_id.hpp:79
bool operator<(const SessionIDType &other) const
Definition sess_id.hpp:130
std::string to_string() const
Definition sess_id.hpp:115
bool operator==(const SessionIDType &other) const
Definition sess_id.hpp:120
std::uint64_t shortform() const
Definition sess_id.hpp:103
bool defined() const
Definition sess_id.hpp:94
bool eq_weak(const SessionIDType< S > &other) const
Definition sess_id.hpp:137
bool operator!=(const SessionIDType &other) const
Definition sess_id.hpp:125
union openvpn::SessionIDType::@23 u
void hash(HASH &h) const
Definition sess_id.hpp:109
static constexpr size_t size()
Definition sess_id.hpp:148
SessionIDType(const std::string &b64)
Definition sess_id.hpp:54
std::uint64_t dataz[SIZE/sizeof(std::uint64_t)]
Definition sess_id.hpp:177
const SessionIDType * find_weak(const UNORDERED_MAP &m, const bool conflict) const
Definition sess_id.hpp:163
static bool is(const std::string &str)
Definition sess_id.hpp:143
const std::uint8_t * c_data() const
Definition sess_id.hpp:153
SessionIDType(StrongRandomAPI &rng)
Definition sess_id.hpp:48
SessionIDType(const std::uint8_t *bytes)
Definition sess_id.hpp:70
Abstract base class for cryptographically strong random number generators.
Definition randapi.hpp:228
#define OPENVPN_HASH_METHOD(T, meth)
Definition hash.hpp:30
Support deferred server-side state creation when client connects.
Definition ovpncli.cpp:95
std::string to_string(T value)
Definition to_string.hpp:33
constexpr std::size_t array_size(T(&)[N])
Definition arraysize.hpp:19
const Base64 * base64_urlsafe
Definition base64.hpp:300
SessionIDType< 16 > SessionID128
Definition sess_id.hpp:184
SessionIDType< 8 > SessionID64
Definition sess_id.hpp:183
#define OPENVPN_OSTREAM(TYPE, METH)
Definition ostream.hpp:21
Implementation of the base classes for random number generators.