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