1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  *                    Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 #ifndef INCL_SX_H
22 #define INCL_SX_H
23 
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 
28 #include "ac-stdint.h"
29 
30 #include <expat.h>
31 #include <util/util.h>
32 
33 /* jabberd2 Windows DLL */
34 #ifndef JABBERD2_API
35 # ifdef _WIN32
36 #  ifdef JABBERD2_EXPORTS
37 #   define JABBERD2_API  __declspec(dllexport)
38 #  else /* JABBERD2_EXPORTS */
39 #   define JABBERD2_API  __declspec(dllimport)
40 #  endif /* JABBERD2_EXPORTS */
41 # else /* _WIN32 */
42 #  define JABBERD2_API extern
43 # endif /* _WIN32 */
44 #endif /* JABBERD2_API */
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /* forward declarations */
51 typedef struct _sx_st           *sx_t;
52 typedef struct _sx_env_st       *sx_env_t;
53 typedef struct _sx_plugin_st    *sx_plugin_t;
54 
55 /** things that can happen */
56 typedef enum {
57     event_WANT_READ,        /* we want read actions */
58     event_WANT_WRITE,       /* we want write actions */
59     event_READ,             /* read some stuff for me */
60     event_WRITE,            /* write this to the fd */
61     event_STREAM,           /* stream is ready to go */
62     event_OPEN,             /* normal operation */
63     event_PACKET,           /* got a packet */
64     event_CLOSED,           /* its over */
65     event_ERROR             /* something's wrong */
66 } sx_event_t;
67 
68 /** connection states */
69 typedef enum {
70     state_NONE,             /* pre-init */
71     state_STREAM_RECEIVED,  /* stream start received (server) */
72     state_STREAM_SENT,      /* stream start sent (client) */
73     state_STREAM,           /* stream established */
74     state_OPEN,             /* auth completed (normal stream operation) */
75     state_CLOSING,          /* ready to close (send event_CLOSED to app) */
76     state_CLOSED            /* closed (same as NONE, but can't be used any more) */
77 } _sx_state_t;
78 
79 /** connection types */
80 typedef enum {
81     type_NONE,
82     type_CLIENT,            /* we initiated the connection */
83     type_SERVER             /* they initiated */
84 } _sx_type_t;
85 
86 /** event callback */
87 typedef int (*sx_callback_t)(sx_t s, sx_event_t e, void *data, void *arg);
88 
89 /** plugin init */
90 typedef int (*sx_plugin_init_t)(sx_env_t env, sx_plugin_t p, va_list args);
91 
92 /* errors */
93 #define SX_SUCCESS          (0x00)
94 #define SX_ERR_STREAM       (0x01)
95 #define SX_ERR_AUTH         (0x02)
96 #define SX_ERR_XML_PARSE    (0x03)
97 
98 /** error info for event_ERROR */
99 typedef struct _sx_error_st {
100     int                     code;
101     const char              *generic;
102     const char              *specific;
103 } sx_error_t;
104 
105 /** helper macro to populate this struct */
106 #define _sx_gen_error(e,c,g,s)  do { e.code = c; e.generic = g; e.specific = s; } while(0);
107 
108 /** prototype for the write notify function */
109 typedef void (*_sx_notify_t)(sx_t s, void *arg);
110 
111 /** utility: buffer */
112 typedef struct _sx_buf_st *sx_buf_t;
113 struct _sx_buf_st {
114     char           *data;     /* pointer to buffer's data */
115     unsigned int   len;       /* length of buffer's data */
116     char           *heap;     /* beginning of malloc() block containing data, if non-NULL */
117 
118     /* function to call when this buffer gets written */
119     _sx_notify_t            notify;
120     void                    *notify_arg;
121 };
122 
123 /* stream errors */
124 #define stream_err_BAD_FORMAT               (0)
125 #define stream_err_BAD_NAMESPACE_PREFIX     (1)
126 #define stream_err_CONFLICT                 (2)
127 #define stream_err_CONNECTION_TIMEOUT       (3)
128 #define stream_err_HOST_GONE                (4)
129 #define stream_err_HOST_UNKNOWN             (5)
130 #define stream_err_IMPROPER_ADDRESSING      (6)
131 #define stream_err_INTERNAL_SERVER_ERROR    (7)
132 #define stream_err_INVALID_FROM             (8)
133 #define stream_err_INVALID_ID               (9)
134 #define stream_err_INVALID_NAMESPACE        (10)
135 #define stream_err_INVALID_XML              (11)
136 #define stream_err_NOT_AUTHORIZED           (12)
137 #define stream_err_POLICY_VIOLATION         (13)
138 #define stream_err_REMOTE_CONNECTION_FAILED (14)
139 #define stream_err_RESTRICTED_XML           (15)
140 #define stream_err_RESOURCE_CONSTRAINT      (16)
141 #define stream_err_SEE_OTHER_HOST           (17)
142 #define stream_err_SYSTEM_SHUTDOWN          (18)
143 #define stream_err_UNDEFINED_CONDITION      (19)
144 #define stream_err_UNSUPPORTED_ENCODING     (20)
145 #define stream_err_UNSUPPORTED_STANZA_TYPE  (21)
146 #define stream_err_UNSUPPORTED_VERSION      (22)
147 #define stream_err_XML_NOT_WELL_FORMED      (23)
148 #define stream_err_LAST                     (24)
149 /** if you change these, reflect your changes in the table in error.c */
150 
151 /* exported functions */
152 
153 /* make/break */
154 JABBERD2_API sx_t                        sx_new(sx_env_t env, int tag, sx_callback_t cb, void *arg);
155 JABBERD2_API void                        sx_free(sx_t s);
156 
157 /* get things ready */
158 JABBERD2_API void                        sx_client_init(sx_t s, unsigned int flags, const char *ns, const char *to, const char *from, const char *version);
159 JABBERD2_API void                        sx_server_init(sx_t s, unsigned int flags);
160 
161 /* activity on socket, do stuff! (returns 1 if more read/write actions wanted, 0 otherwise) */
162 JABBERD2_API int                         sx_can_read(sx_t s);
163 JABBERD2_API int                         sx_can_write(sx_t s);
164 
165 /** sending a nad */
166 JABBERD2_API void                        sx_nad_write_elem(sx_t s, nad_t nad, int elem);
167 #define sx_nad_write(s,nad) sx_nad_write_elem(s, nad, 0)
168 
169 /** sending raw data */
170 JABBERD2_API void                        sx_raw_write(sx_t s, const char *buf, int len);
171 
172 /** authenticate the stream and move to the auth'd state */
173 JABBERD2_API void                        sx_auth(sx_t s, const char *auth_method, const char *auth_id);
174 
175 /* make/break an environment */
176 JABBERD2_API sx_env_t                    sx_env_new(void);
177 JABBERD2_API void                        sx_env_free(sx_env_t env);
178 
179 /** load a plugin into the environment */
180 JABBERD2_API sx_plugin_t                 sx_env_plugin(sx_env_t env, sx_plugin_init_t init, ...);
181 
182 /* send errors and close stuff */
183 JABBERD2_API void                        sx_error(sx_t s, int err, const char *text);
184 JABBERD2_API void                        sx_error_extended(sx_t s, int err, const char *content);
185 JABBERD2_API void                        sx_close(sx_t s);
186 JABBERD2_API void                        sx_kill(sx_t s);
187 
188 
189 /* helper functions */
190 JABBERD2_API char*                       _sx_flags(sx_t s);
191 
192 /* primary expat callbacks */
193 JABBERD2_API void                        _sx_element_start(void *arg, const char *name, const char **atts);
194 JABBERD2_API void                        _sx_element_end(void *arg, const char *name);
195 JABBERD2_API void                        _sx_cdata(void *arg, const char *str, int len);
196 JABBERD2_API void                        _sx_namespace_start(void *arg, const char *prefix, const char *uri);
197 #ifdef HAVE_XML_STOPPARSER
198 JABBERD2_API void                        _sx_entity_declaration(void *arg, const char *entityName,
199                                                                 int is_parameter_entity, const char *value,
200                                                                 int value_length, const char *base,
201                                                                 const char *systemId, const char *publicId,
202                                                                 const char *notationName);
203 #endif
204 
205 /** processor for incoming wire data */
206 JABBERD2_API void                        _sx_process_read(sx_t s, sx_buf_t buf);
207 
208 /** main nad processor */
209 JABBERD2_API void                        _sx_nad_process(sx_t s, nad_t nad);
210 
211 /* chain management */
212 JABBERD2_API void                        _sx_chain_io_plugin(sx_t s, sx_plugin_t p);
213 JABBERD2_API void                        _sx_chain_nad_plugin(sx_t s, sx_plugin_t p);
214 
215 /* chain running */
216 JABBERD2_API int                         _sx_chain_io_write(sx_t s, sx_buf_t buf);
217 JABBERD2_API int                         _sx_chain_io_read(sx_t s, sx_buf_t buf);
218 
219 JABBERD2_API int                         _sx_chain_nad_write(sx_t s, nad_t nad, int elem);
220 JABBERD2_API int                         _sx_chain_nad_read(sx_t s, nad_t nad);
221 
222 /* buffer utilities */
223 JABBERD2_API sx_buf_t                     _sx_buffer_new(const char *data, int len, _sx_notify_t notify, void *notify_arg);
224 JABBERD2_API void                        _sx_buffer_free(sx_buf_t buf);
225 JABBERD2_API void                        _sx_buffer_clear(sx_buf_t buf);
226 JABBERD2_API void                        _sx_buffer_alloc_margin(sx_buf_t buf, int before, int after);
227 JABBERD2_API void                        _sx_buffer_set(sx_buf_t buf, char *newdata, int newlength, char *newheap);
228 
229 /** sending a nad (internal) */
230 JABBERD2_API int                         _sx_nad_write(sx_t s, nad_t nad, int elem);
231 
232 /** sending raw data (internal) */
233 JABBERD2_API void                        sx_raw_write(sx_t s, const char *buf, int len);
234 
235 /** reset stream state without informing the app */
236 JABBERD2_API void                        _sx_reset(sx_t s);
237 
238 /* send errors and close stuff */
239 JABBERD2_API void                        _sx_error(sx_t s, int err, const char *text);
240 JABBERD2_API void                        _sx_error_extended(sx_t s, int err, const char *content);
241 JABBERD2_API void                        _sx_close(sx_t s);
242 
243 /** read/write plugin chain */
244 typedef struct _sx_chain_st *_sx_chain_t;
245 struct _sx_chain_st {
246     sx_plugin_t              p;
247 
248     _sx_chain_t              wnext;          /* -> write */
249     _sx_chain_t              rnext;          /* <- read */
250 };
251 
252 /** holds the state for a single stream */
253 struct _sx_st {
254     /* environment */
255     sx_env_t                 env;
256 
257     /* tag, for logging */
258     int                      tag;
259 
260     /* IP address of the connection */
261     /* pointing to sess.ip and owned by sess structure */
262     const char              *ip;
263 
264     /* TCP port of the connection */
265     /* pointing to sess.port and owned by sess structure */
266     int                     port;
267 
268     /* callback */
269     sx_callback_t            cb;
270     void                    *cb_arg;
271 
272     /* type */
273     _sx_type_t               type;
274 
275     /* flags */
276     unsigned int             flags;
277 
278     /* application namespace */
279     const char              *ns;
280 
281     /* requested stream properties */
282     const char              *req_to;
283     const char              *req_from;
284     const char              *req_version;
285 
286     /* responded stream properties */
287     const char              *res_to;
288     const char              *res_from;
289     const char              *res_version;
290 
291     /* stream id */
292     const char              *id;
293 
294     /* io chain */
295     _sx_chain_t              wio, rio;
296 
297     /* nad chain */
298     _sx_chain_t              wnad, rnad;
299 
300     /* internal queues */
301     jqueue_t                 wbufq;              /* buffers waiting to go to wio */
302     sx_buf_t                 wbufpending;        /* buffer passed through wio but not written yet */
303     jqueue_t                 rnadq;              /* completed nads waiting to go to rnad */
304 
305     /* do we want to read or write? */
306     int                      want_read, want_write;
307 
308     /* bytes read from socket */
309     int                      rbytes;
310     /* bytes parsed by parser */
311     int                      pbytes;
312     /* total bytes processed */
313     int                      tbytes;
314 
315     /* read bytes maximum */
316     int                      rbytesmax;
317 
318     /* current state */
319     _sx_state_t              state;
320 
321     /* parser */
322     XML_Parser               expat;
323     int                      depth;
324     int                      fail;
325 
326     /* nad currently being built */
327     nad_t                    nad;
328 
329     /* plugin storage */
330     void                   **plugin_data;
331 
332     /* type and id of auth */
333     const char              *auth_method;
334     const char              *auth_id;
335 
336     /* if true, then we were called from the callback */
337     int                     reentry;
338 
339     /* this is true after a stream resets - applications should check this before doing per-stream init */
340     int                     has_reset;
341 
342     /* security strength factor (in sasl parlance) - roughly equivalent to key strength */
343     int                     ssf;
344 };
345 
346 /** a plugin */
347 struct _sx_plugin_st {
348     sx_env_t                env;
349 
350     int                     magic;              /* unique id so that plugins can find each other */
351 
352     int                     index;
353 
354     void                    *private;
355 
356     void                    (*new)(sx_t s, sx_plugin_t p);                          /* pre-run init */
357     void                    (*free)(sx_t s, sx_plugin_t p);                         /* conn being freed */
358 
359     void                    (*client)(sx_t s, sx_plugin_t p);                       /* client init */
360     void                    (*server)(sx_t s, sx_plugin_t p);                       /* server init */
361 
362     /* return -2 == failed (permanent), -1 == failed (temporary), 0 == handled, 1 == pass */
363     int                     (*wio)(sx_t s, sx_plugin_t p, sx_buf_t buf);            /* before being written */
364     int                     (*rio)(sx_t s, sx_plugin_t p, sx_buf_t buf);            /* after being read */
365 
366     /* return 0 == handled, 1 == pass */
367     int                     (*wnad)(sx_t s, sx_plugin_t p, nad_t nad, int elem);    /* before being written */
368     int                     (*rnad)(sx_t s, sx_plugin_t p, nad_t nad);              /* after being read */
369 
370     void                    (*header)(sx_t s, sx_plugin_t p, sx_buf_t buf);         /* before header req/res write */
371     void                    (*stream)(sx_t s, sx_plugin_t p);                       /* after-stream init */
372 
373     void                    (*features)(sx_t s, sx_plugin_t p, nad_t nad);          /* offer features */
374 
375     /* return 0 == handled, 1 == pass */
376     int                     (*process)(sx_t s, sx_plugin_t p, nad_t nad);           /* process completed nads */
377 
378     void                    (*unload)(sx_plugin_t p);                               /* plugin unloading */
379 };
380 
381 /** an environment */
382 struct _sx_env_st {
383     sx_plugin_t             *plugins;
384     int                     nplugins;
385 };
386 
387 /** debugging macros */
388 #define ZONE __FILE__,__LINE__
389 
390 /** helper functions for macros when we're debugging */
391 JABBERD2_API void        __sx_debug(const char *file, int line, const char *msgfmt, ...);
392 
393 /** helper and internal macro for firing the callback */
394 JABBERD2_API int         __sx_event(const char *file, int line, sx_t s, sx_event_t e, void *data);
395 #define _sx_event(s,e,data) __sx_event(ZONE, s, e, data)
396 
397 #ifdef SX_DEBUG
398 
399 /** print debug output */
400 #define _sx_debug if(get_debug_flag()) __sx_debug
401 
402 /** state changes with output */
403 #define _sx_state(s,st) do { _sx_debug(ZONE, "%d state change from %d to %d", s->tag, s->state, st); s->state = st; } while(0)
404 
405 #else
406 
407 /* clean and efficient versions */
408 #define _sx_debug if(0) __sx_debug
409 #define _sx_state(s,st) s->state = st
410 
411 #endif
412 
413 #ifdef __cplusplus
414 }
415 #endif
416 
417 /* now include sx envplugins datatypes */
418 #include "plugins.h"
419 
420 #endif
421