1 /* 2 * Advanced Exchange Access (AXA) common code for RAD and SRA clients 3 * 4 * Copyright (c) 2014-2018 by Farsight Security, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #ifndef AXA_CLIENT_H 20 #define AXA_CLIENT_H 21 22 /** 23 * \defgroup axa_client axa_client 24 * 25 * `axa_client` contains AXA client macros, data type definitions, and 26 * function prototypes. 27 * 28 * @{ 29 */ 30 31 #include <axa/axa.h> 32 #include <axa/wire.h> 33 34 /** 35 * maximum length of an AXA server specification such as "unix user@host" 36 */ 37 #define AXA_MAX_SRVRLEN (4+64+1025+1) 38 39 40 /** @cond */ 41 /* obsolete but retained for upward compatibility */ 42 #define AXA_CLIENT_TYPE_UNIX_STR AXA_IO_TYPE_UNIX_STR 43 #define AXA_CLIENT_TYPE_TCP_STR AXA_IO_TYPE_TCP_STR 44 #define AXA_CLIENT_TYPE_SSH_STR AXA_IO_TYPE_SSH_STR 45 /** @endcond */ 46 47 /** AXA client state */ 48 typedef struct { 49 axa_io_t io; /**< I/O context */ 50 51 struct timeval retry; /**< connection retry timer */ 52 time_t backoff; /**< connection back-off quantum */ 53 54 char *hello; /**< HELLO string from server */ 55 56 bool have_id; /**< for AXA_P_OP_JOIN */ 57 axa_p_clnt_id_t clnt_id; /**< unique client ID */ 58 } axa_client_t; 59 60 /** 61 * Check than an AXA client context is closed. 62 * 63 * \param[in] client address of a client context 64 */ 65 #define AXA_CLIENT_OPENED(client) AXA_IO_OPENED(&((client)->io)) 66 67 /** 68 * Check that an AXA client context is open and connected. 69 * 70 * \param[in] client address of a client context 71 */ 72 #define AXA_CLIENT_CONNECTED(client) AXA_IO_CONNECTED(&((client)->io)) 73 74 /** 75 * (Re-)initialize an AXA client context with default values. 76 * 77 * \param[in] client address of a client context 78 */ 79 extern void axa_client_init(axa_client_t *client); 80 81 /** 82 * Disconnect from the server and increase the delay before trying again. 83 * 84 * \param[in] client address of a client context 85 */ 86 extern void axa_client_backoff(axa_client_t *client); 87 88 /** 89 * Disconnect from the server and increase the delay before trying again to 90 * the maximum. 91 * 92 * \param[in] client address of a client context 93 */ 94 extern void axa_client_backoff_max(axa_client_t *client); 95 96 /** 97 * Reset the delay before try to connect to zero. 98 * 99 * \param[in] client address of a client context 100 */ 101 extern void axa_client_backoff_reset(axa_client_t *client); 102 103 /** 104 * Get the number of milliseconds before the server connection should be 105 * attempted again. 106 * 107 * \param[in] client address of a client context 108 * \param[out] now current wall clock time or NULL 109 * 110 * \return <= 0 if yes 111 */ 112 extern time_t axa_client_again(axa_client_t *client, struct timeval *now); 113 114 /** 115 * Close the server connection and release buffers. 116 * 117 * \param[in] client address of a client context 118 */ 119 extern void axa_client_close(axa_client_t *client); 120 121 /** return codes for axa_client_open() and axa_client_connect() */ 122 typedef enum { 123 /** 124 * Permanent failure. The connection has been closed and 125 * axa_client_backoff() called. Check emsg. 126 */ 127 AXA_CONNECT_ERR, 128 129 /** 130 * Temporary failure. The connection has been closed and 131 * axa_client_backoff() called. Check emsg 132 */ 133 AXA_CONNECT_TEMP, 134 135 /** connection is complete */ 136 AXA_CONNECT_DONE, 137 138 /** non-blocking connection waiting for TCP syn-ack or TLS handshake */ 139 AXA_CONNECT_INCOM, 140 141 /** 142 * Connection now completed including sending the initial AXA_P_OP_NOP. 143 * emsg contains the result of 144 * axa_p_to_str(emsg->c, sizeof(emsg->c), true, ...) 145 */ 146 AXA_CONNECT_NOP, 147 148 /** 149 * Connection now completed including sending the initial AXA_P_OP_USER. 150 * An AXA_P_OP_OK or AXA_P_OP_ERROR should be coming. emsg contains the 151 * result of axa_p_to_str(emsg->c, sizeof(emsg->c), true, ...) 152 */ 153 AXA_CONNECT_USER 154 } axa_connect_result_t; 155 156 /** 157 * Create a new server connection perhaps after closing an existing 158 * connection. axa_client_connect() must be called after a result other 159 * than AXA_CONNECT_DONE, AXA_CONNECT_NOP, or AXA_CONNECT_USER. 160 * 161 * \param[out] emsg if something goes wrong, this will contain the reason 162 * \param[in] client address of a client context 163 * \param[in] is_rad true if server is radd instead of srad 164 * \param[in] addr connect to this AXA server specification 165 * \param[in] tun_debug true to turn on ssh tunnel debugging 166 * \param[in] bufsize 0 or desired socket buffer sizes 167 * \param[in] nonblock true to start the connection without blocking and 168 * to make the connection non-blocking 169 * 170 * \retval one of #axa_connect_result_t 171 */ 172 extern axa_connect_result_t axa_client_open(axa_emsg_t *emsg, 173 axa_client_t *client, 174 const char *addr, bool is_rad, 175 bool tun_debug, 176 int bufsize, bool nonblock); 177 178 /** 179 * Finish a new connection to an SRA or RAD server. 180 * The connection must have been previously opened with axa_client_open(), 181 * which must have returned #AXA_CONNECT_TEMP. 182 * axa_client_connect() must be called again when it returns #AXA_CONNECT_TEMP. 183 * 184 * \param[out] emsg if something goes wrong, this will contain the reason 185 * \param[in] client address of a client context 186 * 187 * \retval one of #axa_connect_result_t 188 */ 189 extern axa_connect_result_t axa_client_connect(axa_emsg_t *emsg, 190 axa_client_t *client); 191 192 /** 193 * Send an AXA message to the server connected through a client context, 194 * blocking until finished. 195 * 196 * \param[out] emsg if something goes wrong, this will contain the reason 197 * \param[in] client address of a client context 198 * \param[in] tag AXA tag 199 * \param[in] op AXA opcode 200 * \param[out] hdr AXA protocol header to be built or NULL 201 * \param[in] body NULL or optional body of the AXA message after the header 202 * \param[in] body_len length of body 203 * 204 * \retval true success 205 * \retval false error. Call axa_client_backoff() and check check emsg. 206 */ 207 extern bool axa_client_send(axa_emsg_t *emsg, axa_client_t *client, 208 axa_tag_t tag, axa_p_op_t op, axa_p_hdr_t *hdr, 209 const void *body, size_t body_len); 210 211 /** 212 * Retrieve a detailed string describing the local host/config to pass to 213 * the AXA server as part of a client HELLO message. 214 * 215 * \param[out] emsg if something goes wrong, this will contain the reason 216 * \param[in] origin null-terminated string containing the name of the 217 * requesting client application or service, i.e. radtool, sratunnel, etc. 218 * \param[in] client address of the client context 219 * \param[out] out pointer to a char * that is assigned on success. Must be 220 * freed by caller. 221 * 222 * \retval true version string was generated successfully 223 * \retval false error occurred making client HELLO string 224 */ 225 extern bool 226 axa_client_get_hello_string(axa_emsg_t *emsg, const char *origin, 227 axa_client_t *client, char **out); 228 229 /** 230 * Examine HELLO message from server to pick a common protocol version 231 * and save session information. 232 * 233 * \param[out] emsg if something goes wrong, this will contain the reason 234 * \param[in] client address of the client context 235 * default to &client->recv_body->hello if NULL 236 * \param[in] hello address of the received HELLO message or NULL, which 237 * implies client->recv_body->hello 238 * \param[in] origin null-terminated string with name of requesting 239 * application, which will be sent back in a client HELLO string 240 * 241 * \retval true parameters saved 242 * \retval false bad HELLO 243 */ 244 extern bool axa_client_hello(axa_emsg_t *emsg, axa_client_t *client, 245 const axa_p_hello_t* hello, const char *origin); 246 /**@}*/ 247 248 #endif /* AXA_CLIENT_H */ 249