Branch data Line data Source code
1 : : /**
2 : : * \file server/incoming_spa.c
3 : : *
4 : : * \brief Process an incoming SPA data packet for fwknopd.
5 : : */
6 : :
7 : : /* Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
8 : : * Copyright (C) 2009-2015 fwknop developers and contributors. For a full
9 : : * list of contributors, see the file 'CREDITS'.
10 : : *
11 : : * License (GNU General Public License):
12 : : *
13 : : * This program is free software; you can redistribute it and/or
14 : : * modify it under the terms of the GNU General Public License
15 : : * as published by the Free Software Foundation; either version 2
16 : : * of the License, or (at your option) any later version.
17 : : *
18 : : * This program is distributed in the hope that it will be useful,
19 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : : * GNU General Public License for more details.
22 : : *
23 : : * You should have received a copy of the GNU General Public License
24 : : * along with this program; if not, write to the Free Software
25 : : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 : : * USA
27 : : *
28 : : *****************************************************************************
29 : : */
30 : : #include "fwknopd_common.h"
31 : : #include "netinet_common.h"
32 : :
33 : : #if HAVE_SYS_WAIT_H
34 : : #include <sys/wait.h>
35 : : #endif
36 : :
37 : : #include "incoming_spa.h"
38 : : #include "access.h"
39 : : #include "extcmd.h"
40 : : #include "cmd_cycle.h"
41 : : #include "log_msg.h"
42 : : #include "utils.h"
43 : : #include "fw_util.h"
44 : : #include "fwknopd_errors.h"
45 : : #include "replay_cache.h"
46 : :
47 : : #define CTX_DUMP_BUFSIZE 4096 /*!< Maximum size allocated to a FKO context dump */
48 : :
49 : : /* Validate and in some cases preprocess/reformat the SPA data. Return an
50 : : * error code value if there is any indication the data is not valid spa data.
51 : : */
52 : : static int
53 : 19072 : preprocess_spa_data(const fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt, spa_data_t *spadat)
54 : : {
55 : :
56 : 19072 : char *ndx = (char *)&(spa_pkt->packet_data);
57 : : char *xff;
58 : 19072 : int i, pkt_data_len = 0;
59 : :
60 : 19072 : pkt_data_len = spa_pkt->packet_data_len;
61 : :
62 : : /* At this point, we can reset the packet data length to 0. This is our
63 : : * indicator to the rest of the program that we do not have a current
64 : : * spa packet to process (after this one that is).
65 : : */
66 : 19072 : spa_pkt->packet_data_len = 0;
67 : :
68 : : /* These two checks are already done in process_packet(), but this is a
69 : : * defensive measure to run them again here
70 : : */
71 [ + - ]: 19072 : if(pkt_data_len < MIN_SPA_DATA_SIZE)
72 : : return(SPA_MSG_BAD_DATA);
73 : :
74 [ + - ]: 19072 : if(pkt_data_len > MAX_SPA_PACKET_LEN)
75 : : return(SPA_MSG_BAD_DATA);
76 : :
77 : : /* Ignore any SPA packets that contain the Rijndael or GnuPG prefixes
78 : : * since an attacker might have tacked them on to a previously seen
79 : : * SPA packet in an attempt to get past the replay check. And, we're
80 : : * no worse off since a legitimate SPA packet that happens to include
81 : : * a prefix after the outer one is stripped off won't decrypt properly
82 : : * anyway because libfko would not add a new one.
83 : : */
84 [ + + ]: 19072 : if(constant_runtime_cmp(ndx, B64_RIJNDAEL_SALT, B64_RIJNDAEL_SALT_STR_LEN) == 0)
85 : : return(SPA_MSG_BAD_DATA);
86 : :
87 [ + + ]: 18053 : if(pkt_data_len > MIN_GNUPG_MSG_SIZE
88 [ + + ]: 5785 : && constant_runtime_cmp(ndx, B64_GPG_PREFIX, B64_GPG_PREFIX_STR_LEN) == 0)
89 : : return(SPA_MSG_BAD_DATA);
90 : :
91 : : /* Initialize X-Forwarded-For field */
92 : 17035 : spadat->pkt_source_xff_ip[0] = '\0';
93 : :
94 : : /* Detect and parse out SPA data from an HTTP request. If the SPA data
95 : : * starts with "GET /" and the user agent starts with "Fwknop", then
96 : : * assume it is a SPA over HTTP request.
97 : : */
98 [ + + ]: 17035 : if(strncasecmp(opts->config[CONF_ENABLE_SPA_OVER_HTTP], "Y", 1) == 0
99 [ + + ]: 3 : && strncasecmp(ndx, "GET /", 5) == 0
100 [ + - ]: 2 : && strstr(ndx, "User-Agent: Fwknop") != NULL)
101 : : {
102 : : /* This looks like an HTTP request, so let's see if we are
103 : : * configured to accept such request and if so, find the SPA
104 : : * data.
105 : : */
106 : :
107 : : /* Process X-Forwarded-For header */
108 : :
109 : 2 : xff = strcasestr(ndx, "X-Forwarded-For: ");
110 : :
111 [ + + ][ + - ]: 2 : if (xff != NULL && strncasecmp(opts->config[CONF_ENABLE_X_FORWARDED_FOR], "Y", 1) == 0) {
112 : 1 : xff += 17;
113 : :
114 [ + + ]: 9 : for (i = 0; *xff != '\0'; i++)
115 [ + + ]: 8 : if (isspace(*xff))
116 : 1 : *xff = '\0';
117 : : else
118 : 7 : xff++;
119 : :
120 : 1 : xff -= i - 1;
121 : :
122 [ - + ]: 1 : if (!is_valid_ipv4_addr(xff, strlen(xff)))
123 : 0 : log_msg(LOG_WARNING,
124 : : "Error parsing X-Forwarded-For header: value '%s' is not an IP address",
125 : : xff);
126 : : else
127 : 1 : strlcpy(spadat->pkt_source_xff_ip, xff, i);
128 : : }
129 : :
130 : : /* Now extract, adjust (convert characters translated by the fwknop
131 : : * client), and reset the SPA message itself.
132 : : */
133 : 2 : strlcpy((char *)spa_pkt->packet_data, ndx+5, pkt_data_len);
134 : 2 : pkt_data_len -= 5;
135 : :
136 [ + - ]: 410 : for(i=0; i<pkt_data_len; i++)
137 : : {
138 [ + + ]: 410 : if(isspace(*ndx)) /* The first space marks the end of the req */
139 : : {
140 : 2 : *ndx = '\0';
141 : : break;
142 : : }
143 [ + + ]: 408 : else if(*ndx == '-') /* Convert '-' to '+' */
144 : 7 : *ndx = '+';
145 [ + + ]: 401 : else if(*ndx == '_') /* Convert '_' to '/' */
146 : 6 : *ndx = '/';
147 : :
148 : 408 : ndx++;
149 : : }
150 : :
151 [ + - ]: 2 : if(i < MIN_SPA_DATA_SIZE)
152 : : return(SPA_MSG_BAD_DATA);
153 : :
154 : 2 : spa_pkt->packet_data_len = pkt_data_len = i;
155 : : }
156 : :
157 : : /* Require base64-encoded data
158 : : */
159 [ + + ]: 17035 : if(! is_base64(spa_pkt->packet_data, pkt_data_len))
160 : : return(SPA_MSG_NOT_SPA_DATA);
161 : :
162 : :
163 : : /* If we made it here, we have no reason to assume this is not SPA data.
164 : : * The ultimate test will be whether the SPA data authenticates via an
165 : : * HMAC anyway.
166 : : */
167 : : return(FKO_SUCCESS);
168 : : }
169 : :
170 : : /* For replay attack detection
171 : : */
172 : : static int
173 : 16313 : get_raw_digest(char **digest, char *pkt_data)
174 : : {
175 : 16313 : fko_ctx_t ctx = NULL;
176 : 16313 : char *tmp_digest = NULL;
177 : 16313 : int res = FKO_SUCCESS;
178 : 16313 : short raw_digest_type = -1;
179 : :
180 : : /* initialize an FKO context with no decryption key just so
181 : : * we can get the outer message digest
182 : : */
183 : 16313 : res = fko_new_with_data(&ctx, (char *)pkt_data, NULL, 0,
184 : : FKO_DEFAULT_ENC_MODE, NULL, 0, 0);
185 : :
186 [ + + ]: 16313 : if(res != FKO_SUCCESS)
187 : : {
188 : 39 : log_msg(LOG_WARNING, "Error initializing FKO context from SPA data: %s",
189 : : fko_errstr(res));
190 : 39 : fko_destroy(ctx);
191 : 39 : ctx = NULL;
192 : 39 : return(SPA_MSG_FKO_CTX_ERROR);
193 : : }
194 : :
195 : 16274 : res = fko_set_raw_spa_digest_type(ctx, FKO_DEFAULT_DIGEST);
196 [ + + ]: 16274 : if(res != FKO_SUCCESS)
197 : : {
198 : 2 : log_msg(LOG_WARNING, "Error setting digest type for SPA data: %s",
199 : : fko_errstr(res));
200 : 2 : fko_destroy(ctx);
201 : 2 : ctx = NULL;
202 : 2 : return(SPA_MSG_DIGEST_ERROR);
203 : : }
204 : :
205 : 16272 : res = fko_get_raw_spa_digest_type(ctx, &raw_digest_type);
206 [ + + ]: 16272 : if(res != FKO_SUCCESS)
207 : : {
208 : 1 : log_msg(LOG_WARNING, "Error getting digest type for SPA data: %s",
209 : : fko_errstr(res));
210 : 1 : fko_destroy(ctx);
211 : 1 : ctx = NULL;
212 : 1 : return(SPA_MSG_DIGEST_ERROR);
213 : : }
214 : :
215 : : /* Make sure the digest type is what we expect
216 : : */
217 [ - + ]: 16271 : if(raw_digest_type != FKO_DEFAULT_DIGEST)
218 : : {
219 : 0 : log_msg(LOG_WARNING, "Error setting digest type for SPA data: %s",
220 : : fko_errstr(res));
221 : 0 : fko_destroy(ctx);
222 : 0 : ctx = NULL;
223 : 0 : return(SPA_MSG_DIGEST_ERROR);
224 : : }
225 : :
226 : 16271 : res = fko_set_raw_spa_digest(ctx);
227 [ + + ]: 16271 : if(res != FKO_SUCCESS)
228 : : {
229 : 46 : log_msg(LOG_WARNING, "Error setting digest for SPA data: %s",
230 : : fko_errstr(res));
231 : 46 : fko_destroy(ctx);
232 : 46 : ctx = NULL;
233 : 46 : return(SPA_MSG_DIGEST_ERROR);
234 : : }
235 : :
236 : 16225 : res = fko_get_raw_spa_digest(ctx, &tmp_digest);
237 [ + + ]: 16225 : if(res != FKO_SUCCESS)
238 : : {
239 : 1 : log_msg(LOG_WARNING, "Error getting digest from SPA data: %s",
240 : : fko_errstr(res));
241 : 1 : fko_destroy(ctx);
242 : 1 : ctx = NULL;
243 : 1 : return(SPA_MSG_DIGEST_ERROR);
244 : : }
245 : :
246 : 16224 : *digest = strdup(tmp_digest);
247 : :
248 [ - + ]: 16224 : if (*digest == NULL)
249 : 0 : res = SPA_MSG_ERROR; /* really a strdup() memory allocation problem */
250 : :
251 : 16224 : fko_destroy(ctx);
252 : 16224 : ctx = NULL;
253 : :
254 : 16224 : return res;
255 : : }
256 : :
257 : : /* Popluate a spa_data struct from an initialized (and populated) FKO context.
258 : : */
259 : : static int
260 : 1521 : get_spa_data_fields(fko_ctx_t ctx, spa_data_t *spdat)
261 : : {
262 : 1521 : int res = FKO_SUCCESS;
263 : :
264 : 1521 : res = fko_get_username(ctx, &(spdat->username));
265 [ + + ]: 1521 : if(res != FKO_SUCCESS)
266 : : return(res);
267 : :
268 : 1519 : res = fko_get_timestamp(ctx, &(spdat->timestamp));
269 [ + + ]: 1519 : if(res != FKO_SUCCESS)
270 : : return(res);
271 : :
272 : 1517 : res = fko_get_version(ctx, &(spdat->version));
273 [ + + ]: 1517 : if(res != FKO_SUCCESS)
274 : : return(res);
275 : :
276 : 1515 : res = fko_get_spa_message_type(ctx, &(spdat->message_type));
277 [ + + ]: 1515 : if(res != FKO_SUCCESS)
278 : : return(res);
279 : :
280 : 1513 : res = fko_get_spa_message(ctx, &(spdat->spa_message));
281 [ + + ]: 1513 : if(res != FKO_SUCCESS)
282 : : return(res);
283 : :
284 : 1511 : res = fko_get_spa_nat_access(ctx, &(spdat->nat_access));
285 [ + + ]: 1511 : if(res != FKO_SUCCESS)
286 : : return(res);
287 : :
288 : 1509 : res = fko_get_spa_server_auth(ctx, &(spdat->server_auth));
289 [ + + ]: 1509 : if(res != FKO_SUCCESS)
290 : : return(res);
291 : :
292 : 1507 : res = fko_get_spa_client_timeout(ctx, (int *)&(spdat->client_timeout));
293 : : if(res != FKO_SUCCESS)
294 : : return(res);
295 : :
296 : : return(res);
297 : : }
298 : :
299 : : static int
300 : 1505 : check_pkt_age(const fko_srv_options_t *opts, spa_data_t *spadat,
301 : : const int stanza_num)
302 : : {
303 : : int ts_diff;
304 : : time_t now_ts;
305 : :
306 [ + + ]: 1505 : if(strncasecmp(opts->config[CONF_ENABLE_SPA_PACKET_AGING], "Y", 1) == 0)
307 : : {
308 : 750 : time(&now_ts);
309 : :
310 : 750 : ts_diff = labs(now_ts - spadat->timestamp);
311 : :
312 [ + + ]: 750 : if(ts_diff > opts->max_spa_packet_age)
313 : : {
314 : 2 : log_msg(LOG_WARNING, "[%s] (stanza #%d) SPA data time difference is too great (%i seconds).",
315 : 2 : spadat->pkt_source_ip, stanza_num, ts_diff);
316 : : return 0;
317 : : }
318 : : }
319 : : return 1;
320 : : }
321 : :
322 : : static int
323 : 30550 : check_stanza_expiration(acc_stanza_t *acc, spa_data_t *spadat,
324 : : const int stanza_num)
325 : : {
326 [ + + ]: 15275 : if(acc->access_expire_time > 0)
327 : : {
328 [ + - ]: 3 : if(acc->expired)
329 : : {
330 : : return 0;
331 : : }
332 : : else
333 : : {
334 [ + + ]: 3 : if(time(NULL) > acc->access_expire_time)
335 : : {
336 : 2 : log_msg(LOG_INFO, "[%s] (stanza #%d) Access stanza has expired",
337 : 2 : spadat->pkt_source_ip, stanza_num);
338 : 2 : acc->expired = 1;
339 : : return 0;
340 : : }
341 : : }
342 : : }
343 : : return 1;
344 : : }
345 : :
346 : : /* Check for access.conf stanza SOURCE match based on SPA packet
347 : : * source IP
348 : : */
349 : : static int
350 : 16416 : is_src_match(acc_stanza_t *acc, const uint32_t ip)
351 : : {
352 [ + + ]: 16423 : while (acc)
353 : : {
354 [ + + ]: 16420 : if(compare_addr_list(acc->source_list, ip))
355 : : return 1;
356 : :
357 : 7 : acc = acc->next;
358 : : }
359 : : return 0;
360 : : }
361 : :
362 : : static int
363 : 16416 : src_check(fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt,
364 : : spa_data_t *spadat, char **raw_digest)
365 : : {
366 [ + + ]: 16416 : if (is_src_match(opts->acc_stanzas, ntohl(spa_pkt->packet_src_ip)))
367 : : {
368 [ + + ]: 16413 : if(strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
369 : : {
370 : : /* Check for a replay attack
371 : : */
372 [ + + ]: 16313 : if(get_raw_digest(raw_digest, (char *)spa_pkt->packet_data) != FKO_SUCCESS)
373 : : {
374 [ - + ]: 89 : if (*raw_digest != NULL)
375 : 0 : free(*raw_digest);
376 : : return 0;
377 : : }
378 [ + - ]: 16224 : if (*raw_digest == NULL)
379 : : return 0;
380 : :
381 [ + + ]: 16224 : if (is_replay(opts, *raw_digest) != SPA_MSG_SUCCESS)
382 : : {
383 : 1504 : free(*raw_digest);
384 : 1504 : return 0;
385 : : }
386 : : }
387 : : }
388 : : else
389 : : {
390 : 3 : log_msg(LOG_WARNING,
391 : 3 : "No access data found for source IP: %s", spadat->pkt_source_ip
392 : : );
393 : 3 : return 0;
394 : : }
395 : : return 1;
396 : : }
397 : :
398 : : static int
399 : 19072 : precheck_pkt(fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt,
400 : : spa_data_t *spadat, char **raw_digest)
401 : : {
402 : 19072 : int res = 0, packet_data_len = 0;
403 : :
404 : 19072 : packet_data_len = spa_pkt->packet_data_len;
405 : :
406 : 19072 : res = preprocess_spa_data(opts, spa_pkt, spadat);
407 [ + + ]: 19072 : if(res != FKO_SUCCESS)
408 : : {
409 : 2656 : log_msg(LOG_DEBUG, "[%s] preprocess_spa_data() returned error %i: '%s' for incoming packet.",
410 : 2656 : spadat->pkt_source_ip, res, get_errstr(res));
411 : 2656 : return 0;
412 : : }
413 : :
414 [ + - ][ + + ]: 16416 : if(opts->foreground == 1 && opts->verbose > 2)
415 : : {
416 : : printf("[+] candidate SPA packet payload:\n");
417 : 110 : hex_dump(spa_pkt->packet_data, packet_data_len);
418 : : }
419 : :
420 [ + + ]: 16416 : if(! src_check(opts, spa_pkt, spadat, raw_digest))
421 : : return 0;
422 : :
423 : 14820 : return 1;
424 : : }
425 : :
426 : : static int
427 : 15281 : src_dst_check(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
428 : : spa_data_t *spadat, const int stanza_num)
429 : : {
430 [ + + ][ + + ]: 15281 : if(! compare_addr_list(acc->source_list, ntohl(spa_pkt->packet_src_ip)) ||
431 : 15277 : (acc->destination_list != NULL
432 [ + + ]: 5 : && ! compare_addr_list(acc->destination_list, ntohl(spa_pkt->packet_dst_ip))))
433 : : {
434 : 6 : log_msg(LOG_DEBUG,
435 : : "(stanza #%d) SPA packet (%s -> %s) filtered by SOURCE and/or DESTINATION criteria",
436 : 6 : stanza_num, spadat->pkt_source_ip, spadat->pkt_destination_ip);
437 : : return 0;
438 : : }
439 : : return 1;
440 : : }
441 : :
442 : : /* Process command messages
443 : : */
444 : : static int
445 : 192 : process_cmd_msg(fko_srv_options_t *opts, acc_stanza_t *acc,
446 : : spa_data_t *spadat, const int stanza_num, int *res)
447 : : {
448 : 192 : int pid_status=0;
449 : 192 : char cmd_buf[MAX_SPA_CMD_LEN] = {0};
450 : :
451 [ + + ]: 192 : if(!acc->enable_cmd_exec)
452 : : {
453 : 1 : log_msg(LOG_WARNING,
454 : : "[%s] (stanza #%d) SPA Command messages are not allowed in the current configuration.",
455 : 1 : spadat->pkt_source_ip, stanza_num
456 : : );
457 : 1 : return 0;
458 : : }
459 [ + + ]: 191 : else if(opts->test)
460 : : {
461 : 171 : log_msg(LOG_WARNING,
462 : : "[%s] (stanza #%d) --test mode enabled, skipping command execution.",
463 : 171 : spadat->pkt_source_ip, stanza_num
464 : : );
465 : 171 : return 0;
466 : : }
467 : : else
468 : : {
469 : 20 : log_msg(LOG_INFO,
470 : : "[%s] (stanza #%d) Processing SPA Command message: command='%s'.",
471 : 20 : spadat->pkt_source_ip, stanza_num, spadat->spa_message_remain
472 : : );
473 : :
474 : : memset(cmd_buf, 0x0, sizeof(cmd_buf));
475 [ + + ]: 20 : if(acc->enable_cmd_sudo_exec)
476 : : {
477 : : /* Run the command via sudo - this allows sudo filtering
478 : : * to apply to the incoming command
479 : : */
480 : 9 : strlcpy(cmd_buf, opts->config[CONF_SUDO_EXE],
481 : : sizeof(cmd_buf));
482 [ + + ]: 9 : if(acc->cmd_sudo_exec_user != NULL
483 [ + - ]: 8 : && strncasecmp(acc->cmd_sudo_exec_user, "root", 4) != 0)
484 : : {
485 : 8 : strlcat(cmd_buf, " -u ", sizeof(cmd_buf));
486 : 8 : strlcat(cmd_buf, acc->cmd_sudo_exec_user, sizeof(cmd_buf));
487 : : }
488 [ + + ]: 9 : if(acc->cmd_exec_group != NULL
489 [ + - ]: 2 : && strncasecmp(acc->cmd_sudo_exec_group, "root", 4) != 0)
490 : : {
491 : 2 : strlcat(cmd_buf, " -g ", sizeof(cmd_buf));
492 : 2 : strlcat(cmd_buf,
493 : 2 : acc->cmd_sudo_exec_group, sizeof(cmd_buf));
494 : : }
495 : 9 : strlcat(cmd_buf, " ", sizeof(cmd_buf));
496 : 9 : strlcat(cmd_buf, spadat->spa_message_remain, sizeof(cmd_buf));
497 : : }
498 : : else
499 : 11 : strlcpy(cmd_buf, spadat->spa_message_remain, sizeof(cmd_buf));
500 : :
501 [ + + ]: 20 : if(acc->cmd_exec_user != NULL
502 [ + - ]: 11 : && strncasecmp(acc->cmd_exec_user, "root", 4) != 0)
503 : : {
504 [ + + ]: 11 : log_msg(LOG_INFO,
505 : : "[%s] (stanza #%d) Running command '%s' setuid/setgid user/group to %s/%s (UID=%i,GID=%i)",
506 : : spadat->pkt_source_ip, stanza_num, cmd_buf, acc->cmd_exec_user,
507 : 11 : acc->cmd_exec_group == NULL ? acc->cmd_exec_user : acc->cmd_exec_group,
508 : : acc->cmd_exec_uid, acc->cmd_exec_gid);
509 : :
510 : 11 : *res = run_extcmd_as(acc->cmd_exec_uid, acc->cmd_exec_gid,
511 : : cmd_buf, NULL, 0, WANT_STDERR, NO_TIMEOUT,
512 : : &pid_status, opts);
513 : : }
514 : : else /* Just run it as we are (root that is). */
515 : : {
516 : 9 : log_msg(LOG_INFO,
517 : : "[%s] (stanza #%d) Running command '%s'",
518 : : spadat->pkt_source_ip, stanza_num, cmd_buf);
519 : 9 : *res = run_extcmd(cmd_buf, NULL, 0, WANT_STDERR,
520 : : 5, &pid_status, opts);
521 : : }
522 : :
523 : : /* should only call WEXITSTATUS() if WIFEXITED() is true
524 : : */
525 [ + - ]: 20 : log_msg(LOG_INFO,
526 : : "[%s] (stanza #%d) CMD_EXEC: command returned %i, pid_status: %d",
527 : : spadat->pkt_source_ip, stanza_num, *res,
528 : 40 : WIFEXITED(pid_status) ? WEXITSTATUS(pid_status) : pid_status);
529 : :
530 [ + - ]: 20 : if(WIFEXITED(pid_status))
531 : : {
532 [ - + ]: 20 : if(WEXITSTATUS(pid_status) != 0)
533 : 0 : *res = SPA_MSG_COMMAND_ERROR;
534 : : }
535 : : else
536 : 0 : *res = SPA_MSG_COMMAND_ERROR;
537 : : }
538 : : return 1;
539 : : }
540 : :
541 : : static int
542 : 15272 : check_mode_ctx(spa_data_t *spadat, fko_ctx_t *ctx, int attempted_decrypt,
543 : : const int enc_type, const int stanza_num, const int res)
544 : : {
545 [ + + ]: 15272 : if(attempted_decrypt == 0)
546 : : {
547 : 9 : log_msg(LOG_ERR,
548 : : "[%s] (stanza #%d) No stanza encryption mode match for encryption type: %i.",
549 : 9 : spadat->pkt_source_ip, stanza_num, enc_type);
550 : 9 : return 0;
551 : : }
552 : :
553 : : /* Do we have a valid FKO context? Did the SPA decrypt properly?
554 : : */
555 [ + + ]: 15263 : if(res != FKO_SUCCESS)
556 : : {
557 : 13740 : log_msg(LOG_WARNING, "[%s] (stanza #%d) Error creating fko context: %s",
558 : 13740 : spadat->pkt_source_ip, stanza_num, fko_errstr(res));
559 : :
560 [ + + ]: 13740 : if(IS_GPG_ERROR(res))
561 : 14 : log_msg(LOG_WARNING, "[%s] (stanza #%d) - GPG ERROR: %s",
562 : : spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
563 : : return 0;
564 : : }
565 : :
566 : : return 1;
567 : : }
568 : :
569 : : static void
570 : 30456 : handle_rijndael_enc(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
571 : : spa_data_t *spadat, fko_ctx_t *ctx, int *attempted_decrypt,
572 : : int *cmd_exec_success, const int enc_type, const int stanza_num,
573 : : int *res)
574 : : {
575 [ + + ][ + + ]: 15228 : if(enc_type == FKO_ENCRYPTION_RIJNDAEL || acc->enable_cmd_exec)
576 : : {
577 : 15193 : *res = fko_new_with_data(ctx, (char *)spa_pkt->packet_data,
578 : 30386 : acc->key, acc->key_len, acc->encryption_mode, acc->hmac_key,
579 : : acc->hmac_key_len, acc->hmac_type);
580 : 15193 : *attempted_decrypt = 1;
581 [ + + ]: 15193 : if(*res == FKO_SUCCESS)
582 : 1467 : *cmd_exec_success = 1;
583 : : }
584 : 15228 : return;
585 : : }
586 : :
587 : : static int
588 : 15273 : handle_gpg_enc(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt,
589 : : spa_data_t *spadat, fko_ctx_t *ctx, int *attempted_decrypt,
590 : : const int cmd_exec_success, const int enc_type,
591 : : const int stanza_num, int *res)
592 : : {
593 [ + + ][ + - ]: 15273 : if(acc->use_gpg && enc_type == FKO_ENCRYPTION_GPG && cmd_exec_success == 0)
594 : : {
595 : : /* For GPG we create the new context without decrypting on the fly
596 : : * so we can set some GPG parameters first.
597 : : */
598 [ - + ][ # # ]: 71 : if(acc->gpg_decrypt_pw != NULL || acc->gpg_allow_no_pw)
599 : : {
600 : 71 : *res = fko_new_with_data(ctx, (char *)spa_pkt->packet_data, NULL,
601 : 71 : 0, FKO_ENC_MODE_ASYMMETRIC, acc->hmac_key,
602 : : acc->hmac_key_len, acc->hmac_type);
603 : :
604 [ - + ]: 71 : if(*res != FKO_SUCCESS)
605 : : {
606 : 0 : log_msg(LOG_WARNING,
607 : : "[%s] (stanza #%d) Error creating fko context (before decryption): %s",
608 : 0 : spadat->pkt_source_ip, stanza_num, fko_errstr(*res)
609 : : );
610 : 0 : return 0;
611 : : }
612 : :
613 : : /* Set whatever GPG parameters we have.
614 : : */
615 [ + + ]: 71 : if(acc->gpg_exe != NULL)
616 : : {
617 : 1 : *res = fko_set_gpg_exe(*ctx, acc->gpg_exe);
618 [ + - ]: 1 : if(*res != FKO_SUCCESS)
619 : : {
620 : 1 : log_msg(LOG_WARNING,
621 : : "[%s] (stanza #%d) Error setting GPG path %s: %s",
622 : 1 : spadat->pkt_source_ip, stanza_num, acc->gpg_exe,
623 : : fko_errstr(*res)
624 : : );
625 : 1 : return 0;
626 : : }
627 : : }
628 : :
629 [ + - ]: 70 : if(acc->gpg_home_dir != NULL)
630 : : {
631 : 70 : *res = fko_set_gpg_home_dir(*ctx, acc->gpg_home_dir);
632 [ - + ]: 70 : if(*res != FKO_SUCCESS)
633 : : {
634 : 0 : log_msg(LOG_WARNING,
635 : : "[%s] (stanza #%d) Error setting GPG keyring path to %s: %s",
636 : 0 : spadat->pkt_source_ip, stanza_num, acc->gpg_home_dir,
637 : : fko_errstr(*res)
638 : : );
639 : 0 : return 0;
640 : : }
641 : : }
642 : :
643 [ + - ]: 70 : if(acc->gpg_decrypt_id != NULL)
644 : 70 : fko_set_gpg_recipient(*ctx, acc->gpg_decrypt_id);
645 : :
646 : : /* If GPG_REQUIRE_SIG is set for this acc stanza, then set
647 : : * the FKO context accordingly and check the other GPG Sig-
648 : : * related parameters. This also applies when REMOTE_ID is
649 : : * set.
650 : : */
651 [ + + ]: 70 : if(acc->gpg_require_sig)
652 : : {
653 : 69 : fko_set_gpg_signature_verify(*ctx, 1);
654 : :
655 : : /* Set whether or not to ignore signature verification errors.
656 : : */
657 : 69 : fko_set_gpg_ignore_verify_error(*ctx, acc->gpg_ignore_sig_error);
658 : : }
659 : : else
660 : : {
661 : 1 : fko_set_gpg_signature_verify(*ctx, 0);
662 : 1 : fko_set_gpg_ignore_verify_error(*ctx, 1);
663 : : }
664 : :
665 : : /* Now decrypt the data.
666 : : */
667 : 70 : *res = fko_decrypt_spa_data(*ctx, acc->gpg_decrypt_pw, 0);
668 : 70 : *attempted_decrypt = 1;
669 : : }
670 : : }
671 : : return 1;
672 : : }
673 : :
674 : : static int
675 : 1523 : handle_gpg_sigs(acc_stanza_t *acc, spa_data_t *spadat,
676 : : fko_ctx_t *ctx, const int enc_type, const int stanza_num, int *res)
677 : : {
678 : : char *gpg_id, *gpg_fpr;
679 : : acc_string_list_t *gpg_id_ndx;
680 : : acc_string_list_t *gpg_fpr_ndx;
681 : 1523 : unsigned char is_gpg_match = 0;
682 : :
683 [ + + ][ + + ]: 1523 : if(enc_type == FKO_ENCRYPTION_GPG && acc->gpg_require_sig)
684 : : {
685 : 55 : *res = fko_get_gpg_signature_id(*ctx, &gpg_id);
686 [ - + ]: 55 : if(*res != FKO_SUCCESS)
687 : : {
688 : 0 : log_msg(LOG_WARNING,
689 : : "[%s] (stanza #%d) Error pulling the GPG signature ID from the context: %s",
690 : 0 : spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
691 : 0 : return 0;
692 : : }
693 : :
694 : 55 : *res = fko_get_gpg_signature_fpr(*ctx, &gpg_fpr);
695 [ - + ]: 55 : if(*res != FKO_SUCCESS)
696 : : {
697 : 0 : log_msg(LOG_WARNING,
698 : : "[%s] (stanza #%d) Error pulling the GPG fingerprint from the context: %s",
699 : 0 : spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
700 : 0 : return 0;
701 : : }
702 : :
703 : 55 : log_msg(LOG_INFO,
704 : : "[%s] (stanza #%d) Incoming SPA data signed by '%s' (fingerprint '%s').",
705 : 55 : spadat->pkt_source_ip, stanza_num, gpg_id, gpg_fpr);
706 : :
707 : : /* prefer GnuPG fingerprint match if so configured
708 : : */
709 [ + + ]: 55 : if(acc->gpg_remote_fpr != NULL)
710 : : {
711 : 2 : is_gpg_match = 0;
712 [ + + ]: 3 : for(gpg_fpr_ndx = acc->gpg_remote_fpr_list;
713 : 1 : gpg_fpr_ndx != NULL; gpg_fpr_ndx=gpg_fpr_ndx->next)
714 : : {
715 : 2 : *res = fko_gpg_signature_fpr_match(*ctx,
716 : 2 : gpg_fpr_ndx->str, &is_gpg_match);
717 [ - + ]: 2 : if(*res != FKO_SUCCESS)
718 : : {
719 : 0 : log_msg(LOG_WARNING,
720 : : "[%s] (stanza #%d) Error in GPG signature comparison: %s",
721 : : spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
722 : 0 : return 0;
723 : : }
724 [ + + ]: 2 : if(is_gpg_match)
725 : : break;
726 : : }
727 [ + + ]: 2 : if(! is_gpg_match)
728 : : {
729 : 1 : log_msg(LOG_WARNING,
730 : : "[%s] (stanza #%d) Incoming SPA packet signed by: %s, but that fingerprint is not in the GPG_FINGERPRINT_ID list.",
731 : : spadat->pkt_source_ip, stanza_num, gpg_fpr);
732 : 1 : return 0;
733 : : }
734 : : }
735 : :
736 [ + + ]: 54 : if(acc->gpg_remote_id != NULL)
737 : : {
738 : 53 : is_gpg_match = 0;
739 [ + + ]: 54 : for(gpg_id_ndx = acc->gpg_remote_id_list;
740 : 1 : gpg_id_ndx != NULL; gpg_id_ndx=gpg_id_ndx->next)
741 : : {
742 : 53 : *res = fko_gpg_signature_id_match(*ctx,
743 : 53 : gpg_id_ndx->str, &is_gpg_match);
744 [ - + ]: 53 : if(*res != FKO_SUCCESS)
745 : : {
746 : 0 : log_msg(LOG_WARNING,
747 : : "[%s] (stanza #%d) Error in GPG signature comparison: %s",
748 : : spadat->pkt_source_ip, stanza_num, fko_gpg_errstr(*ctx));
749 : 0 : return 0;
750 : : }
751 [ + + ]: 53 : if(is_gpg_match)
752 : : break;
753 : : }
754 : :
755 [ + + ]: 53 : if(! is_gpg_match)
756 : : {
757 : 1 : log_msg(LOG_WARNING,
758 : : "[%s] (stanza #%d) Incoming SPA packet signed by ID: %s, but that ID is not in the GPG_REMOTE_ID list.",
759 : : spadat->pkt_source_ip, stanza_num, gpg_id);
760 : 1 : return 0;
761 : : }
762 : : }
763 : : }
764 : : return 1;
765 : : }
766 : :
767 : : static int
768 : 1503 : check_src_access(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
769 : : {
770 [ + + ]: 1503 : if(strcmp(spadat->spa_message_src_ip, "0.0.0.0") == 0)
771 : : {
772 [ + + ]: 8 : if(acc->require_source_address)
773 : : {
774 : 1 : log_msg(LOG_WARNING,
775 : : "[%s] (stanza #%d) Got 0.0.0.0 when valid source IP was required.",
776 : 1 : spadat->pkt_source_ip, stanza_num
777 : : );
778 : : return 0;
779 : : }
780 : :
781 [ + + ]: 7 : if (spadat->pkt_source_xff_ip[0] != '\0')
782 : 1 : spadat->use_src_ip = spadat->pkt_source_xff_ip;
783 : : else
784 : 6 : spadat->use_src_ip = spadat->pkt_source_ip;
785 : : }
786 : : else
787 : 1495 : spadat->use_src_ip = spadat->spa_message_src_ip;
788 : :
789 : : return 1;
790 : : }
791 : :
792 : : static int
793 : 1502 : check_username(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
794 : : {
795 [ + + ]: 1502 : if(acc->require_username != NULL)
796 : : {
797 [ + + ]: 2 : if(strcmp(spadat->username, acc->require_username) != 0)
798 : : {
799 : 1 : log_msg(LOG_WARNING,
800 : : "[%s] (stanza #%d) Username in SPA data (%s) does not match required username: %s",
801 : 1 : spadat->pkt_source_ip, stanza_num, spadat->username, acc->require_username
802 : : );
803 : : return 0;
804 : : }
805 : : }
806 : : return 1;
807 : : }
808 : :
809 : : static int
810 : 1501 : check_nat_access_types(fko_srv_options_t *opts, acc_stanza_t *acc,
811 : : spa_data_t *spadat, const int stanza_num)
812 : : {
813 : 1501 : int not_enabled=0;
814 : :
815 [ + + ]: 1501 : if(spadat->message_type == FKO_NAT_ACCESS_MSG
816 : 1501 : || spadat->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG)
817 : : {
818 : : #if FIREWALL_FIREWALLD
819 [ + + ]: 161 : if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_FORWARDING], "Y", 1)!=0)
820 : 138 : not_enabled = 1;
821 : : #elif FIREWALL_IPTABLES
822 : : if(strncasecmp(opts->config[CONF_ENABLE_IPT_FORWARDING], "Y", 1)!=0)
823 : : not_enabled = 1;
824 : : #endif
825 : : }
826 [ + + ]: 1340 : else if(spadat->message_type == FKO_LOCAL_NAT_ACCESS_MSG
827 : 1340 : || spadat->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
828 : : {
829 : : #if FIREWALL_FIREWALLD
830 [ + + ]: 135 : if(strncasecmp(opts->config[CONF_ENABLE_FIREWD_LOCAL_NAT], "Y", 1)!=0)
831 : 124 : not_enabled = 1;
832 : : #elif FIREWALL_IPTABLES
833 : : if(strncasecmp(opts->config[CONF_ENABLE_IPT_LOCAL_NAT], "Y", 1)!=0)
834 : : not_enabled = 1;
835 : : #endif
836 : : }
837 : :
838 [ + + ]: 1501 : if(not_enabled)
839 : : {
840 : 262 : log_msg(LOG_WARNING,
841 : : "(stanza #%d) SPA packet from %s requested NAT access, but is not enabled/supported",
842 : 262 : stanza_num, spadat->pkt_source_ip
843 : : );
844 : : return 0;
845 : : }
846 : : return 1;
847 : : }
848 : :
849 : : static int
850 : 1523 : add_replay_cache(fko_srv_options_t *opts, acc_stanza_t *acc,
851 : : spa_data_t *spadat, char *raw_digest, int *added_replay_digest,
852 : : const int stanza_num, int *res)
853 : : {
854 [ + + ][ + + ]: 1523 : if (!opts->test && *added_replay_digest == 0
855 [ + - ]: 811 : && strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0)
856 : : {
857 : :
858 : 811 : *res = add_replay(opts, raw_digest);
859 [ - + ]: 811 : if (*res != SPA_MSG_SUCCESS)
860 : : {
861 : 0 : log_msg(LOG_WARNING, "[%s] (stanza #%d) Could not add digest to replay cache",
862 : 0 : spadat->pkt_source_ip, stanza_num);
863 : : return 0;
864 : : }
865 : 811 : *added_replay_digest = 1;
866 : : }
867 : :
868 : : return 1;
869 : : }
870 : :
871 : : static void
872 : 3010 : set_timeout(acc_stanza_t *acc, spa_data_t *spadat)
873 : : {
874 : 1505 : spadat->fw_access_timeout = DEF_FW_ACCESS_TIMEOUT;
875 : :
876 [ + + ]: 1505 : if(spadat->client_timeout > 0)
877 : 176 : spadat->fw_access_timeout = spadat->client_timeout;
878 [ + - ]: 1329 : else if(acc->fw_access_timeout > 0)
879 : 1329 : spadat->fw_access_timeout = acc->fw_access_timeout;
880 : :
881 : 1505 : return;
882 : : }
883 : :
884 : : static int
885 : 605 : check_port_proto(acc_stanza_t *acc, spa_data_t *spadat, const int stanza_num)
886 : : {
887 [ + + ]: 605 : if(! acc_check_port_access(acc, spadat->spa_message_remain))
888 : : {
889 : 3 : log_msg(LOG_WARNING,
890 : : "[%s] (stanza #%d) One or more requested protocol/ports was denied per access.conf.",
891 : 3 : spadat->pkt_source_ip, stanza_num
892 : : );
893 : 3 : return 0;
894 : : }
895 : : return 1;
896 : : }
897 : :
898 : : /* Process the SPA packet data
899 : : */
900 : : void
901 : 19072 : incoming_spa(fko_srv_options_t *opts)
902 : : {
903 : : /* Always a good idea to initialize ctx to null if it will be used
904 : : * repeatedly (especially when using fko_new_with_data()).
905 : : */
906 : 19072 : fko_ctx_t ctx = NULL;
907 : :
908 : 19072 : char *spa_ip_demark, *raw_digest = NULL;
909 : 19072 : int res, enc_type, stanza_num=0;
910 : 19072 : int added_replay_digest = 0;
911 : 19072 : int cmd_exec_success = 0, attempted_decrypt = 0;
912 : : char dump_buf[CTX_DUMP_BUFSIZE];
913 : :
914 : 19072 : spa_pkt_info_t *spa_pkt = &(opts->spa_pkt);
915 : :
916 : : /* This will hold our pertinent SPA data.
917 : : */
918 : : spa_data_t spadat;
919 : :
920 : : /* Loop through all access stanzas looking for a match
921 : : */
922 : 19072 : acc_stanza_t *acc = opts->acc_stanzas;
923 : :
924 : 19072 : inet_ntop(AF_INET, &(spa_pkt->packet_src_ip),
925 : : spadat.pkt_source_ip, sizeof(spadat.pkt_source_ip));
926 : :
927 : 19072 : inet_ntop(AF_INET, &(spa_pkt->packet_dst_ip),
928 : : spadat.pkt_destination_ip, sizeof(spadat.pkt_destination_ip));
929 : :
930 : : /* At this point, we want to validate and (if needed) preprocess the
931 : : * SPA data and/or to be reasonably sure we have a SPA packet (i.e
932 : : * try to eliminate obvious non-spa packets).
933 : : */
934 [ + + ]: 19072 : if(!precheck_pkt(opts, spa_pkt, &spadat, &raw_digest))
935 : : return;
936 : :
937 : : /* Now that we know there is a matching access.conf stanza and the
938 : : * incoming SPA packet is not a replay, see if we should grant any
939 : : * access
940 : : */
941 [ + + ]: 29316 : while(acc)
942 : : {
943 : 15281 : res = FKO_SUCCESS;
944 : 15281 : cmd_exec_success = 0;
945 : 15281 : attempted_decrypt = 0;
946 : 15281 : stanza_num++;
947 : :
948 : : /* Start access loop with a clean FKO context
949 : : */
950 [ + + ]: 15281 : if(ctx != NULL)
951 : : {
952 [ - + ]: 2 : if(fko_destroy(ctx) == FKO_ERROR_ZERO_OUT_DATA)
953 : 0 : log_msg(LOG_WARNING,
954 : : "[%s] (stanza #%d) fko_destroy() could not zero out sensitive data buffer.",
955 : : spadat.pkt_source_ip, stanza_num
956 : : );
957 : 2 : ctx = NULL;
958 : : }
959 : :
960 : : /* Check for a match for the SPA source and destination IP and the access stanza
961 : : */
962 [ + + ]: 15281 : if(! src_dst_check(acc, spa_pkt, &spadat, stanza_num))
963 : : {
964 : 6 : acc = acc->next;
965 : 6 : continue;
966 : : }
967 : :
968 : 15275 : log_msg(LOG_INFO,
969 : : "(stanza #%d) SPA Packet from IP: %s received with access source match",
970 : : stanza_num, spadat.pkt_source_ip);
971 : :
972 : 15275 : log_msg(LOG_DEBUG, "SPA Packet: '%s'", spa_pkt->packet_data);
973 : :
974 : : /* Make sure this access stanza has not expired
975 : : */
976 [ + + ]: 15275 : if(! check_stanza_expiration(acc, &spadat, stanza_num))
977 : : {
978 : 2 : acc = acc->next;
979 : 2 : continue;
980 : : }
981 : :
982 : : /* Get encryption type and try its decoding routine first (if the key
983 : : * for that type is set)
984 : : */
985 : 15273 : enc_type = fko_encryption_type((char *)spa_pkt->packet_data);
986 : :
987 [ + + ]: 15273 : if(acc->use_rijndael)
988 : 15228 : handle_rijndael_enc(acc, spa_pkt, &spadat, &ctx,
989 : : &attempted_decrypt, &cmd_exec_success, enc_type,
990 : : stanza_num, &res);
991 : :
992 [ + + ]: 15273 : if(! handle_gpg_enc(acc, spa_pkt, &spadat, &ctx, &attempted_decrypt,
993 : : cmd_exec_success, enc_type, stanza_num, &res))
994 : : {
995 : 1 : acc = acc->next;
996 : 1 : continue;
997 : : }
998 : :
999 [ + + ]: 15272 : if(! check_mode_ctx(&spadat, &ctx, attempted_decrypt,
1000 : : enc_type, stanza_num, res))
1001 : : {
1002 : 13749 : acc = acc->next;
1003 : 13749 : continue;
1004 : : }
1005 : :
1006 : : /* Add this SPA packet into the replay detection cache
1007 : : */
1008 [ - + ]: 1523 : if(! add_replay_cache(opts, acc, &spadat, raw_digest,
1009 : : &added_replay_digest, stanza_num, &res))
1010 : : {
1011 : 0 : acc = acc->next;
1012 : 0 : continue;
1013 : : }
1014 : :
1015 : : /* At this point the SPA data is authenticated via the HMAC (if used
1016 : : * for now). Next we need to see if it meets our access criteria which
1017 : : * the server imposes regardless of the content of the SPA packet.
1018 : : */
1019 : 1523 : log_msg(LOG_DEBUG, "[%s] (stanza #%d) SPA Decode (res=%i):",
1020 : : spadat.pkt_source_ip, stanza_num, res);
1021 : :
1022 : 1523 : res = dump_ctx_to_buffer(ctx, dump_buf, sizeof(dump_buf));
1023 [ + + ]: 1523 : if (res == FKO_SUCCESS)
1024 : 1503 : log_msg(LOG_DEBUG, "%s", dump_buf);
1025 : : else
1026 : 20 : log_msg(LOG_WARNING, "Unable to dump FKO context: %s", fko_errstr(res));
1027 : :
1028 : : /* First, if this is a GPG message, and GPG_REMOTE_ID list is not empty,
1029 : : * then we need to make sure this incoming message is signer ID matches
1030 : : * an entry in the list.
1031 : : */
1032 : :
1033 [ + + ]: 1523 : if(! handle_gpg_sigs(acc, &spadat, &ctx, enc_type, stanza_num, &res))
1034 : : {
1035 : 2 : acc = acc->next;
1036 : 2 : continue;
1037 : : }
1038 : :
1039 : : /* Populate our spa data struct for future reference.
1040 : : */
1041 : 1521 : res = get_spa_data_fields(ctx, &spadat);
1042 : :
1043 [ + + ]: 1521 : if(res != FKO_SUCCESS)
1044 : : {
1045 : 16 : log_msg(LOG_ERR,
1046 : : "[%s] (stanza #%d) Unexpected error pulling SPA data from the context: %s",
1047 : : spadat.pkt_source_ip, stanza_num, fko_errstr(res));
1048 : :
1049 : 16 : acc = acc->next;
1050 : 16 : continue;
1051 : : }
1052 : :
1053 : : /* Figure out what our timeout will be. If it is specified in the SPA
1054 : : * data, then use that. If not, try the FW_ACCESS_TIMEOUT from the
1055 : : * access.conf file (if there is one). Otherwise use the default.
1056 : : */
1057 : 1505 : set_timeout(acc, &spadat);
1058 : :
1059 : : /* Check packet age if so configured.
1060 : : */
1061 [ + + ]: 1505 : if(! check_pkt_age(opts, &spadat, stanza_num))
1062 : : {
1063 : 2 : acc = acc->next;
1064 : 2 : continue;
1065 : : }
1066 : :
1067 : : /* At this point, we have enough to check the embedded (or packet source)
1068 : : * IP address against the defined access rights. We start by splitting
1069 : : * the spa msg source IP from the remainder of the message.
1070 : : */
1071 : 1503 : spa_ip_demark = strchr(spadat.spa_message, ',');
1072 [ - + ]: 1503 : if(spa_ip_demark == NULL)
1073 : : {
1074 : 0 : log_msg(LOG_WARNING,
1075 : : "[%s] (stanza #%d) Error parsing SPA message string: %s",
1076 : : spadat.pkt_source_ip, stanza_num, fko_errstr(res));
1077 : :
1078 : 0 : acc = acc->next;
1079 : 0 : continue;
1080 : : }
1081 : :
1082 [ - + ]: 1503 : if((spa_ip_demark-spadat.spa_message) < MIN_IPV4_STR_LEN-1
1083 : 1503 : || (spa_ip_demark-spadat.spa_message) > MAX_IPV4_STR_LEN)
1084 : : {
1085 : 0 : log_msg(LOG_WARNING,
1086 : : "[%s] (stanza #%d) Invalid source IP in SPA message, ignoring SPA packet",
1087 : : spadat.pkt_source_ip, stanza_num);
1088 : 0 : break;
1089 : : }
1090 : :
1091 : 1503 : strlcpy(spadat.spa_message_src_ip,
1092 : 1503 : spadat.spa_message, (spa_ip_demark-spadat.spa_message)+1);
1093 : :
1094 [ - + ]: 1503 : if(! is_valid_ipv4_addr(spadat.spa_message_src_ip, strlen(spadat.spa_message_src_ip)))
1095 : : {
1096 : 0 : log_msg(LOG_WARNING,
1097 : : "[%s] (stanza #%d) Invalid source IP in SPA message, ignoring SPA packet",
1098 : : spadat.pkt_source_ip, stanza_num, fko_errstr(res));
1099 : 0 : break;
1100 : : }
1101 : :
1102 : 1503 : strlcpy(spadat.spa_message_remain, spa_ip_demark+1, MAX_DECRYPTED_SPA_LEN);
1103 : :
1104 : : /* If use source IP was requested (embedded IP of 0.0.0.0), make sure it
1105 : : * is allowed.
1106 : : */
1107 [ + + ]: 1503 : if(! check_src_access(acc, &spadat, stanza_num))
1108 : : {
1109 : 1 : acc = acc->next;
1110 : 1 : continue;
1111 : : }
1112 : :
1113 : : /* If REQUIRE_USERNAME is set, make sure the username in this SPA data
1114 : : * matches.
1115 : : */
1116 [ + + ]: 1502 : if(! check_username(acc, &spadat, stanza_num))
1117 : : {
1118 : 1 : acc = acc->next;
1119 : 1 : continue;
1120 : : }
1121 : :
1122 : : /* Take action based on SPA message type.
1123 : : */
1124 [ + + ]: 1501 : if(! check_nat_access_types(opts, acc, &spadat, stanza_num))
1125 : : {
1126 : 262 : acc = acc->next;
1127 : 262 : continue;
1128 : : }
1129 : :
1130 : : /* Command messages.
1131 : : */
1132 [ + + ]: 1239 : if(acc->cmd_cycle_open != NULL)
1133 : : {
1134 [ - + ]: 442 : if(cmd_cycle_open(opts, acc, &spadat, stanza_num, &res))
1135 : : break; /* successfully processed a matching access stanza */
1136 : : else
1137 : : {
1138 : 0 : acc = acc->next;
1139 : 0 : continue;
1140 : : }
1141 : : }
1142 [ + + ]: 797 : else if(spadat.message_type == FKO_COMMAND_MSG)
1143 : : {
1144 [ + + ]: 192 : if(process_cmd_msg(opts, acc, &spadat, stanza_num, &res))
1145 : : {
1146 : : /* we processed the command on a matching access stanza, so we
1147 : : * don't look for anything else to do with this SPA packet
1148 : : */
1149 : : break;
1150 : : }
1151 : : else
1152 : : {
1153 : 172 : acc = acc->next;
1154 : 172 : continue;
1155 : : }
1156 : : }
1157 : :
1158 : : /* From this point forward, we have some kind of access message. So
1159 : : * we first see if access is allowed by checking access against
1160 : : * restrict_ports and open_ports.
1161 : : *
1162 : : * --DSS TODO: We should add BLACKLIST support here as well.
1163 : : */
1164 [ + + ]: 605 : if(! check_port_proto(acc, &spadat, stanza_num))
1165 : : {
1166 : 3 : acc = acc->next;
1167 : 3 : continue;
1168 : : }
1169 : :
1170 : : /* At this point, we process the SPA request and break out of the
1171 : : * access stanza loop (first valid access stanza stops us looking
1172 : : * for others).
1173 : : */
1174 [ + + ]: 602 : if(opts->test) /* no firewall changes in --test mode */
1175 : : {
1176 : 279 : log_msg(LOG_WARNING,
1177 : : "[%s] (stanza #%d) --test mode enabled, skipping firewall manipulation.",
1178 : : spadat.pkt_source_ip, stanza_num
1179 : : );
1180 : 279 : acc = acc->next;
1181 : 279 : continue;
1182 : : }
1183 : : else
1184 : : {
1185 [ - + ]: 323 : if(acc->cmd_cycle_open != NULL)
1186 : : {
1187 [ # # ]: 0 : if(cmd_cycle_open(opts, acc, &spadat, stanza_num, &res))
1188 : : break; /* successfully processed a matching access stanza */
1189 : : else
1190 : : {
1191 : 0 : acc = acc->next;
1192 : 0 : continue;
1193 : : }
1194 : : }
1195 : : else
1196 : : {
1197 : 323 : process_spa_request(opts, acc, &spadat);
1198 : : }
1199 : : }
1200 : :
1201 : : /* If we made it here, then the SPA packet was processed according
1202 : : * to a matching access.conf stanza, so we're done with this packet.
1203 : : */
1204 : 14819 : break;
1205 : : }
1206 : :
1207 [ + + ]: 14820 : if (raw_digest != NULL)
1208 : 14720 : free(raw_digest);
1209 : :
1210 [ + + ]: 14820 : if(ctx != NULL)
1211 : : {
1212 [ - + ]: 1536 : if(fko_destroy(ctx) == FKO_ERROR_ZERO_OUT_DATA)
1213 : 0 : log_msg(LOG_WARNING,
1214 : : "[%s] (stanza #%d) fko_destroy() could not zero out sensitive data buffer.",
1215 : : spadat.pkt_source_ip, stanza_num
1216 : : );
1217 : 1536 : ctx = NULL;
1218 : : }
1219 : :
1220 : : return;
1221 : : }
1222 : :
1223 : : /***EOF***/
|