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