src/openvpn/manage.h
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 */