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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef AUTH_TOKEN_H
#define AUTH_TOKEN_H
/**
* Generate an auth token based on username and timestamp
*
* The idea of auth token is to be stateless, so that we can verify use it
* even after we have forgotten about it or server has been restarted.
*
* To achieve this even though we cannot trust the client we use HMAC
* to be able to verify the information.
*
* Format of the auth-token (before base64 encode)
*
* session id(12 bytes)|uint64 timestamp (8 bytes)|
* uint64 timestamp (8 bytes)|sha256-hmac(32 bytes)
*
* The first timestamp is the time the token was initially created and is used to
* determine the maximum renewable time of the token. We always include this even
* if tokens do not expire (this value is not used) to keep the code cleaner.
*
* The second timestamp is the time the token was renewed/regenerated and is used
* to determine if this token has been renewed in the acceptable time range
* (2 * renogiation timeout)
*
* The session id is a random string of 12 byte (or 16 in base64) that is not
* used by OpenVPN itself but kept intact so that external logging/managment
* can track the session multiple reconnects/servers. It is delibrately chosen
* be a multiple of 3 bytes to have a base64 encoding without padding.
*
* The hmac is calculated over the username contactinated with the
* raw auth-token bytes to include authentication of the username in the token
*
* We encode the auth-token with base64 and then prepend "SESS_ID_" before
* sending it to the client.
*
* This function will free() an existing multi->auth_token and keep the
* existing initial timestamp and session id contained in that token.
*/
void
generate_auth_token(const struct user_pass *up, struct tls_multi *multi);
/**
* Verifies the auth token to be in the format that generate_auth_token
* create and checks if the token is valid.
*
*/
unsigned
verify_auth_token(struct user_pass *up, struct tls_multi *multi,
struct tls_session *session);
/**
* Loads an HMAC secret from a file or if no file is present generates a
* epheremal secret for the run time of the server and stores it into ctx
*/
void
auth_token_init_secret(struct key_ctx *key_ctx, const char *key_file,
bool key_inline);
/**
* Generate a auth-token server secret key, and write to file.
*
* @param filename Filename of the server key file to create.
*/
void auth_token_write_server_key_file(const char *filename);
/**
* Put the session id, and auth token status into the environment
* if auth-token is enabled
*
*/
void add_session_token_env(struct tls_session *session, struct tls_multi *multi,
const struct user_pass *up);
/**
* Wipes the authentication token out of the memory, frees and cleans up
* related buffers and flags
*
* @param multi Pointer to a multi object holding the auth_token variables
*/
void wipe_auth_token(struct tls_multi *multi);
/**
* The prefix given to auth tokens start with, this prefix is special
* cased to not show up in log files in OpenVPN 2 and 3
*
* We also prefix this with _AT_ to only act on auth token generated by us.
*/
#define SESSION_ID_PREFIX "SESS_ID_AT_"
/**
* Return if the password string has the format of a password.
*
* This fuction will always read as many bytes as SESSION_ID_PREFIX is longer
* the caller needs ensure that password memory is at least that long (true for
* calling with struct user_pass)
* @param password
* @return whether the password string starts with the session token prefix
*/
static inline bool
is_auth_token(const char *password)
{
return (memcmp_constant_time(SESSION_ID_PREFIX, password,
strlen(SESSION_ID_PREFIX)) == 0);
}
#endif /* AUTH_TOKEN_H */
|