manage.h
6fbf66fa
 /*
  *  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.
  *
564a2109
  *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
6fbf66fa
  *
  *  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 (see the file COPYING included with this
  *  distribution); if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #ifndef MANAGE_H
 #define MANAGE_H
 
 #ifdef ENABLE_MANAGEMENT
 
 #include "misc.h"
 #include "event.h"
 #include "socket.h"
90efcacb
 #include "mroute.h"
6fbf66fa
 
 #define MANAGEMENT_VERSION                      1
 #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
 
 /*
90efcacb
  * Management-interface-based deferred authentication
  */
 #ifdef MANAGEMENT_DEF_AUTH
 struct man_def_auth_context {
   unsigned long cid;
 
 #define DAF_CONNECTION_ESTABLISHED (1<<0)
 #define DAF_CONNECTION_CLOSED      (1<<1)
 #define DAF_INITIAL_AUTH           (1<<2)
   unsigned int flags;
 
   unsigned int mda_key_id_counter;
5f435d64
 
   time_t bytecount_last_update;
90efcacb
 };
 #endif
 
 /*
6fbf66fa
  * Manage build-up of command line
  */
 struct command_line
 {
   struct buffer buf;
   struct buffer residual;
 };
 
 struct command_line *command_line_new (const int buf_len);
 void command_line_free (struct command_line *cl);
 
 void command_line_add (struct command_line *cl, const unsigned char *buf, const int len);
 const unsigned char *command_line_get (struct command_line *cl);
 void command_line_reset (struct command_line *cl);
 void command_line_next (struct command_line *cl);
 
 /*
  * Manage log file history
  */
 
 union log_entry_union {
   unsigned int msg_flags;
   int state;
3c7f2f55
   int intval;
6fbf66fa
 };
 
 struct log_entry
 {
   time_t timestamp;
   const char *string;
   in_addr_t local_ip;
5ad84585
   in_addr_t remote_ip;
6fbf66fa
   union log_entry_union u;
 };
 
 #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)
 
3c7f2f55
 #define LOG_PRINT_INTVAL       (1<<9)
 
5ad84585
 #define LOG_PRINT_REMOTE_IP    (1<<10)
 
e482a632
 #define LOG_ECHO_TO_LOG        (1<<11)
 
6fbf66fa
 const char *log_entry_print (const struct log_entry *e, unsigned int flags, struct gc_arena *gc);
 
 struct log_history
 {
   int base;
   int size;
   int capacity;
   struct log_entry *array;
 };
 
 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);
 
 static inline int
 log_history_size (const struct log_history *h)
 {
   return h->size;
 }
 
 static inline int
 log_history_capacity (const struct log_history *h)
 {
   return h->capacity;
 }
 
 /*
90efcacb
  * Callbacks for 'status' and 'kill' commands.
  * Also for management-based deferred authentication and packet filter.
6fbf66fa
  */
 struct management_callback
 {
   void *arg;
5f435d64
 
 # define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */
   unsigned int flags;
 
6fbf66fa
   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);
4fb4ce12
   int (*n_clients) (void *arg);
90efcacb
 #ifdef MANAGEMENT_DEF_AUTH
   bool (*kill_by_cid) (void *arg, const unsigned long cid);
   bool (*client_auth) (void *arg,
 		       const unsigned long cid,
 		       const unsigned int mda_key_id,
 		       const bool auth,
 		       const char *reason,
5733ef66
 		       const char *client_reason,
90efcacb
 		       struct buffer_list *cc_config); /* ownership transferred */
aaf72974
   char *(*get_peer_info) (void *arg, const unsigned long cid);
90efcacb
 #endif
 #ifdef MANAGEMENT_PF
   bool (*client_pf) (void *arg,
 		     const unsigned long cid,
 		     struct buffer_list *pf_config);   /* ownership transferred */
 #endif
3cf6c932
 #if HTTP_PROXY_FALLBACK
   bool (*http_proxy_fallback_cmd) (void *arg, const char *server, const char *port, const char *flags);
 #endif
