blob: fe079457a87dca253f46439e37be6df9a9f81970 [file] [log] [blame]
/*
* 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-2018 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 */