Branch data Line data Source code
1 : : /*
2 : : *****************************************************************************
3 : : *
4 : : * File: fko_message.c
5 : : *
6 : : * Purpose: Set/Get the spa message (access req/command/etc) based
7 : : * on the current spa data.
8 : : *
9 : : * Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
10 : : * Copyright (C) 2009-2014 fwknop developers and contributors. For a full
11 : : * list of contributors, see the file 'CREDITS'.
12 : : *
13 : : * License (GNU General Public License):
14 : : *
15 : : * This program is free software; you can redistribute it and/or
16 : : * modify it under the terms of the GNU General Public License
17 : : * as published by the Free Software Foundation; either version 2
18 : : * of the License, or (at your option) any later version.
19 : : *
20 : : * This program is distributed in the hope that it will be useful,
21 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 : : * GNU General Public License for more details.
24 : : *
25 : : * You should have received a copy of the GNU General Public License
26 : : * along with this program; if not, write to the Free Software
27 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 : : * USA
29 : : *
30 : : *****************************************************************************
31 : : */
32 : : #include "fko_common.h"
33 : : #include "fko_message.h"
34 : : #include "fko.h"
35 : :
36 : : static int
37 : 3950813 : have_allow_ip(const char *msg)
38 : : {
39 : 3950813 : const char *ndx = msg;
40 : : char ip_str[MAX_IPV4_STR_LEN];
41 : 3950813 : int dot_ctr = 0, char_ctr = 0;
42 : 3950813 : int res = FKO_SUCCESS;
43 : :
44 [ + + ]: 44330490 : while(*ndx != ',' && *ndx != '\0')
45 : : {
46 : 40537309 : ip_str[char_ctr] = *ndx;
47 : 40537309 : char_ctr++;
48 [ + + ]: 40537309 : if(char_ctr >= MAX_IPV4_STR_LEN)
49 : : {
50 : : res = FKO_ERROR_INVALID_ALLOW_IP;
51 : : break;
52 : : }
53 [ + + ]: 40532424 : if(*ndx == '.')
54 : : dot_ctr++;
55 [ + + ]: 29148908 : else if(isdigit(*ndx) == 0)
56 : : {
57 : : res = FKO_ERROR_INVALID_ALLOW_IP;
58 : : break;
59 : : }
60 : 40379677 : ndx++;
61 : : }
62 : :
63 [ + + ]: 3950813 : if(char_ctr < MAX_IPV4_STR_LEN)
64 : 3945928 : ip_str[char_ctr] = '\0';
65 : : else
66 : : res = FKO_ERROR_INVALID_ALLOW_IP;
67 : :
68 [ + + ]: 3950813 : if(res == FKO_SUCCESS)
69 [ + + ]: 3793181 : if (! is_valid_ipv4_addr(ip_str))
70 : 36854 : res = FKO_ERROR_INVALID_ALLOW_IP;
71 : :
72 : 3950813 : return(res);
73 : : }
74 : :
75 : : static int
76 : 6915613 : have_port(const char *msg)
77 : : {
78 : 6915613 : const char *ndx = msg;
79 : 6915613 : int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE), port_str_len = 0;
80 : :
81 [ + - ]: 6915613 : if(startlen == MAX_SPA_MESSAGE_SIZE)
82 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_PORT_MISSING);
83 : :
84 : : /* Must have at least one digit for the port number
85 : : */
86 [ + + ]: 6915613 : if(isdigit(*ndx) == 0)
87 : : return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
88 : :
89 [ + + ]: 26424457 : while(*ndx != '\0' && *ndx != ',')
90 : : {
91 : 19618013 : port_str_len++;
92 [ + + ][ + + ]: 19618013 : if((isdigit(*ndx) == 0) || (port_str_len > MAX_PORT_STR_LEN))
93 : : return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
94 : 19524409 : ndx++;
95 : : }
96 : :
97 : : return FKO_SUCCESS;
98 : : }
99 : :
100 : : /* Set the SPA message type.
101 : : */
102 : : int
103 : 5093215 : fko_set_spa_message_type(fko_ctx_t ctx, const short msg_type)
104 : : {
105 : : #if HAVE_LIBFIU
106 [ + + ]: 5093215 : fiu_return_on("fko_set_spa_message_type_init",
107 : : FKO_ERROR_CTX_NOT_INITIALIZED);
108 : : #endif
109 : : /* Must be initialized
110 : : */
111 [ + + ][ + - ]: 5093212 : if(!CTX_INITIALIZED(ctx))
112 : : return FKO_ERROR_CTX_NOT_INITIALIZED;
113 : :
114 : : #if HAVE_LIBFIU
115 [ + + ]: 5092378 : fiu_return_on("fko_set_spa_message_type_val",
116 : : FKO_ERROR_INVALID_DATA_MESSAGE_TYPE_VALIDFAIL);
117 : : #endif
118 [ + + ]: 5092375 : if(msg_type < 0 || msg_type >= FKO_LAST_MSG_TYPE)
119 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_TYPE_VALIDFAIL);
120 : :
121 : 5088078 : ctx->message_type = msg_type;
122 : :
123 : 5088078 : ctx->state |= FKO_SPA_MSG_TYPE_MODIFIED;
124 : :
125 : 5088078 : return(FKO_SUCCESS);
126 : : }
127 : :
128 : : /* Return the SPA message type.
129 : : */
130 : : int
131 : 6370 : fko_get_spa_message_type(fko_ctx_t ctx, short *msg_type)
132 : : {
133 : :
134 : : #if HAVE_LIBFIU
135 [ + + ]: 6370 : fiu_return_on("fko_get_spa_message_type_init",
136 : : FKO_ERROR_CTX_NOT_INITIALIZED);
137 : : #endif
138 : :
139 : : /* Must be initialized
140 : : */
141 [ + + ][ + - ]: 6368 : if(!CTX_INITIALIZED(ctx))
142 : : return FKO_ERROR_CTX_NOT_INITIALIZED;
143 : :
144 [ + + ]: 5800 : if(msg_type == NULL)
145 : : return(FKO_ERROR_INVALID_DATA);
146 : :
147 : : #if HAVE_LIBFIU
148 [ + + ]: 5732 : fiu_return_on("fko_get_spa_message_type_val", FKO_ERROR_INVALID_DATA);
149 : : #endif
150 : :
151 : 5730 : *msg_type = ctx->message_type;
152 : :
153 : 5730 : return(FKO_SUCCESS);
154 : : }
155 : :
156 : : /* Set the SPA MESSAGE data
157 : : */
158 : : int
159 : 1615666 : fko_set_spa_message(fko_ctx_t ctx, const char * const msg)
160 : : {
161 : 1615666 : int res = FKO_ERROR_UNKNOWN;
162 : :
163 : : /* Context must be initialized.
164 : : */
165 [ + + ][ + - ]: 1615666 : if(!CTX_INITIALIZED(ctx))
166 : : return FKO_ERROR_CTX_NOT_INITIALIZED;
167 : :
168 : : /* Gotta have a valid string.
169 : : */
170 [ + + ][ + + ]: 1615652 : if(msg == NULL || strnlen(msg, MAX_SPA_MESSAGE_SIZE) == 0)
171 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_EMPTY);
172 : :
173 : : /* --DSS XXX: Bail out for now. But consider just
174 : : * truncating in the future...
175 : : */
176 [ + + ]: 1615464 : if(strnlen(msg, MAX_SPA_MESSAGE_SIZE) == MAX_SPA_MESSAGE_SIZE)
177 : : return(FKO_ERROR_DATA_TOO_LARGE);
178 : :
179 : : /* Basic message type and format checking...
180 : : */
181 [ + + ]: 1614699 : if(ctx->message_type == FKO_COMMAND_MSG)
182 : 1795 : res = validate_cmd_msg(msg);
183 : : else
184 : 1612904 : res = validate_access_msg(msg);
185 : :
186 [ + + ]: 1614699 : if(res != FKO_SUCCESS)
187 : : return(res);
188 : :
189 : : /* Just in case this is a subsquent call to this function. We
190 : : * do not want to be leaking memory.
191 : : */
192 [ + + ]: 1607982 : if(ctx->message != NULL)
193 : 1008 : free(ctx->message);
194 : :
195 : 1607982 : ctx->message = strdup(msg);
196 : :
197 : 1607982 : ctx->state |= FKO_DATA_MODIFIED;
198 : :
199 [ + - ]: 1607982 : if(ctx->message == NULL)
200 : : return(FKO_ERROR_MEMORY_ALLOCATION);
201 : :
202 : 1607982 : return(FKO_SUCCESS);
203 : : }
204 : :
205 : : /* Return the SPA message data.
206 : : */
207 : : int
208 : 1591331 : fko_get_spa_message(fko_ctx_t ctx, char **msg)
209 : : {
210 : :
211 : : #if HAVE_LIBFIU
212 [ + + ]: 1591331 : fiu_return_on("fko_get_spa_message_init", FKO_ERROR_CTX_NOT_INITIALIZED);
213 : : #endif
214 : :
215 : : /* Must be initialized
216 : : */
217 [ + + ][ + - ]: 1591329 : if(!CTX_INITIALIZED(ctx))
218 : : return(FKO_ERROR_CTX_NOT_INITIALIZED);
219 : :
220 [ + + ]: 1591177 : if(msg == NULL)
221 : : return(FKO_ERROR_INVALID_DATA);
222 : :
223 : : #if HAVE_LIBFIU
224 [ + + ]: 1591109 : fiu_return_on("fko_get_spa_message_val", FKO_ERROR_INVALID_DATA);
225 : : #endif
226 : :
227 : 1591107 : *msg = ctx->message;
228 : :
229 : 1591107 : return(FKO_SUCCESS);
230 : : }
231 : :
232 : : /* Validate a command message format.
233 : : */
234 : : int
235 : 44850 : validate_cmd_msg(const char *msg)
236 : : {
237 : : const char *ndx;
238 : 44850 : int res = FKO_SUCCESS;
239 : 44850 : int startlen = strnlen(msg, MAX_SPA_CMD_LEN);
240 : :
241 [ + - ]: 44850 : if(startlen == MAX_SPA_CMD_LEN)
242 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_CMD_MISSING);
243 : :
244 : : /* Should always have a valid allow IP regardless of message type
245 : : */
246 [ + + ]: 44850 : if((res = have_allow_ip(msg)) != FKO_SUCCESS)
247 : : return(FKO_ERROR_INVALID_SPA_COMMAND_MSG);
248 : :
249 : : /* Commands are fairly free-form so all we can really verify is
250 : : * there is something at all. Get past the IP and comma, and make
251 : : * sure we have some string leftover...
252 : : */
253 : 30666 : ndx = strchr(msg, ',');
254 [ + + ][ + + ]: 30666 : if(ndx == NULL || (1+(ndx - msg)) >= startlen)
255 : : return(FKO_ERROR_INVALID_SPA_COMMAND_MSG);
256 : :
257 : 29271 : return(FKO_SUCCESS);
258 : : }
259 : :
260 : : int
261 : 3692756 : validate_access_msg(const char *msg)
262 : : {
263 : : const char *ndx;
264 : 3692756 : int res = FKO_SUCCESS;
265 : 3692756 : int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE);
266 : :
267 [ + - ]: 3692756 : if(startlen == MAX_SPA_MESSAGE_SIZE)
268 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_ACCESS_MISSING);
269 : :
270 : : /* Should always have a valid allow IP regardless of message type
271 : : */
272 [ + + ]: 3692756 : if((res = have_allow_ip(msg)) != FKO_SUCCESS)
273 : : return(res);
274 : :
275 : : /* Position ourselves beyond the allow IP and make sure we are
276 : : * still good.
277 : : */
278 : 3574577 : ndx = strchr(msg, ',');
279 [ + + ][ + + ]: 3574577 : if(ndx == NULL || (1+(ndx - msg)) >= startlen)
280 : : return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
281 : :
282 : : /* Look for a comma to see if this is a multi-part access request.
283 : : */
284 : : do {
285 : 6783034 : ndx++;
286 : 6783034 : res = validate_proto_port_spec(ndx);
287 [ + + ]: 6783034 : if(res != FKO_SUCCESS)
288 : : break;
289 [ + + ]: 6698087 : } while((ndx = strchr(ndx, ',')));
290 : :
291 : : return(res);
292 : : }
293 : :
294 : : int
295 : 213207 : validate_nat_access_msg(const char *msg)
296 : : {
297 : : const char *ndx;
298 : 213207 : int res = FKO_SUCCESS;
299 : 213207 : int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE);
300 : :
301 [ + - ]: 213207 : if(startlen == MAX_SPA_MESSAGE_SIZE)
302 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_NAT_MISSING);
303 : :
304 : : /* Should always have a valid allow IP regardless of message type
305 : : */
306 [ + + ]: 213207 : if((res = have_allow_ip(msg)) != FKO_SUCCESS)
307 : : return(FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG);
308 : :
309 : : /* Position ourselves beyond the allow IP and make sure we have
310 : : * a single port value
311 : : */
312 : 151084 : ndx = strchr(msg, ',');
313 [ + + ][ + + ]: 151084 : if(ndx == NULL || (1+(ndx - msg)) >= startlen)
314 : : return(FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG);
315 : :
316 : 147295 : ndx++;
317 : :
318 [ + + ]: 147295 : if((res = have_port(ndx)) != FKO_SUCCESS)
319 : : return(FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG);
320 : :
321 [ + + ]: 108357 : if(msg[startlen-1] == ',')
322 : : return(FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG);
323 : :
324 : 107973 : return(res);
325 : : }
326 : :
327 : : int
328 : 6783034 : validate_proto_port_spec(const char *msg)
329 : : {
330 : 6783034 : int startlen = strnlen(msg, MAX_SPA_MESSAGE_SIZE);
331 : 6783034 : const char *ndx = msg;
332 : :
333 [ + - ]: 6783034 : if(startlen == MAX_SPA_MESSAGE_SIZE)
334 : : return(FKO_ERROR_INVALID_DATA_MESSAGE_PORTPROTO_MISSING);
335 : :
336 : : /* Now check for proto/port string.
337 : : */
338 [ + + ]: 6783034 : if(strncmp(ndx, "tcp", 3)
339 [ + + ]: 2690121 : && strncmp(ndx, "udp", 3)
340 [ + + ]: 12380 : && strncmp(ndx, "icmp", 4)
341 [ + + ]: 11530 : && strncmp(ndx, "none", 4))
342 : : return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
343 : :
344 : 6771505 : ndx = strchr(ndx, '/');
345 [ + + ][ + + ]: 6771505 : if(ndx == NULL || ((1+(ndx - msg)) > MAX_PROTO_STR_LEN))
346 : : return(FKO_ERROR_INVALID_SPA_ACCESS_MSG);
347 : :
348 : : /* Skip over the '/' and make sure we only have digits.
349 : : */
350 : 6768318 : ndx++;
351 : :
352 : 6768318 : return have_port(ndx);
353 : : }
354 : :
355 : : /***EOF***/
|