d02a86d3 |
/*
* 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.
* |
49979459 |
* Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net> |
d02a86d3 |
*
* 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.
* |
caa54ac3 |
* 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. |
d02a86d3 |
*/
#ifndef MANAGE_H
#define MANAGE_H
#ifdef ENABLE_MANAGEMENT
#include "misc.h"
#include "event.h"
#include "socket.h"
#include "mroute.h"
|
e7995f3c |
#define MANAGEMENT_VERSION 2 |
d02a86d3 |
#define MANAGEMENT_N_PASSWORD_RETRIES 3
#define MANAGEMENT_LOG_HISTORY_INITIAL_SIZE 100
#define MANAGEMENT_ECHO_BUFFER_SIZE 100
#define MANAGEMENT_STATE_BUFFER_SIZE 100
/*
* Management-interface-based deferred authentication
*/
#ifdef MANAGEMENT_DEF_AUTH
struct man_def_auth_context { |
81d882d5 |
unsigned long cid; |
d02a86d3 |
#define DAF_CONNECTION_ESTABLISHED (1<<0)
#define DAF_CONNECTION_CLOSED (1<<1)
#define DAF_INITIAL_AUTH (1<<2) |
81d882d5 |
unsigned int flags; |
d02a86d3 |
|
81d882d5 |
unsigned int mda_key_id_counter; |
d02a86d3 |
|
81d882d5 |
time_t bytecount_last_update; |
d02a86d3 |
};
#endif
/*
* Manage build-up of command line
*/
struct command_line
{ |
81d882d5 |
struct buffer buf;
struct buffer residual; |
d02a86d3 |
};
|
81d882d5 |
struct command_line *command_line_new(const int buf_len); |
d02a86d3 |
|
81d882d5 |
void command_line_free(struct command_line *cl);
void command_line_add(struct command_line *cl, const unsigned char *buf, const int len);
|
b395f36e |
const char *command_line_get(struct command_line *cl); |
81d882d5 |
void command_line_reset(struct command_line *cl);
void command_line_next(struct command_line *cl); |
d02a86d3 |
/*
* Manage log file history
*/
union log_entry_union { |
81d882d5 |
unsigned int msg_flags;
int state;
int intval; |
d02a86d3 |
};
struct log_entry
{ |
81d882d5 |
time_t timestamp;
const char *string;
in_addr_t local_ip;
struct in6_addr local_ip6;
struct openvpn_sockaddr local_sock;
struct openvpn_sockaddr remote_sock;
union log_entry_union u; |
d02a86d3 |
};
#define LOG_PRINT_LOG_PREFIX (1<<0)
#define LOG_PRINT_ECHO_PREFIX (1<<1)
#define LOG_PRINT_STATE_PREFIX (1<<2)
#define LOG_PRINT_INT_DATE (1<<3)
#define LOG_PRINT_MSG_FLAGS (1<<4)
#define LOG_PRINT_STATE (1<<5)
#define LOG_PRINT_LOCAL_IP (1<<6)
#define LOG_PRINT_CRLF (1<<7)
#define LOG_FATAL_NOTIFY (1<<8)
#define LOG_PRINT_INTVAL (1<<9)
#define LOG_PRINT_REMOTE_IP (1<<10)
#define LOG_ECHO_TO_LOG (1<<11)
|
81d882d5 |
const char *log_entry_print(const struct log_entry *e, unsigned int flags, struct gc_arena *gc); |
d02a86d3 |
struct log_history
{ |
81d882d5 |
int base;
int size;
int capacity;
struct log_entry *array; |
d02a86d3 |
};
|
81d882d5 |
struct log_history *log_history_init(const int capacity);
void log_history_close(struct log_history *h);
void log_history_add(struct log_history *h, const struct log_entry *le);
void log_history_resize(struct log_history *h, const int capacity);
const struct log_entry *log_history_ref(const struct log_history *h, const int index); |
d02a86d3 |
static inline int |
81d882d5 |
log_history_size(const struct log_history *h) |
d02a86d3 |
{ |
81d882d5 |
return h->size; |
d02a86d3 |
}
static inline int |
81d882d5 |
log_history_capacity(const struct log_history *h) |
d02a86d3 |
{ |
81d882d5 |
return h->capacity; |
d02a86d3 |
}
/*
* Callbacks for 'status' and 'kill' commands.
* Also for management-based deferred authentication and packet filter.
*/
struct management_callback
{ |
81d882d5 |
void *arg; |
d02a86d3 |
|
81d882d5 |
#define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */
unsigned int flags; |
d02a86d3 |
|
81d882d5 |
void (*status) (void *arg, const int version, struct status_output *so);
void (*show_net) (void *arg, const int msglevel);
int (*kill_by_cn) (void *arg, const char *common_name);
int (*kill_by_addr) (void *arg, const in_addr_t addr, const int port);
void (*delete_event) (void *arg, event_t event);
int (*n_clients) (void *arg); |
d02a86d3 |
#ifdef MANAGEMENT_DEF_AUTH |
81d882d5 |
bool (*kill_by_cid)(void *arg, const unsigned long cid, const char *kill_msg);
bool (*client_auth) (void *arg,
const unsigned long cid,
const unsigned int mda_key_id,
const bool auth,
const char *reason,
const char *client_reason,
struct buffer_list *cc_config); /* ownership transferred */
char *(*get_peer_info) (void *arg, const unsigned long cid); |
d02a86d3 |
#endif
#ifdef MANAGEMENT_PF |
81d882d5 |
bool (*client_pf)(void *arg,
const unsigned long cid,
struct buffer_list *pf_config); /* ownership transferred */ |
d02a86d3 |
#endif |
81d882d5 |
bool (*proxy_cmd)(void *arg, const char **p);
bool (*remote_cmd) (void *arg, const char **p); |
30003978 |
#ifdef TARGET_ANDROID |
81d882d5 |
int (*network_change)(void *arg, bool samenetwork); |
30003978 |
#endif |
d02a86d3 |
};
/*
* Management object, split into three components:
*
* struct man_persist : Data elements which are persistent across
* man_connection open and close.
*
* struct man_settings : management parameters.
*
* struct man_connection : created on socket binding and listen,
* deleted on socket unbind, may
* handle multiple sequential client
* connections.
*/
struct man_persist { |
81d882d5 |
bool defined; |
d02a86d3 |
|
81d882d5 |
struct log_history *log;
struct virtual_output vout; |
d02a86d3 |
|
81d882d5 |
bool standalone_disabled;
struct management_callback callback; |
d02a86d3 |
|
81d882d5 |
struct log_history *echo; /* saved --echo strings */
struct log_history *state; |
d02a86d3 |
|
81d882d5 |
bool hold_release; |
d02a86d3 |
|
81d882d5 |
const char *special_state_msg; |
d02a86d3 |
|
81d882d5 |
counter_type bytes_in;
counter_type bytes_out; |
d02a86d3 |
};
struct man_settings { |
81d882d5 |
bool defined;
unsigned int flags; /* MF_x flags */
struct addrinfo *local; |
d02a86d3 |
#if UNIX_SOCK_SUPPORT |
81d882d5 |
struct sockaddr_un local_unix; |
d02a86d3 |
#endif |
81d882d5 |
bool management_over_tunnel;
struct user_pass up;
int log_history_cache;
int echo_buffer_size;
int state_buffer_size;
char *write_peer_info_file;
int client_uid;
int client_gid; |
d02a86d3 |
/* flags for handling the management interface "signal" command */ |
81d882d5 |
#define MANSIG_IGNORE_USR1_HUP (1<<0)
#define MANSIG_MAP_USR1_TO_HUP (1<<1)
#define MANSIG_MAP_USR1_TO_TERM (1<<2)
unsigned int mansig; |
d02a86d3 |
};
/* up_query modes */
#define UP_QUERY_DISABLED 0
#define UP_QUERY_USER_PASS 1
#define UP_QUERY_PASS 2
#define UP_QUERY_NEED_OK 3
#define UP_QUERY_NEED_STR 4
/* states */
#define MS_INITIAL 0 /* all sockets are closed */
#define MS_LISTEN 1 /* no client is connected */
#define MS_CC_WAIT_READ 2 /* client is connected, waiting for read on socket */
#define MS_CC_WAIT_WRITE 3 /* client is connected, waiting for ability to write to socket */
struct man_connection { |
81d882d5 |
int state; |
d02a86d3 |
|
81d882d5 |
socket_descriptor_t sd_top;
socket_descriptor_t sd_cli;
struct openvpn_sockaddr remote; |
d02a86d3 |
|
445b192a |
#ifdef _WIN32 |
81d882d5 |
struct net_event_win32 ne32; |
d02a86d3 |
#endif
|
81d882d5 |
bool halt;
bool password_verified;
int password_tries; |
d02a86d3 |
|
81d882d5 |
struct command_line *in;
struct buffer_list *out; |
d02a86d3 |
|
81d882d5 |
#define IEC_UNDEF 0
#define IEC_CLIENT_AUTH 1
#define IEC_CLIENT_PF 2
#define IEC_RSA_SIGN 3
#define IEC_CERTIFICATE 4 |
e7995f3c |
#define IEC_PK_SIGN 5 |
81d882d5 |
int in_extra_cmd;
struct buffer_list *in_extra; |
d02a86d3 |
#ifdef MANAGEMENT_DEF_AUTH |
81d882d5 |
unsigned long in_extra_cid;
unsigned int in_extra_kid; |
d02a86d3 |
#endif |
81d882d5 |
#define EKS_UNDEF 0
#define EKS_SOLICIT 1
#define EKS_INPUT 2
#define EKS_READY 3
int ext_key_state;
struct buffer_list *ext_key_input;
int ext_cert_state;
struct buffer_list *ext_cert_input;
struct event_set *es;
int env_filter_level; |
d02a86d3 |
|
81d882d5 |
bool state_realtime;
bool log_realtime;
bool echo_realtime;
int bytecount_update_seconds;
time_t bytecount_last_update; |
d02a86d3 |
|
81d882d5 |
const char *up_query_type;
int up_query_mode;
struct user_pass up_query; |
d02a86d3 |
|
ad2df7b9 |
#ifdef TARGET_ANDROID |
81d882d5 |
int fdtosend;
int lastfdreceived; |
ad2df7b9 |
#endif |
686fe9ce |
int client_version; |
d02a86d3 |
};
struct management
{ |
81d882d5 |
struct man_persist persist;
struct man_settings settings;
struct man_connection connection; |
d02a86d3 |
};
extern struct management *management;
struct user_pass;
|
81d882d5 |
struct management *management_init(void); |
d02a86d3 |
/* management_open flags */ |
81d882d5 |
#define MF_SERVER (1<<0)
#define MF_QUERY_PASSWORDS (1<<1)
#define MF_HOLD (1<<2)
#define MF_SIGNAL (1<<3)
#define MF_FORGET_DISCONNECT (1<<4)
#define MF_CONNECT_AS_CLIENT (1<<5) |
d02a86d3 |
#ifdef MANAGEMENT_DEF_AUTH |
81d882d5 |
#define MF_CLIENT_AUTH (1<<6) |
d02a86d3 |
#endif
#ifdef MANAGEMENT_PF |
81d882d5 |
#define MF_CLIENT_PF (1<<7) |
d02a86d3 |
#endif |
81d882d5 |
#define MF_UNIX_SOCK (1<<8)
#define MF_EXTERNAL_KEY (1<<9) |
d02a86d3 |
#define MF_UP_DOWN (1<<10) |
54561af6 |
#define MF_QUERY_REMOTE (1<<11) |
af1bf85a |
#define MF_QUERY_PROXY (1<<12) |
39e3d336 |
#define MF_EXTERNAL_CERT (1<<13) |
d02a86d3 |
|
81d882d5 |
bool management_open(struct management *man,
const char *addr,
const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
const int log_history_cache,
const int echo_buffer_size,
const int state_buffer_size,
const char *write_peer_info_file,
const int remap_sigusr1,
const unsigned int flags); |
d02a86d3 |
|
81d882d5 |
void management_close(struct management *man); |
d02a86d3 |
|
81d882d5 |
void management_post_tunnel_open(struct management *man, const in_addr_t tun_local_ip); |
d02a86d3 |
|
81d882d5 |
void management_pre_tunnel_close(struct management *man); |
d02a86d3 |
|
81d882d5 |
void management_socket_set(struct management *man,
struct event_set *es,
void *arg,
unsigned int *persistent); |
d02a86d3 |
|
81d882d5 |
void management_io(struct management *man); |
d02a86d3 |
|
81d882d5 |
void management_set_callback(struct management *man,
const struct management_callback *cb); |
d02a86d3 |
|
81d882d5 |
void management_clear_callback(struct management *man); |
d02a86d3 |
|
81d882d5 |
bool management_query_user_pass(struct management *man,
struct user_pass *up,
const char *type,
const unsigned int flags,
const char *static_challenge); |
d02a86d3 |
|
a55b3cdb |
#ifdef TARGET_ANDROID |
81d882d5 |
bool management_android_control(struct management *man, const char *command, const char *msg); |
c058cbff |
#define ANDROID_KEEP_OLD_TUN 1
#define ANDROID_OPEN_AFTER_CLOSE 2
#define ANDROID_OPEN_BEFORE_CLOSE 3 |
81d882d5 |
int managment_android_persisttun_action(struct management *man);
|
a55b3cdb |
#endif
|
81d882d5 |
bool management_should_daemonize(struct management *man); |
d02a86d3 |
|
81d882d5 |
bool management_would_hold(struct management *man);
bool management_hold(struct management *man, int holdtime);
void management_event_loop_n_seconds(struct management *man, int sec); |
d02a86d3 |
void management_up_down(struct management *man, const char *updown, const struct env_set *es);
|
0df67879 |
void management_notify(struct management *man, const char *severity, const char *type, const char *text);
|
81d882d5 |
void management_notify_generic(struct management *man, const char *str); |
54561af6 |
|
d02a86d3 |
#ifdef MANAGEMENT_DEF_AUTH |
81d882d5 |
void management_notify_client_needing_auth(struct management *management,
const unsigned int auth_id,
struct man_def_auth_context *mdac,
const struct env_set *es);
void management_connection_established(struct management *management,
struct man_def_auth_context *mdac,
const struct env_set *es);
void management_notify_client_close(struct management *management,
struct man_def_auth_context *mdac,
const struct env_set *es);
void management_learn_addr(struct management *management,
struct man_def_auth_context *mdac,
const struct mroute_addr *addr,
const bool primary);
|
d02a86d3 |
#endif
|
e7995f3c |
char *management_query_pk_sig(struct management *man, const char *b64_data); |
81d882d5 |
char *management_query_cert(struct management *man, const char *cert_name); |
d02a86d3 |
static inline bool |
81d882d5 |
management_connected(const struct management *man) |
d02a86d3 |
{ |
81d882d5 |
return man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE; |
d02a86d3 |
}
static inline bool |
81d882d5 |
management_query_user_pass_enabled(const struct management *man) |
d02a86d3 |
{ |
81d882d5 |
return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS); |
d02a86d3 |
}
|
54561af6 |
static inline bool |
81d882d5 |
management_query_remote_enabled(const struct management *man) |
54561af6 |
{ |
81d882d5 |
return BOOL_CAST(man->settings.flags & MF_QUERY_REMOTE); |
54561af6 |
}
|
af1bf85a |
static inline bool |
81d882d5 |
management_query_proxy_enabled(const struct management *man) |
af1bf85a |
{ |
81d882d5 |
return BOOL_CAST(man->settings.flags & MF_QUERY_PROXY); |
af1bf85a |
}
|
d02a86d3 |
#ifdef MANAGEMENT_PF
static inline bool |
81d882d5 |
management_enable_pf(const struct management *man) |
d02a86d3 |
{ |
81d882d5 |
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF); |
d02a86d3 |
}
#endif
#ifdef MANAGEMENT_DEF_AUTH
static inline bool |
81d882d5 |
management_enable_def_auth(const struct management *man) |
d02a86d3 |
{ |
81d882d5 |
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_AUTH); |
d02a86d3 |
}
#endif
/*
* OpenVPN tells the management layer what state it's in
*/
/* client/server states */
#define OPENVPN_STATE_INITIAL 0 /* Initial, undefined state */
#define OPENVPN_STATE_CONNECTING 1 /* Management interface has been initialized */
#define OPENVPN_STATE_ASSIGN_IP 2 /* Assigning IP address to virtual network interface */
#define OPENVPN_STATE_ADD_ROUTES 3 /* Adding routes to system */
#define OPENVPN_STATE_CONNECTED 4 /* Initialization sequence completed */
#define OPENVPN_STATE_RECONNECTING 5 /* Restart */
#define OPENVPN_STATE_EXITING 6 /* Exit */
/* client-only states */
#define OPENVPN_STATE_WAIT 7 /* Waiting for initial response from server */
#define OPENVPN_STATE_AUTH 8 /* Authenticating with server */
#define OPENVPN_STATE_GET_CONFIG 9 /* Downloading configuration from server */
#define OPENVPN_STATE_RESOLVE 10 /* DNS lookup */
#define OPENVPN_STATE_TCP_CONNECT 11 /* Connecting to TCP server */
#define OPENVPN_STATE_CLIENT_BASE 7 /* Base index of client-only states */
|
81d882d5 |
void management_set_state(struct management *man,
const int state,
const char *detail,
const in_addr_t *tun_local_ip,
const struct in6_addr *tun_local_ip6,
const struct openvpn_sockaddr *local_addr,
const struct openvpn_sockaddr *remote_addr); |
d02a86d3 |
/*
* The management object keeps track of OpenVPN --echo
* parameters.
*/ |
81d882d5 |
void management_echo(struct management *man, const char *string, const bool pull); |
d02a86d3 |
/*
* OpenVPN calls here to indicate a password failure
*/
|
81d882d5 |
void management_auth_failure(struct management *man, const char *type, const char *reason); |
d02a86d3 |
/* |
e52e76ce |
* Echo an authentication token to management interface
*/ |
81d882d5 |
void management_auth_token(struct management *man, const char *token); |
e52e76ce |
/* |
d02a86d3 |
* These functions drive the bytecount in/out counters.
*/
|
81d882d5 |
void man_bytecount_output_client(struct management *man); |
d02a86d3 |
static inline void |
81d882d5 |
man_bytecount_possible_output_client(struct management *man) |
d02a86d3 |
{ |
81d882d5 |
if (man->connection.bytecount_update_seconds > 0
&& now >= man->connection.bytecount_last_update
+ man->connection.bytecount_update_seconds)
{
man_bytecount_output_client(man);
} |
d02a86d3 |
}
static inline void |
81d882d5 |
management_bytes_out_client(struct management *man, const int size) |
d02a86d3 |
{ |
81d882d5 |
man->persist.bytes_out += size;
man_bytecount_possible_output_client(man); |
d02a86d3 |
}
static inline void |
81d882d5 |
management_bytes_in_client(struct management *man, const int size) |
d02a86d3 |
{ |
81d882d5 |
man->persist.bytes_in += size;
man_bytecount_possible_output_client(man); |
d02a86d3 |
}
static inline void |
81d882d5 |
management_bytes_out(struct management *man, const int size) |
d02a86d3 |
{ |
81d882d5 |
if (!(man->persist.callback.flags & MCF_SERVER))
{
management_bytes_out_client(man, size);
} |
d02a86d3 |
}
static inline void |
81d882d5 |
management_bytes_in(struct management *man, const int size) |
d02a86d3 |
{ |
81d882d5 |
if (!(man->persist.callback.flags & MCF_SERVER))
{
management_bytes_in_client(man, size);
} |
d02a86d3 |
}
#ifdef MANAGEMENT_DEF_AUTH
|
632af53a |
void man_bytecount_output_server(struct management *man,
const counter_type *bytes_in_total,
const counter_type *bytes_out_total,
struct man_def_auth_context *mdac);
|
d02a86d3 |
static inline void |
81d882d5 |
management_bytes_server(struct management *man,
const counter_type *bytes_in_total,
const counter_type *bytes_out_total,
struct man_def_auth_context *mdac) |
d02a86d3 |
{ |
81d882d5 |
if (man->connection.bytecount_update_seconds > 0
&& now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds
&& (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
{
man_bytecount_output_server(man, bytes_in_total, bytes_out_total, mdac);
} |
d02a86d3 |
}
#endif /* MANAGEMENT_DEF_AUTH */
|
81d882d5 |
#endif /* ifdef ENABLE_MANAGEMENT */ |
45b2af9c |
/**
* A sleep function that services the management layer for n seconds rather
* than doing nothing.
*/
void management_sleep(const int n);
|
81d882d5 |
#endif /* ifndef MANAGE_H */ |