| 1 | /* Core interface of secnet, to be used by all modules */ |
| 2 | |
| 3 | #ifndef secnet_h |
| 4 | #define secnet_h |
| 5 | |
| 6 | #include "config.h" |
| 7 | #include <stdlib.h> |
| 8 | #include <stdarg.h> |
| 9 | #include <syslog.h> |
| 10 | #include <sys/poll.h> |
| 11 | #include <sys/types.h> |
| 12 | #include <sys/time.h> |
| 13 | #include <netinet/in.h> |
| 14 | |
| 15 | typedef char *string_t; |
| 16 | typedef enum {False,True} bool_t; |
| 17 | |
| 18 | #define ASSERT(x) do { if (!(x)) { fatal("assertion failed line " __LINE__ \ |
| 19 | " file " __FILE__ "\n"); } while(0) |
| 20 | |
| 21 | /***** SHARED types *****/ |
| 22 | |
| 23 | /* These are stored in HOST byte order */ |
| 24 | struct subnet { |
| 25 | uint32_t prefix; |
| 26 | uint32_t mask; |
| 27 | }; |
| 28 | |
| 29 | struct subnet_list { |
| 30 | uint32_t entries; |
| 31 | struct subnet *list; |
| 32 | }; |
| 33 | |
| 34 | /* Match an address (in HOST byte order) with a subnet list. |
| 35 | Returns True if matched. */ |
| 36 | extern bool_t subnet_match(struct subnet_list *list, uint32_t address); |
| 37 | extern bool_t subnets_intersect(struct subnet a, struct subnet b); |
| 38 | extern bool_t subnet_intersects_with_list(struct subnet a, |
| 39 | struct subnet_list *b); |
| 40 | extern bool_t subnet_lists_intersect(struct subnet_list *a, |
| 41 | struct subnet_list *b); |
| 42 | |
| 43 | /***** END of shared types *****/ |
| 44 | |
| 45 | /***** CONFIGURATION support *****/ |
| 46 | |
| 47 | extern bool_t just_check_config; /* If True then we're going to exit after |
| 48 | reading the configuration file */ |
| 49 | |
| 50 | typedef struct dict dict_t; /* Configuration dictionary */ |
| 51 | typedef struct closure closure_t; |
| 52 | typedef struct item item_t; |
| 53 | typedef struct list list_t; /* A list of items */ |
| 54 | |
| 55 | /* Configuration file location, for error-reporting */ |
| 56 | struct cloc { |
| 57 | string_t file; |
| 58 | uint32_t line; |
| 59 | }; |
| 60 | |
| 61 | /* Modules export closures, which can be invoked from the configuration file. |
| 62 | "Invoking" a closure usually returns another closure (of a different |
| 63 | type), but can actually return any configuration object. */ |
| 64 | typedef list_t *(apply_fn)(closure_t *self, struct cloc loc, |
| 65 | dict_t *context, list_t *data); |
| 66 | struct closure { |
| 67 | string_t description; /* For debugging */ |
| 68 | uint32_t type; /* Central registry... */ |
| 69 | apply_fn *apply; |
| 70 | void *interface; /* Interface for use inside secnet; depends on type */ |
| 71 | }; |
| 72 | |
| 73 | enum types { t_null, t_bool, t_string, t_number, t_dict, t_closure }; |
| 74 | struct item { |
| 75 | enum types type; |
| 76 | union { |
| 77 | bool_t bool; |
| 78 | string_t string; |
| 79 | uint32_t number; |
| 80 | dict_t *dict; |
| 81 | closure_t *closure; |
| 82 | } data; |
| 83 | struct cloc loc; |
| 84 | }; |
| 85 | |
| 86 | struct list { |
| 87 | item_t *item; |
| 88 | struct list *next; |
| 89 | }; |
| 90 | |
| 91 | /* In the following two lookup functions, NULL means 'not found' */ |
| 92 | /* Lookup a value in the specified dictionary, or its parents */ |
| 93 | extern list_t *dict_lookup(dict_t *dict, string_t key); |
| 94 | /* Lookup a value in just the specified dictionary */ |
| 95 | extern list_t *dict_lookup_primitive(dict_t *dict, string_t key); |
| 96 | /* Add a value to the specified dictionary */ |
| 97 | extern void dict_add(dict_t *dict, string_t key, list_t *val); |
| 98 | /* Obtain an array of keys in the dictionary. malloced; caller frees */ |
| 99 | extern string_t *dict_keys(dict_t *dict); |
| 100 | |
| 101 | /* List-manipulation functions */ |
| 102 | extern list_t *list_new(void); |
| 103 | extern list_t *list_append(list_t *a, item_t *i); |
| 104 | extern list_t *list_append_list(list_t *a, list_t *b); |
| 105 | /* Returns an item from the list (index starts at 0), or NULL */ |
| 106 | extern item_t *list_elem(list_t *l, uint32_t index); |
| 107 | |
| 108 | /* Convenience functions */ |
| 109 | extern list_t *new_closure(closure_t *cl); |
| 110 | extern void add_closure(dict_t *dict, string_t name, apply_fn apply); |
| 111 | extern void *find_cl_if(dict_t *dict, string_t name, uint32_t type, |
| 112 | bool_t fail_if_invalid, string_t desc, |
| 113 | struct cloc loc); |
| 114 | extern item_t *dict_find_item(dict_t *dict, string_t key, bool_t required, |
| 115 | string_t desc, struct cloc loc); |
| 116 | extern string_t dict_read_string(dict_t *dict, string_t key, bool_t required, |
| 117 | string_t desc, struct cloc loc); |
| 118 | extern uint32_t dict_read_number(dict_t *dict, string_t key, bool_t required, |
| 119 | string_t desc, struct cloc loc, uint32_t def); |
| 120 | extern bool_t dict_read_bool(dict_t *dict, string_t key, bool_t required, |
| 121 | string_t desc, struct cloc loc, bool_t def); |
| 122 | extern void dict_read_subnet_list(dict_t *dict, string_t key, bool_t required, |
| 123 | string_t desc, struct cloc loc, |
| 124 | struct subnet_list *sl); |
| 125 | extern uint32_t string_to_ipaddr(item_t *i, string_t desc); |
| 126 | |
| 127 | /***** END of configuration support *****/ |
| 128 | |
| 129 | /***** UTILITY functions *****/ |
| 130 | |
| 131 | #define M_WARNING 1 |
| 132 | #define M_ERROR 2 |
| 133 | #define M_FATAL 4 |
| 134 | #define M_INFO 8 |
| 135 | #define M_DEBUG_CONFIG 16 |
| 136 | #define M_DEBUG_PHASE 32 |
| 137 | |
| 138 | extern void fatal(char *message, ...); |
| 139 | extern void fatal_perror(char *message, ...); |
| 140 | extern void fatal_status(int status, char *message, ...); |
| 141 | extern void fatal_perror_status(int status, char *message, ...); |
| 142 | extern void cfgfatal(struct cloc loc, string_t facility, char *message, ...); |
| 143 | |
| 144 | extern char *safe_strdup(char *string, char *message); |
| 145 | extern void *safe_malloc(size_t size, char *message); |
| 146 | |
| 147 | extern void Message(uint32_t class, char *message, ...); |
| 148 | |
| 149 | extern string_t ipaddr_to_string(uint32_t addr); |
| 150 | extern string_t subnet_to_string(struct subnet *sn); |
| 151 | |
| 152 | extern int sys_cmd(const char *file, char *argc, ...); |
| 153 | |
| 154 | /***** END of utility functions *****/ |
| 155 | |
| 156 | /***** SCHEDULING support */ |
| 157 | |
| 158 | /* "now" is current program time, in milliseconds. It is derived |
| 159 | (once) from tv_now. If nfds_io is insufficient for your needs, set |
| 160 | it to the required number and return ERANGE. timeout is in milliseconds; |
| 161 | if it is too high then lower it. It starts at -1 (==infinite) */ |
| 162 | typedef int beforepoll_fn(void *st, struct pollfd *fds, int *nfds_io, |
| 163 | int *timeout_io, const struct timeval *tv_now, |
| 164 | uint64_t *now); |
| 165 | typedef void afterpoll_fn(void *st, struct pollfd *fds, int nfds, |
| 166 | const struct timeval *tv_now, uint64_t *now); |
| 167 | |
| 168 | /* Register interest in the main loop of the program. Before a call |
| 169 | to poll() your supplied beforepoll function will be called. After |
| 170 | the call to poll() the supplied afterpoll function will be called. |
| 171 | max_nfds is a _hint_ about the maximum number of struct pollfd |
| 172 | structures you may require - you can always ask for more in |
| 173 | *nfds_io. */ |
| 174 | extern void register_for_poll(void *st, beforepoll_fn *before, |
| 175 | afterpoll_fn *after, uint32_t max_nfds, |
| 176 | string_t desc); |
| 177 | |
| 178 | /***** END of scheduling support */ |
| 179 | |
| 180 | /***** PROGRAM LIFETIME support */ |
| 181 | |
| 182 | /* The secnet program goes through a number of phases in its lifetime. |
| 183 | Module code may arrange to be called just as various phases are |
| 184 | entered. */ |
| 185 | |
| 186 | #define PHASE_INIT 0 |
| 187 | #define PHASE_GETOPTS 1 /* Process command-line arguments */ |
| 188 | #define PHASE_READCONFIG 2 /* Parse and process configuration file */ |
| 189 | #define PHASE_SETUP 3 /* Process information in configuration */ |
| 190 | #define PHASE_GETRESOURCES 4 /* Obtain all external resources */ |
| 191 | #define PHASE_DROPPRIV 5 /* Last chance for privileged operations */ |
| 192 | #define PHASE_RUN 6 |
| 193 | #define PHASE_SHUTDOWN 7 /* About to die; delete key material, etc. */ |
| 194 | #define NR_PHASES 8 |
| 195 | |
| 196 | typedef void hook_fn(void *self, uint32_t newphase); |
| 197 | bool_t add_hook(uint32_t phase, hook_fn *f, void *state); |
| 198 | bool_t remove_hook(uint32_t phase, hook_fn *f, void *state); |
| 199 | |
| 200 | /***** END of program lifetime support *****/ |
| 201 | |
| 202 | /***** MODULE support *****/ |
| 203 | |
| 204 | /* Module initialisation function type - modules export one function of |
| 205 | this type which is called to initialise them. For dynamically loaded |
| 206 | modules it's called "secnet_module". */ |
| 207 | typedef void (init_module)(dict_t *dict); |
| 208 | |
| 209 | /***** END of module support *****/ |
| 210 | |
| 211 | /***** CLOSURE TYPES and interface definitions *****/ |
| 212 | |
| 213 | #define CL_PURE 0 |
| 214 | #define CL_RESOLVER 1 |
| 215 | #define CL_RANDOMSRC 2 |
| 216 | #define CL_RSAPUBKEY 3 |
| 217 | #define CL_RSAPRIVKEY 4 |
| 218 | #define CL_COMM 5 |
| 219 | #define CL_IPIF 6 |
| 220 | #define CL_LOG 7 |
| 221 | #define CL_SITE 8 |
| 222 | #define CL_TRANSFORM 9 |
| 223 | #define CL_NETLINK 10 |
| 224 | #define CL_DH 11 |
| 225 | #define CL_HASH 12 |
| 226 | #define CL_BUFFER 13 |
| 227 | |
| 228 | struct buffer_if; |
| 229 | |
| 230 | /* PURE closure requires no interface */ |
| 231 | |
| 232 | /* RESOLVER interface */ |
| 233 | |
| 234 | /* Answers to queries are delivered to a function of this |
| 235 | type. 'address' will be NULL if there was a problem with the query. It |
| 236 | will be freed once resolve_answer_fn returns. It is in network byte |
| 237 | order. */ |
| 238 | typedef void resolve_answer_fn(void *st, struct in_addr *addr); |
| 239 | typedef bool_t resolve_request_fn(void *st, string_t name, |
| 240 | resolve_answer_fn *cb, void *cst); |
| 241 | struct resolver_if { |
| 242 | void *st; |
| 243 | resolve_request_fn *request; |
| 244 | }; |
| 245 | |
| 246 | /* RANDOMSRC interface */ |
| 247 | |
| 248 | /* Return some random data. Returns TRUE for success. */ |
| 249 | typedef bool_t random_fn(void *st, uint32_t bytes, uint8_t *buff); |
| 250 | |
| 251 | struct random_if { |
| 252 | void *st; |
| 253 | bool_t blocking; |
| 254 | random_fn *generate; |
| 255 | }; |
| 256 | |
| 257 | /* RSAPUBKEY interface */ |
| 258 | |
| 259 | typedef bool_t rsa_checksig_fn(void *st, uint8_t *data, uint32_t datalen, |
| 260 | string_t signature); |
| 261 | struct rsapubkey_if { |
| 262 | void *st; |
| 263 | rsa_checksig_fn *check; |
| 264 | }; |
| 265 | |
| 266 | /* RSAPRIVKEY interface */ |
| 267 | |
| 268 | typedef string_t rsa_makesig_fn(void *st, uint8_t *data, uint32_t datalen); |
| 269 | struct rsaprivkey_if { |
| 270 | void *st; |
| 271 | rsa_makesig_fn *sign; |
| 272 | }; |
| 273 | |
| 274 | /* COMM interface */ |
| 275 | |
| 276 | /* Return True if the packet was processed, and shouldn't be passed to |
| 277 | any other potential receivers. */ |
| 278 | typedef bool_t comm_notify_fn(void *state, struct buffer_if *buf, |
| 279 | struct sockaddr_in *source); |
| 280 | typedef void comm_request_notify_fn(void *commst, void *nst, |
| 281 | comm_notify_fn *fn); |
| 282 | typedef void comm_release_notify_fn(void *commst, void *nst, |
| 283 | comm_notify_fn *fn); |
| 284 | typedef bool_t comm_sendmsg_fn(void *commst, struct buffer_if *buf, |
| 285 | struct sockaddr_in *dest); |
| 286 | struct comm_if { |
| 287 | void *st; |
| 288 | comm_request_notify_fn *request_notify; |
| 289 | comm_release_notify_fn *release_notify; |
| 290 | comm_sendmsg_fn *sendmsg; |
| 291 | }; |
| 292 | |
| 293 | /* LOG interface */ |
| 294 | |
| 295 | typedef void log_msg_fn(void *st, int priority, char *message, ...); |
| 296 | typedef void log_vmsg_fn(void *st, int priority, char *message, va_list args); |
| 297 | struct log_if { |
| 298 | void *st; |
| 299 | log_msg_fn *log; |
| 300 | log_vmsg_fn *vlog; |
| 301 | }; |
| 302 | /* (convenience function, defined in util.c) */ |
| 303 | extern void log(struct log_if *lf, int priority, char *message, ...); |
| 304 | |
| 305 | /* SITE interface */ |
| 306 | |
| 307 | /* Pretty much a placeholder; allows starting and stopping of processing, |
| 308 | key expiry, etc. */ |
| 309 | typedef void site_control_fn(void *st, bool_t run); |
| 310 | typedef uint32_t site_status_fn(void *st); |
| 311 | struct site_if { |
| 312 | void *st; |
| 313 | site_control_fn *control; |
| 314 | site_status_fn *status; |
| 315 | }; |
| 316 | |
| 317 | /* TRANSFORM interface */ |
| 318 | |
| 319 | /* A reversable transformation. Transforms buffer in-place; may add |
| 320 | data to start or end. Maximum amount of data to be added specified |
| 321 | in max_start_pad and max_end_pad. (Reverse transformations decrease |
| 322 | length, of course.) Transformations may be key-dependent, in which |
| 323 | case key material is passed in at initialisation time. They may |
| 324 | also depend on internal factors (eg. time) and keep internal |
| 325 | state. A struct transform_if only represents a particular type of |
| 326 | transformation; instances of the transformation (eg. with |
| 327 | particular key material) have a different C type. */ |
| 328 | |
| 329 | typedef struct transform_inst_if *transform_createinstance_fn(void *st); |
| 330 | typedef bool_t transform_setkey_fn(void *st, uint8_t *key, uint32_t keylen); |
| 331 | typedef void transform_delkey_fn(void *st); |
| 332 | typedef void transform_destroyinstance_fn(void *st); |
| 333 | /* Returns 0 for 'all is well', any other value for a problem */ |
| 334 | typedef uint32_t transform_apply_fn(void *st, struct buffer_if *buf, |
| 335 | char **errmsg); |
| 336 | |
| 337 | struct transform_inst_if { |
| 338 | void *st; |
| 339 | transform_setkey_fn *setkey; |
| 340 | transform_delkey_fn *delkey; |
| 341 | transform_apply_fn *forwards; |
| 342 | transform_apply_fn *reverse; |
| 343 | transform_destroyinstance_fn *destroy; |
| 344 | }; |
| 345 | |
| 346 | struct transform_if { |
| 347 | void *st; |
| 348 | uint32_t max_start_pad; |
| 349 | uint32_t max_end_pad; |
| 350 | uint32_t keylen; |
| 351 | transform_createinstance_fn *create; |
| 352 | }; |
| 353 | |
| 354 | /* NETLINK interface */ |
| 355 | |
| 356 | /* Used by netlink to deliver to site, and by site to deliver to netlink. |
| 357 | cid is the client identifier returned by netlink_regnets_fn */ |
| 358 | typedef void netlink_deliver_fn(void *st, void *cid, struct buffer_if *buf); |
| 359 | /* site code can tell netlink when outgoing packets will be dropped, |
| 360 | so netlink can generate appropriate ICMP */ |
| 361 | typedef void netlink_can_deliver_fn(void *st, void *cid, bool_t can_deliver); |
| 362 | /* Register for packets from specified networks. Return value is client |
| 363 | identifier. */ |
| 364 | typedef void *netlink_regnets_fn(void *st, struct subnet_list *networks, |
| 365 | netlink_deliver_fn *deliver, void *dst, |
| 366 | uint32_t max_start_pad, uint32_t max_end_pad, |
| 367 | string_t client_name); |
| 368 | |
| 369 | struct netlink_if { |
| 370 | void *st; |
| 371 | netlink_regnets_fn *regnets; |
| 372 | netlink_deliver_fn *deliver; |
| 373 | netlink_can_deliver_fn *set_delivery; |
| 374 | }; |
| 375 | |
| 376 | /* DH interface */ |
| 377 | |
| 378 | /* Returns public key as a malloced hex string */ |
| 379 | typedef string_t dh_makepublic_fn(void *st, uint8_t *secret, |
| 380 | uint32_t secretlen); |
| 381 | /* Fills buffer (up to buflen) with shared secret */ |
| 382 | typedef void dh_makeshared_fn(void *st, uint8_t *secret, |
| 383 | uint32_t secretlen, string_t rempublic, |
| 384 | uint8_t *sharedsecret, uint32_t buflen); |
| 385 | struct dh_if { |
| 386 | void *st; |
| 387 | uint32_t len; /* Approximate size of modulus in bytes */ |
| 388 | dh_makepublic_fn *makepublic; |
| 389 | dh_makeshared_fn *makeshared; |
| 390 | }; |
| 391 | |
| 392 | /* HASH interface */ |
| 393 | |
| 394 | typedef void *hash_init_fn(void); |
| 395 | typedef void hash_update_fn(void *st, uint8_t const *buf, uint32_t len); |
| 396 | typedef void hash_final_fn(void *st, uint8_t *digest); |
| 397 | struct hash_if { |
| 398 | uint32_t len; /* Hash output length in bytes */ |
| 399 | hash_init_fn *init; |
| 400 | hash_update_fn *update; |
| 401 | hash_final_fn *final; |
| 402 | }; |
| 403 | |
| 404 | /* BUFFER interface */ |
| 405 | |
| 406 | struct buffer_if { |
| 407 | bool_t free; |
| 408 | string_t owner; /* Set to constant string */ |
| 409 | uint32_t flags; /* How paranoid should we be? */ |
| 410 | struct cloc loc; /* Where we were defined */ |
| 411 | uint8_t *base; |
| 412 | uint8_t *start; |
| 413 | uint32_t size; /* Size of buffer contents */ |
| 414 | uint32_t len; /* Total length allocated at base */ |
| 415 | }; |
| 416 | |
| 417 | #endif /* secnet_h */ |