1 /*
2  * Copyright (c) 2008
3  *      Matt Harris.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      "This product includes software developed by Matt Harris."
16  * 4. Neither the name of the Mr. Harris nor the names of his contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  * 5. Any modifications and/or variations in the end-product which you are
20  *    distributing from the original source code are clearly noted in
21  *    the standard end-user documentation distributed with any package
22  *    containing this software in either source or binary form, as well
23  *    as on any internet sites or media on which this software is included.
24  *
25  * THIS SOFTWARE IS PROVIDED BY Mr. Harris AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL Mr. Harris OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  */
38 
39 #ifndef INCLUDED_MSOCKET_H
40 # define INCLUDED_MSOCKET_H		1
41 
42 /*
43 **
44 ** DEFINES
45 **
46 */
47 
48 # define LMS_VERSION			"0.5"
49 # define LMS_VERSION_INT		0x000005
50 
51 # define LMS_LEN_V4ADDR			16
52 # define LMS_LEN_V6ADDR			0
53 
54 # define LMS_CONNTIMEOUT		60
55 
56 # define LMSTYPE_ERROR			0
57 # define LMSTYPE_LOCALLISTEN		1
58 # define LMSTYPE_LOCALCLIENT		2
59 # define LMSTYPE_STREAM4		3
60 # define LMSTYPE_DGRAM4			4
61 # define LMSTYPE_LISTEN4		5
62 # define LMSTYPE_STREAM6		6
63 # define LMSTYPE_DGRAM6			7
64 # define LMSTYPE_LISTEN6		8
65 
66 # define LMSFLG_CONNECTED		0x00001		/* Socket is connected */
67 # define LMSFLG_LISTEN			0x00002		/* Socket is listening */
68 # define LMSFLG_READY			0x00004		/* Datagram socket is ready */
69 # define LMSFLG_WAITDNS			0x00008		/* Waiting for a DNS response */
70 # define LMSFLG_WAITIDENT		0x00010		/* Waiting for an ident response */
71 # define LMSFLG_MUXACTIVE		0x00020		/* Socket is in the mux */
72 # define LMSFLG_SSL			0x00040		/* SSL connection */
73 # define LMSFLG_SSLHDSHK		0x00080		/* SSL handshake phase */
74 # define LMSFLG_SSLRDY			0x00100		/* SSL is ready */
75 # define LMSFLG_WAITDESTROY		0x00200		/* Socket is dead, but we are waiting for DNS and/or ident queries to return before destroying it */
76 # define LMSFLG_INBOUND			0x01000		/* Inbound connection via accept() */
77 # define LMSFLG_OUTBOUND		0x02000		/* Outbound connection via connect() */
78 # define LMSFLG_WAITCONN		0x04000		/* Not yet connected */
79 
80 # define LMSOPTION_TRANSIENT		0x002		/* Doesn't do anything */
81 # define LMSOPTION_BLOCK		0x004		/* A blocking socket (default is to set nonblocking mode */
82 # define LMSOPTION_CWAIT		0x008		/* Blocks during connect() or whatever else, then sets nonblocking mode */
83 # define LMSOPTION_SSL			0x010		/* Uses SSL - self-explanatory */
84 # define LMSOPTION_UCREP		0x020		/* For an SSL socket, this sets some additional OpenSSL options for an "unclean" remote end-point which may require bug-adaptability */
85 # define LMSOPTION_ALLOWIDLE		0x040		/* Allow a socket to idle */
86 
87 # define LMS_MAXDNSCACHE		30000
88 
89 # if !defined(LMS_MAXDNSCACHE) || (LMS_MAXDNSCACHE <= 0)
90 #  define LMS_NODNSCACHE
91 # endif
92 # ifdef LMS_NODNSCACHE
93 #  define LMS_MAXDNSCACHE		0
94 # endif
95 
96 # define LMS_DNS_TYPE_NONE		0
97 # define LMS_DNS_TYPE_A			1
98 # define LMS_DNS_TYPE_CNAME		2
99 # define LMS_DNS_TYPE_PTR		3
100 # define LMS_DNS_TYPE_TXT		4
101 # define LMS_DNS_TYPE_MX		5
102 
103 # define ABSTRACT_NOTHING		0
104 # define ABSTRACT_STRING		1
105 # define ABSTRACT_MSOCKET		2
106 # define ABSTRACT_DNSREQUEST		9
107 # define ABSTRACT_CALLBACK		10
108 # define ABSTRACT_MAX			10240
109 
110 /*
111 **
112 ** STRUCTURES
113 **
114 */
115 
116 /*
117  * A totally abstract thing, which can be any type of thing stored in the abstract thing...
118  * along with a handy variable to tell you what type of thing is pointed to by the
119  * pointer stored in the abstract thing.
120  */
121 struct _abstract
122 {
123 	unsigned short what;
124 	void *where;
125 	/* abstract_callback *how; */
126 	void (*how)(struct _abstract *);
127 };
128 typedef struct _abstract Abstract;
129 
130 typedef void (*abstract_callback)(struct _abstract *);
131 
132 /*
133  * MSocket is the structure utilized by our socket abstraction layer
134  */
135 struct _MSocket
136 {
137 	unsigned short type;			/* type (MSTYPE_*) */
138 	unsigned int opts;			/* options for the socket (MSOPTION_*) */
139 
140 	char *localhost;			/* local address if INET/INET6 or path to file if UNIX */
141 	int localport;				/* local port if INET/INET6 */
142 	char *remotehost;			/* remote address if INET/INET6 */
143 	int remoteport;				/* remote port if INET/INET6 */
144 	char *remotedns;			/* DNS name of the remote host if INET/INET6 */
145 	struct in_addr *addr;			/* in_addr structure for evdns and throttling API */
146 
147 	int fd;					/* file descriptor */
148 	unsigned long flags;			/* flags on the socket/connection/etc (MSFLAG_*) */
149 
150 	size_t sendQ_sz;			/* allocated size of current sendQ */
151 	size_t sendQ_len;			/* length of current sendQ */
152 	unsigned char *sendQ;			/* queue of data to be written */
153 	time_t last_send;			/* the time at which I last sent data */
154 	size_t bytes_s;				/* bytes sent via this connection */
155 
156 	size_t recvQ_sz;			/* allocated size of current recvQ */
157 	size_t recvQ_len;			/* length of current recvQ */
158 	unsigned char *recvQ;			/* queue of data to be parsed */
159 	time_t last_recv;			/* the time at which I last received data */
160 	size_t bytes_r;				/* bytes received via this connection */
161 
162 	time_t conn_start;			/* when we started a connect() */
163 	unsigned int conn_to;			/* time before we should give up on a connect() */
164 
165 	int (*func_r)(struct _MSocket *);	/* function to call when mux says read */
166 	int (*func_w)(struct _MSocket *);	/* function to call when mux says write */
167 	int (*func_e)(struct _MSocket *);	/* function to call when mux cries foul */
168 	void (*func_p)(struct _MSocket *);	/* function to call when data is available in recvQ */
169 	void (*func_a)(struct _MSocket *);	/* function to call when a new socket has been accepted on a listener */
170 
171 	void *appdata;				/* abstract application data */
172 
173 	/* DNS (temp) crap down here... */
174 	char *possible_revdns;			/* possible reverse dns, but not yet confirmed */
175 	unsigned short retries;			/* retry attempts for the reverse DNS lookup */
176 };
177 typedef struct _MSocket MSocket;
178 
179 /*
180  * Password data storage structure used by utils_passwords_*multi()
181  */
182 struct _lms_passwords_data
183 {
184 	unsigned char version;
185 
186 	unsigned char salt[8];
187 	char salt_b64[17];
188 	unsigned char hash[32];
189 	char hash_b64[65];
190 };
191 typedef struct _lms_passwords_data lms_passwords_data;
192 
193 /*
194  * Structure for keeping track of throttled IP addresses to prevent brute-force authentication attacks
195  */
196 struct _lms_throttle_data
197 {
198 	char ipaddr[16];
199 	in_addr_t addr;
200 
201 	time_t last_bad;
202 	unsigned int offenses;
203 
204 	struct _lms_throttle_data *prev;
205 	struct _lms_throttle_data *next;
206 };
207 typedef struct _lms_throttle_data lms_throttle_data;
208 
209 /*
210 **
211 ** FUNCTIONS
212 **
213 */
214 
215 /* rand.c */
216 extern int lms_rand_get(size_t bytes, unsigned char *dst);
217 
218 /* conn.c */
219 extern unsigned int lms_throttle_check(in_addr_t ip);
220 extern int lms_throttle_expire(void);
221 extern lms_throttle_data *lms_throttle_setbad(MSocket *m);
222 extern void lms_throttle_remove(lms_throttle_data *throttle);
223 
224 /* lms.c */
225 extern int lms_init(unsigned char print);
226 extern int lms_loop(void);
227 extern int lms_version_int(void);
228 extern char *lms_version(void);
229 
230 /* socket.c */
231 extern void lms_socket_insertfd(MSocket *m);
232 extern inline MSocket *lms_socket_findbyfd(int fd);
233 extern MSocket *lms_socket_create(int type);
234 extern int lms_socket_close(MSocket *ptr);
235 extern int lms_socket_destroy(MSocket *ptr);
236 extern unsigned int lms_socket_destroytype(unsigned short type, short killad);
237 extern unsigned int lms_socket_housekeeping(void);
238 extern int lms_socket_ilisten(MSocket *s);
239 extern int lms_socket_iaccept(MSocket *s, MSocket *new);
240 extern int lms_socket_uaccept(MSocket *s, MSocket *new);
241 extern int lms_socket_iconn(MSocket *s);
242 extern int lms_socket_idgram(MSocket *s);
243 extern int lms_socket_appendq(MSocket *m, unsigned char *data, size_t data_len);
244 extern int lms_socket_clearsq(MSocket *m, ssize_t len);
245 extern int lms_socket_freerq(MSocket *m);
246 
247 /* dns.c */
248 extern void lms_dns_cleancache(void);
249 extern int lms_dns_lookup(const char *h, Abstract *a);
250 extern int lms_dns_findrev(MSocket *m);
251 extern int lms_dns_getip(const char *host, char *buf, size_t buf_len);
252 extern int lms_dns_gethost(const char *ip, char *buf, size_t buf_len);
253 
254 /* mux.c */
255 extern int lms_mux_addfd(MSocket *ms, int fd, unsigned short t);
256 extern int lms_mux_remfd(int fd);
257 extern void lms_mux_setprio(MSocket *s, short prio);
258 
259 /* ssl.c */
260 extern int lms_ssl_startsock(MSocket *m);
261 extern int lms_ssl_closesock(MSocket *m);
262 extern int lms_ssl_stopsock(MSocket *m);
263 extern int lms_ssl_unclean(MSocket *m);
264 extern char *lms_ssl_getclientinfo(MSocket *m);
265 
266 /*
267 **
268 ** MACROS
269 **
270 */
271 
272 /* These macros set various flags on a socket */
273 # define LMS_SetTimeout(s, t)		((s)->conn_to = (t))
274 # define LMS_SetBlocking(s)		((s)->opts |= LMSOPTION_BLOCK)
275 # define LMS_SetAllowIdle(s)		((s)->opts |= LMSOPTION_ALLOWIDLE)
276 # define LMS_SetCWait(s)		((s)->opts |= LMSOPTION_CWAIT)
277 # define LMS_SetSSL(s)			((s)->opts |= LMSOPTION_SSL)
278 # define LMS_SetSSLUnClean(s)		((s)->opts |= LMSOPTION_UCREP)
279 
280 /* These macros evaluate as true if the circumstance described is true */
281 # define LMS_IsConnected(s)		((s)->flags & LMSFLG_CONNECTED)
282 # define LMS_IsWaiting(s)		(((s)->flags & LMSFLG_WAITCONN) || ((s)->flags & LMSFLG_WAITDNS) || ((s)->flags & LMSFLG_WAITIDENT))
283 
284 /* The following macro sends out the contents of the sockets sendQ */
285 # define LMS_SendQueue(s)		(s)->func_w((s))
286 
287 #endif /* INCLUDED_MSOCKET_H */
288