6fbf66fa
 };
 
 /*
  * 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 {
   bool defined;
 
   struct log_history *log;
   struct virtual_output vout;
 
   bool standalone_disabled;
   struct management_callback callback;
 
   struct log_history *echo; /* saved --echo strings */
   struct log_history *state;
 
   bool hold_release;
 
   const char *special_state_msg;
34a507c9
 
   counter_type bytes_in;
   counter_type bytes_out;
6fbf66fa
 };
 
 struct man_settings {
   bool defined;
90efcacb
   unsigned int flags; /* MF_x flags */
8bc93d7f
   struct openvpn_sockaddr local;
bb564a59
 #if UNIX_SOCK_SUPPORT
   struct sockaddr_un local_unix;
 #endif
6fbf66fa
   bool management_over_tunnel;
   struct user_pass up;
   int log_history_cache;
   int echo_buffer_size;
   int state_buffer_size;
8d33c060
   char *write_peer_info_file;
bb564a59
   int client_uid;
   int client_gid;
2c21891e
 
 /* flags for handling the management interface "signal" command */
 # 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;
6fbf66fa
 };
 
 /* up_query modes */
 #define UP_QUERY_DISABLED  0
 #define UP_QUERY_USER_PASS 1
 #define UP_QUERY_PASS      2
984cf003
 #define UP_QUERY_NEED_OK   3
1bda73a7
 #define UP_QUERY_NEED_STR  4
6fbf66fa
 
 /* 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 {
   int state;
 
   socket_descriptor_t sd_top;
   socket_descriptor_t sd_cli;
8bc93d7f
   struct openvpn_sockaddr remote;
6fbf66fa
 
 #ifdef WIN32
   struct net_event_win32 ne32;
 #endif
 
   bool halt;
   bool password_verified;
   int password_tries;
 
   struct command_line *in;
90efcacb
   struct buffer_list *out;
 
 #ifdef MANAGEMENT_DEF_AUTH
 # define IEC_UNDEF       0
 # define IEC_CLIENT_AUTH 1
 # define IEC_CLIENT_PF   2
   int in_extra_cmd;
   unsigned long in_extra_cid;
   unsigned int in_extra_kid;
   struct buffer_list *in_extra;
7e1c085d
   int env_filter_level;
90efcacb
 #endif
6fbf66fa
   struct event_set *es;
 
   bool state_realtime;
   bool log_realtime;
   bool echo_realtime;
34a507c9
   int bytecount_update_seconds;
   time_t bytecount_last_update;
6fbf66fa
 
   const char *up_query_type;
   int up_query_mode;
   struct user_pass up_query;
 };
 
 struct management
 {
   struct man_persist persist;
   struct man_settings settings;
   struct man_connection connection;
 };
 
 extern struct management *management;
 
 struct user_pass;
 
 struct management *management_init (void);
 
90efcacb
 /* management_open flags */
 # 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)
 #ifdef MANAGEMENT_DEF_AUTH
 # define MF_CLIENT_AUTH       (1<<6)
 #endif
 #ifdef MANAGEMENT_PF
 # define MF_CLIENT_PF         (1<<7)
 #endif
86f5c7c9
 # define MF_UNIX_SOCK       (1<<8)
bb564a59
 
6fbf66fa
 bool management_open (struct management *man,
 		      const char *addr,
 		      const int port,
 		      const char *pass_file,
bb564a59
 		      const char *client_user,
 		      const char *client_group,
6fbf66fa
 		      const int log_history_cache,
 		      const int echo_buffer_size,
 		      const int state_buffer_size,
2c21891e
 		      const char *write_peer_info_file,
90efcacb
 		      const int remap_sigusr1,
 		      const unsigned int flags);
6fbf66fa
 
 void management_close (struct management *man);
 
 void management_post_tunnel_open (struct management *man, const in_addr_t tun_local_ip);
 
 void management_pre_tunnel_close (struct management *man);
 
 void management_socket_set (struct management *man,
 			    struct event_set *es,
 			    void *arg,
 			    unsigned int *persistent);
 
 void management_io (struct management *man);
 
 void management_set_callback (struct management *man,
 			      const struct management_callback *cb);
 
 void management_clear_callback (struct management *man);
 
984cf003
 bool management_query_user_pass (struct management *man, struct user_pass *up, const char *type, const unsigned int flags);
6fbf66fa
 
