Revamping for listeners.
[libradsec.git] / lib / include / radsec / radsec-impl.h
1 /** @file libradsec-impl.h
2     @brief Libraray internal header file for libradsec. */
3
4 /* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
5    See LICENSE for licensing information. */
6
7 #ifndef _RADSEC_RADSEC_IMPL_H_
8 #define _RADSEC_RADSEC_IMPL_H_ 1
9
10 #include <assert.h>
11 #include <event2/util.h>
12 #include <confuse.h>
13 #if defined(RS_ENABLE_TLS)
14 #include <openssl/ssl.h>
15 #endif
16 #include "compat.h"
17
18 /**************/
19 /* Constants. */
20 #define RS_HEADER_LEN 4
21 #define RS_CONN_MAGIC_BASE 0xAE004711u
22 #define RS_CONN_MAGIC_GENERIC 0x843AEF47u
23 #define RS_CONN_MAGIC_LISTENER 0xDCB04783u
24
25 /***************/
26 /* Data types. */
27 enum rs_cred_type {
28     RS_CRED_NONE = 0,
29     /* TLS pre-shared keys, RFC 4279. */
30     RS_CRED_TLS_PSK,
31     /* RS_CRED_TLS_DH_PSK, */
32     /* RS_CRED_TLS_RSA_PSK, */
33 };
34 typedef unsigned int rs_cred_type_t;
35
36 enum rs_key_encoding {
37     RS_KEY_ENCODING_UTF8 = 1,
38     RS_KEY_ENCODING_ASCII_HEX = 2,
39 };
40 typedef unsigned int rs_key_encoding_t;
41
42 enum rs_peer_type {
43     RS_PEER_TYPE_CLIENT = 1,
44     RS_PEER_TYPE_SERVER = 2
45 };
46
47 enum rs_conn_subtype {
48     RS_CONN_OBJTYPE_BASE = 1,
49     RS_CONN_OBJTYPE_GENERIC,
50     RS_CONN_OBJTYPE_LISTENER,
51 };
52
53 #if defined (__cplusplus)
54 extern "C" {
55 #endif
56
57 struct rs_credentials {
58     enum rs_cred_type type;
59     char *identity;
60     char *secret;
61     enum rs_key_encoding secret_encoding;
62 };
63
64 struct rs_error {
65     int code;
66     char buf[1024];
67 };
68
69 /** Configuration object for a connection. */
70 struct rs_peer {
71     enum rs_peer_type type;
72     struct rs_conn_base *connbase; /**< For error handling. */
73     struct rs_realm *realm;
74     char *hostname;
75     char *service;
76     char *secret;               /* RADIUS secret. */
77     struct evutil_addrinfo *addr_cache;
78     char *cacertfile;
79     char *cacertpath;
80     char *certfile;
81     char *certkeyfile;
82     struct rs_credentials *transport_cred;
83     struct rs_peer *next;
84 };
85
86 /** Configuration object for a RADIUS realm. */
87 struct rs_realm {
88     char *name;
89     enum rs_conn_type type;
90     int timeout;
91     int retries;
92     struct rs_listener *listeners;
93     struct rs_peer *peers;
94     struct rs_realm *next;
95 };
96
97 /** Top configuration object. */
98 struct rs_config {
99     struct rs_realm *realms;
100     cfg_t *cfg;
101 };
102
103 /** Libradsec context. */
104 struct rs_context {
105     struct rs_config *config;
106     struct rs_alloc_scheme alloc_scheme;
107     struct rs_error *err;
108     struct event_base *evb;     /* Event base. */
109 };
110
111 /** Base class for a connection. */
112 struct rs_conn_base {
113     uint32_t magic;             /* Must be one of RS_CONN_MAGIC_*. */
114     struct rs_context *ctx;
115     struct rs_realm *realm;     /* Owned by ctx. */
116     /** For a listener, allowed client addr/port pairs.
117      For an outgoing connection, set of servers.
118      For an incoming connection, the peer (as the only entry). */
119     struct rs_peer *peers;      /**< Configured peers. */
120     struct rs_peer *active_peer; /**< The other end of the connection. */
121     struct timeval timeout;
122     int tryagain;               /* For server failover. */
123     void *user_data;
124     struct rs_error *err;
125     int fd;                     /* Socket. */
126     /* TCP transport specifics. */
127     struct bufferevent *bev;    /* Buffer event. */
128     /* UDP transport specifics. */
129     struct event *wev;          /* Write event (for UDP). */
130     struct event *rev;          /* Read event (for UDP). */
131 };
132
133
134 enum rs_conn_state {
135     RS_CONN_STATE_UNDEFINED = 0,
136     RS_CONN_STATE_CONNECTING,
137     RS_CONN_STATE_CONNECTED,
138 };
139
140 /** A "generic" connection. */
141 struct rs_connection {
142     struct rs_conn_base base_;
143     struct event *tev;          /* Timeout event. */
144     struct rs_conn_callbacks callbacks;
145     enum rs_conn_state state;
146 #if 0
147     char is_connecting;         /* FIXME: replace with a single state member */
148     char is_connected;          /* FIXME: replace with a single state member */
149 #endif                          /* 0 */
150     struct rs_message *out_queue; /* Queue for outgoing UDP packets. */
151 #if defined(RS_ENABLE_TLS)
152     /* TLS specifics. */
153     SSL_CTX *tls_ctx;
154     SSL *tls_ssl;
155 #endif
156 };
157
158 /** A listening connection. Spawns generic connections when peers
159  * connect to it. */
160 struct rs_listener {
161     struct rs_conn_base base_;
162     struct evconnlistener *evlistener;
163     struct rs_listener_callbacks callbacks;
164     struct rs_listener *next;
165 };
166
167 enum rs_message_flags {
168     RS_MESSAGE_HEADER_READ,
169     RS_MESSAGE_RECEIVED,
170     RS_MESSAGE_SENT,
171 };
172
173 struct radius_packet;
174
175 struct rs_message {
176     struct rs_connection *conn;
177     unsigned int flags;
178     uint8_t hdr[RS_HEADER_LEN];
179     struct radius_packet *rpkt; /* FreeRADIUS object. */
180     struct rs_message *next;    /* Used for UDP output queue. */
181 };
182
183 #if defined (__cplusplus)
184 }
185 #endif
186
187 /***********************/
188 /* Convenience macros. */
189
190 /* Memory allocation. */
191 #define rs_calloc(h, nmemb, size) ((h)->alloc_scheme.calloc != NULL \
192      ? (h)->alloc_scheme.calloc : calloc)((nmemb), (size))
193 #define rs_malloc(h, size) ((h)->alloc_scheme.malloc != NULL \
194      ? (h)->alloc_scheme.malloc : malloc)((size))
195 #define rs_free(h, ptr) ((h)->alloc_scheme.free != NULL \
196      ? (h)->alloc_scheme.free : free)((ptr))
197 #define rs_realloc(h, ptr, size) ((h)->alloc_scheme.realloc != NULL \
198      ? (h)->alloc_scheme.realloc : realloc)((ptr), (size))
199 #define min(a, b) ((a) < (b) ? (a) : (b))
200 #define max(a, b) ((a) > (b) ? (a) : (b))
201
202 /* Basic CPP-based classes, proudly borrowed from Tor. */
203 #if defined(__GNUC__) && __GNUC__ > 3
204  #define STRUCT_OFFSET(tp, member) __builtin_offsetof(tp, member)
205 #else
206  #define STRUCT_OFFSET(tp, member) \
207    ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
208 #endif
209 #define SUBTYPE_P(p, subtype, basemember) \
210   ((void*) (((char*)(p)) - STRUCT_OFFSET(subtype, basemember)))
211 #define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
212 #define TO_BASE_CONN(c) (&((c)->base_))
213 static struct rs_connection *TO_GENERIC_CONN (struct rs_conn_base *);
214 static struct rs_listener *TO_LISTENER_CONN (struct rs_conn_base *);
215 static INLINE struct rs_connection *TO_GENERIC_CONN (struct rs_conn_base *b)
216 {
217   assert (b->magic == RS_CONN_MAGIC_GENERIC);
218   return DOWNCAST (struct rs_connection, b);
219 }
220 static INLINE struct rs_listener *TO_LISTENER_CONN (struct rs_conn_base *b)
221 {
222   assert (b->magic == RS_CONN_MAGIC_LISTENER);
223   return DOWNCAST (struct rs_listener, b);
224 }
225
226 #endif /* _RADSEC_RADSEC_IMPL_H_ */
227
228 /* Local Variables: */
229 /* c-file-style: "stroustrup" */
230 /* End: */