92bbb061
 bool management_should_daemonize (struct management *man);
6fbf66fa
 bool management_would_hold (struct management *man);
 bool management_hold (struct management *man);
 
 void management_event_loop_n_seconds (struct management *man, int sec);
 
90efcacb
 #ifdef MANAGEMENT_DEF_AUTH
 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,
60d9e137
 					struct man_def_auth_context *mdac,
 					const struct env_set *es);
90efcacb
 
 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);
 #endif
 
6fbf66fa
 static inline bool
 management_connected (const struct management *man)
 {
   return man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE;
 }
 
 static inline bool
 management_query_user_pass_enabled (const struct management *man)
 {
90efcacb
   return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
6fbf66fa
 }
 
90efcacb
 #ifdef MANAGEMENT_PF
 static inline bool
 management_enable_pf (const struct management *man)
 {
   return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF);
 }
 #endif
 
 #ifdef MANAGEMENT_DEF_AUTH
 static inline bool
 management_enable_def_auth (const struct management *man)
 {
   return man && BOOL_CAST(man->settings.flags & MF_CLIENT_AUTH);
 }
 #endif
 
6fbf66fa
 /*
  * 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 */
e482a632
 #define OPENVPN_STATE_RESOLVE       10 /* DNS lookup */
 #define OPENVPN_STATE_TCP_CONNECT   11 /* Connecting to TCP server */
6fbf66fa
 
 #define OPENVPN_STATE_CLIENT_BASE   7  /* Base index of client-only states */
 
 void management_set_state (struct management *man,
 			   const int state,
 			   const char *detail,
5ad84585
 			   const in_addr_t tun_local_ip,
 			   const in_addr_t tun_remote_ip);
6fbf66fa
 
 /*
  * The management object keeps track of OpenVPN --echo
  * parameters.
  */
3c7f2f55
 void management_echo (struct management *man, const char *string, const bool pull);
6fbf66fa
 
 /*
  * OpenVPN calls here to indicate a password failure
  */
 
8c7c6be4
 void management_auth_failure (struct management *man, const char *type, const char *reason);
6fbf66fa
 
34a507c9
 /*
  * These functions drive the bytecount in/out counters.
  */
 
5f435d64
 void man_bytecount_output_client (struct management *man);
34a507c9
 
 static inline void
5f435d64
 man_bytecount_possible_output_client (struct management *man)
34a507c9
 {
   if (man->connection.bytecount_update_seconds > 0
       && now >= man->connection.bytecount_last_update
       + man->connection.bytecount_update_seconds)
5f435d64
     man_bytecount_output_client (man);
34a507c9
 }
 
 static inline void
5f435d64
 management_bytes_out_client (struct management *man, const int size)
34a507c9
 {
   man->persist.bytes_out += size;
5f435d64
   man_bytecount_possible_output_client (man);
34a507c9
 }
 
 static inline void
5f435d64
 management_bytes_in_client (struct management *man, const int size)
34a507c9
 {
   man->persist.bytes_in += size;
5f435d64
   man_bytecount_possible_output_client (man);
34a507c9
 }
 
5f435d64
 static inline void
 management_bytes_out (struct management *man, const int size)
 {
   if (!(man->persist.callback.flags & MCF_SERVER))
     management_bytes_out_client (man, size);
 }
6fbf66fa
 
5f435d64
 static inline void
 management_bytes_in (struct management *man, const int size)
 {
   if (!(man->persist.callback.flags & MCF_SERVER))
     management_bytes_in_client (man, size);
 }
 
 #ifdef MANAGEMENT_DEF_AUTH
 
 static inline void
 management_bytes_server (struct management *man,
 			 const counter_type *bytes_in_total,
 			 const counter_type *bytes_out_total,
 			 struct man_def_auth_context *mdac)
 {
   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);
 
   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);
 }
 
 #endif /* MANAGEMENT_DEF_AUTH */
 
3cf6c932
 #if HTTP_PROXY_FALLBACK
 
 void management_http_proxy_fallback_notify (struct management *man, const char *type, const char *remote_ip_hint);
 
 #endif /* HTTP_PROXY_FALLBACK */
 
5f435d64
 #endif
6fbf66fa
 #endif