Branch data Line data Source code
1 : : /*
2 : : *****************************************************************************
3 : : *
4 : : * File: fko_decode.c
5 : : *
6 : : * Purpose: Decode an FKO SPA message after decryption.
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 "fko_common.h"
32 : : #include "fko.h"
33 : : #include "cipher_funcs.h"
34 : : #include "base64.h"
35 : : #include "digest.h"
36 : :
37 : : #define FIELD_PARSERS 9
38 : :
39 : : static int
40 : 4774261 : num_fields(char *str)
41 : : {
42 : 4774261 : int i=0;
43 : 4774261 : char *tmp = NULL;
44 : :
45 : : /* Count the number of remaining SPA packet fields
46 : : */
47 [ + - ]: 24215384 : for (i=0; i <= MAX_SPA_FIELDS+1; i++)
48 : : {
49 [ + + ]: 24215384 : if ((tmp = strchr(str, ':')) == NULL)
50 : : break;
51 : 19441123 : str = tmp + 1;
52 : : }
53 : 4774261 : return i;
54 : : }
55 : :
56 : : static int
57 : 2530130 : last_field(char *str)
58 : : {
59 : 2530130 : int i=0, pos_last=0;
60 : 2530130 : char *tmp = NULL;
61 : :
62 : : /* Count the number of bytes to the last ':' char
63 : : */
64 [ + - ]: 18767902 : for (i=0; i <= MAX_SPA_FIELDS+1; i++)
65 : : {
66 [ + + ]: 18767902 : if ((tmp = strchr(str, ':')) == NULL)
67 : : break;
68 : :
69 : 16237772 : pos_last += (tmp - str) + 1;
70 : 16237772 : str = tmp + 1;
71 : : }
72 : 2530130 : return pos_last;
73 : : }
74 : :
75 : : static int
76 : 2527661 : verify_digest(char *tbuf, int t_size, fko_ctx_t ctx)
77 : : {
78 [ + + + + : 2527661 : switch(ctx->digest_type)
+ - ]
79 : : {
80 : : case FKO_DIGEST_MD5:
81 : 317272 : md5_base64(tbuf, (unsigned char*)ctx->encoded_msg, ctx->encoded_msg_len);
82 : 317272 : break;
83 : :
84 : : case FKO_DIGEST_SHA1:
85 : 317284 : sha1_base64(tbuf, (unsigned char*)ctx->encoded_msg, ctx->encoded_msg_len);
86 : 317284 : break;
87 : :
88 : : case FKO_DIGEST_SHA256:
89 : 1258563 : sha256_base64(tbuf, (unsigned char*)ctx->encoded_msg, ctx->encoded_msg_len);
90 : 1258563 : break;
91 : :
92 : : case FKO_DIGEST_SHA384:
93 : 317270 : sha384_base64(tbuf, (unsigned char*)ctx->encoded_msg, ctx->encoded_msg_len);
94 : 317270 : break;
95 : :
96 : : case FKO_DIGEST_SHA512:
97 : 317272 : sha512_base64(tbuf, (unsigned char*)ctx->encoded_msg, ctx->encoded_msg_len);
98 : 317272 : break;
99 : :
100 : : default: /* Invalid or unsupported digest */
101 : : return(FKO_ERROR_INVALID_DIGEST_TYPE);
102 : : }
103 : :
104 : : /* We give up here if the computed digest does not match the
105 : : * digest in the message data.
106 : : */
107 [ + + ]: 2527661 : if(constant_runtime_cmp(ctx->digest, tbuf, t_size) != 0)
108 : : return(FKO_ERROR_DIGEST_VERIFICATION_FAILED);
109 : :
110 : 2520550 : return FKO_SUCCESS;
111 : : }
112 : :
113 : : static int
114 : 2530130 : is_valid_digest_len(int t_size, fko_ctx_t ctx)
115 : : {
116 [ + + + + : 2530130 : switch(t_size)
+ + ]
117 : : {
118 : : case MD5_B64_LEN:
119 : 317272 : ctx->digest_type = FKO_DIGEST_MD5;
120 : 317272 : ctx->digest_len = MD5_B64_LEN;
121 : 317272 : break;
122 : :
123 : : case SHA1_B64_LEN:
124 : 317284 : ctx->digest_type = FKO_DIGEST_SHA1;
125 : 317284 : ctx->digest_len = SHA1_B64_LEN;
126 : 317284 : break;
127 : :
128 : : case SHA256_B64_LEN:
129 : 1258563 : ctx->digest_type = FKO_DIGEST_SHA256;
130 : 1258563 : ctx->digest_len = SHA256_B64_LEN;
131 : 1258563 : break;
132 : :
133 : : case SHA384_B64_LEN:
134 : 317270 : ctx->digest_type = FKO_DIGEST_SHA384;
135 : 317270 : ctx->digest_len = SHA384_B64_LEN;
136 : 317270 : break;
137 : :
138 : : case SHA512_B64_LEN:
139 : 317272 : ctx->digest_type = FKO_DIGEST_SHA512;
140 : 317272 : ctx->digest_len = SHA512_B64_LEN;
141 : 317272 : break;
142 : :
143 : : default: /* Invalid or unsupported digest */
144 : : return(FKO_ERROR_INVALID_DIGEST_TYPE);
145 : : }
146 : :
147 [ + - ]: 2527661 : if (ctx->encoded_msg_len - t_size < 0)
148 : : return(FKO_ERROR_INVALID_DATA_DECODE_ENC_MSG_LEN_MT_T_SIZE);
149 : :
150 : 2527661 : return FKO_SUCCESS;
151 : : }
152 : :
153 : : static int
154 : 2162520 : parse_msg(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
155 : : {
156 [ + + ]: 2162520 : if((*t_size = strcspn(*ndx, ":")) < 1)
157 : : return(FKO_ERROR_INVALID_DATA_DECODE_MESSAGE_MISSING);
158 : :
159 [ + + ]: 2162404 : if (*t_size > MAX_SPA_MESSAGE_SIZE)
160 : : return(FKO_ERROR_INVALID_DATA_DECODE_MESSAGE_TOOBIG);
161 : :
162 : 2128784 : strlcpy(tbuf, *ndx, *t_size+1);
163 : :
164 [ + + ]: 2128784 : if(ctx->message != NULL)
165 : 550290 : free(ctx->message);
166 : :
167 : 2128784 : ctx->message = calloc(1, *t_size+1); /* Yes, more than we need */
168 : :
169 [ + - ]: 2128784 : if(ctx->message == NULL)
170 : : return(FKO_ERROR_MEMORY_ALLOCATION);
171 : :
172 [ + + ]: 2128784 : if(b64_decode(tbuf, (unsigned char*)ctx->message) < 0)
173 : : return(FKO_ERROR_INVALID_DATA_DECODE_MESSAGE_DECODEFAIL);
174 : :
175 [ + + ]: 2122907 : if(ctx->message_type == FKO_COMMAND_MSG)
176 : : {
177 : : /* Require a message similar to: 1.2.3.4,<command>
178 : : */
179 [ + + ]: 43055 : if(validate_cmd_msg(ctx->message) != FKO_SUCCESS)
180 : : {
181 : : return(FKO_ERROR_INVALID_DATA_DECODE_MESSAGE_VALIDFAIL);
182 : : }
183 : : }
184 : : else
185 : : {
186 : : /* Require a message similar to: 1.2.3.4,tcp/22
187 : : */
188 [ + + ]: 2079852 : if(validate_access_msg(ctx->message) != FKO_SUCCESS)
189 : : {
190 : : return(FKO_ERROR_INVALID_DATA_DECODE_ACCESS_VALIDFAIL);
191 : : }
192 : : }
193 : :
194 : 1906191 : *ndx += *t_size + 1;
195 : 1906191 : return FKO_SUCCESS;
196 : : }
197 : :
198 : : static int
199 : 1906191 : parse_nat_msg(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
200 : : {
201 [ + + ]: 1906191 : if( ctx->message_type == FKO_NAT_ACCESS_MSG
202 : 1906191 : || ctx->message_type == FKO_LOCAL_NAT_ACCESS_MSG
203 [ + + ]: 1827095 : || ctx->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
204 [ + + ]: 1726129 : || ctx->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
205 : : {
206 [ + + ]: 219569 : if((*t_size = strcspn(*ndx, ":")) < 1)
207 : : return(FKO_ERROR_INVALID_DATA_DECODE_NATACCESS_MISSING);
208 : :
209 [ + + ]: 219246 : if (*t_size > MAX_SPA_MESSAGE_SIZE)
210 : : return(FKO_ERROR_INVALID_DATA_DECODE_NATACCESS_TOOBIG);
211 : :
212 : 208410 : strlcpy(tbuf, *ndx, *t_size+1);
213 : :
214 [ - + ]: 208410 : if(ctx->nat_access != NULL)
215 : 0 : free(ctx->nat_access);
216 : :
217 : 208410 : ctx->nat_access = calloc(1, *t_size+1); /* Yes, more than we need */
218 [ + - ]: 208410 : if(ctx->nat_access == NULL)
219 : : return(FKO_ERROR_MEMORY_ALLOCATION);
220 : :
221 [ + + ]: 208410 : if(b64_decode(tbuf, (unsigned char*)ctx->nat_access) < 0)
222 : : return(FKO_ERROR_INVALID_DATA_DECODE_NATACCESS_DECODEFAIL);
223 : :
224 [ + + ]: 207282 : if(validate_nat_access_msg(ctx->nat_access) != FKO_SUCCESS)
225 : : return(FKO_ERROR_INVALID_DATA_DECODE_NATACCESS_VALIDFAIL);
226 : :
227 : 107652 : *ndx += *t_size + 1;
228 : : }
229 : :
230 : : return FKO_SUCCESS;
231 : : }
232 : :
233 : : static int
234 : 1794274 : parse_server_auth(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
235 : : {
236 [ + + ]: 1794274 : if((*t_size = strlen(*ndx)) > 0)
237 : : {
238 [ + + ]: 125715 : if (*t_size > MAX_SPA_MESSAGE_SIZE)
239 : : {
240 : : return(FKO_ERROR_INVALID_DATA_DECODE_SRVAUTH_MISSING);
241 : : }
242 : : }
243 : : else
244 : : return FKO_SUCCESS;
245 : :
246 [ + + ]: 119611 : if( ctx->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG
247 : : || ctx->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
248 : 119611 : || ctx->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
249 : : {
250 : : /* If we are here then we may still have a server_auth string,
251 : : * or a timeout, or both. So we look for a ':' delimiter. If
252 : : * it is there we have both, if not we check the message_type
253 : : * again.
254 : : */
255 [ + + ]: 94403 : if(strchr(*ndx, ':'))
256 : : {
257 : 36080 : *t_size = strcspn(*ndx, ":");
258 : :
259 [ + - ]: 36080 : if (*t_size > MAX_SPA_MESSAGE_SIZE)
260 : : return(FKO_ERROR_INVALID_DATA_DECODE_EXTRA_TOOBIG);
261 : :
262 : 36080 : strlcpy(tbuf, *ndx, *t_size+1);
263 : :
264 [ - + ]: 36080 : if(ctx->server_auth != NULL)
265 : 0 : free(ctx->server_auth);
266 : :
267 : 36080 : ctx->server_auth = calloc(1, *t_size+1); /* Yes, more than we need */
268 [ + - ]: 36080 : if(ctx->server_auth == NULL)
269 : : return(FKO_ERROR_MEMORY_ALLOCATION);
270 : :
271 [ + + ]: 36080 : if(b64_decode(tbuf, (unsigned char*)ctx->server_auth) < 0)
272 : : return(FKO_ERROR_INVALID_DATA_DECODE_EXTRA_DECODEFAIL);
273 : :
274 : 31858 : *ndx += *t_size + 1;
275 : : }
276 : : }
277 : : else
278 : : {
279 : 25208 : strlcpy(tbuf, *ndx, *t_size+1);
280 : :
281 [ - + ]: 25208 : if(ctx->server_auth != NULL)
282 : 0 : free(ctx->server_auth);
283 : :
284 : 25208 : ctx->server_auth = calloc(1, *t_size+1); /* Yes, more than we need */
285 [ + - ]: 25208 : if(ctx->server_auth == NULL)
286 : : return(FKO_ERROR_MEMORY_ALLOCATION);
287 : :
288 [ + + ]: 25208 : if(b64_decode(tbuf, (unsigned char*)ctx->server_auth) < 0)
289 : : return(FKO_ERROR_INVALID_DATA_DECODE_SRVAUTH_DECODEFAIL);
290 : : }
291 : :
292 : : return FKO_SUCCESS;
293 : : }
294 : :
295 : : static int
296 : 1783852 : parse_client_timeout(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
297 : : {
298 : : int is_err;
299 : :
300 [ + + ]: 1783852 : if( ctx->message_type == FKO_CLIENT_TIMEOUT_ACCESS_MSG
301 : : || ctx->message_type == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG
302 : 1783852 : || ctx->message_type == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG)
303 : : {
304 [ + + ]: 92799 : if((*t_size = strlen(*ndx)) < 1)
305 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMEOUT_MISSING);
306 : :
307 [ + - ]: 90161 : if (*t_size > MAX_SPA_MESSAGE_SIZE)
308 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMEOUT_TOOBIG);
309 : :
310 : : /* Should be a number only.
311 : : */
312 [ + + ]: 90161 : if(strspn(*ndx, "0123456789") != *t_size)
313 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMEOUT_VALIDFAIL);
314 : :
315 : 41973 : ctx->client_timeout = (unsigned int) strtol_wrapper(*ndx, 0,
316 : : (2 << 15), NO_EXIT_UPON_ERR, &is_err);
317 [ + + ]: 41973 : if(is_err != FKO_SUCCESS)
318 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMEOUT_DECODEFAIL);
319 : : }
320 : :
321 : : return FKO_SUCCESS;
322 : : }
323 : :
324 : : static int
325 : 2228116 : parse_msg_type(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
326 : : {
327 : : int is_err, remaining_fields;
328 : :
329 [ + + ]: 2228116 : if((*t_size = strcspn(*ndx, ":")) < 1)
330 : : return(FKO_ERROR_INVALID_DATA_DECODE_MSGTYPE_MISSING);
331 : :
332 [ + + ]: 2227995 : if(*t_size > MAX_SPA_MESSAGE_TYPE_SIZE)
333 : : return(FKO_ERROR_INVALID_DATA_DECODE_MSGTYPE_TOOBIG);
334 : :
335 : 2164350 : strlcpy(tbuf, *ndx, *t_size+1);
336 : :
337 : 2164350 : ctx->message_type = strtol_wrapper(tbuf, 0,
338 : : FKO_LAST_MSG_TYPE-1, NO_EXIT_UPON_ERR, &is_err);
339 : :
340 [ + + ]: 2164350 : if(is_err != FKO_SUCCESS)
341 : : return(FKO_ERROR_INVALID_DATA_DECODE_MSGTYPE_DECODEFAIL);
342 : :
343 : : /* Now that we have a valid type, ensure that the total
344 : : * number of SPA fields is also valid for the type
345 : : */
346 [ + - ][ + + ]: 2163634 : remaining_fields = num_fields(*ndx);
[ + + ][ + - ]
347 : :
348 : : switch(ctx->message_type)
349 : : {
350 : : /* optional server_auth + digest */
351 : : case FKO_COMMAND_MSG:
352 : : case FKO_ACCESS_MSG:
353 [ + + ]: 1789499 : if(remaining_fields > 2)
354 : : return FKO_ERROR_INVALID_DATA_DECODE_WRONG_NUM_FIELDS;
355 : : break;
356 : :
357 : : /* nat or client timeout + optional server_auth + digest */
358 : : case FKO_NAT_ACCESS_MSG:
359 : : case FKO_LOCAL_NAT_ACCESS_MSG:
360 : : case FKO_CLIENT_TIMEOUT_ACCESS_MSG:
361 [ + - ]: 170946 : if(remaining_fields > 3)
362 : : return FKO_ERROR_INVALID_DATA_DECODE_WRONG_NUM_FIELDS;
363 : : break;
364 : :
365 : : /* client timeout + nat + optional server_auth + digest */
366 : : case FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG:
367 : : case FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG:
368 [ + + ]: 203189 : if(remaining_fields > 4)
369 : : return FKO_ERROR_INVALID_DATA_DECODE_WRONG_NUM_FIELDS;
370 : : break;
371 : :
372 : : default: /* Should not reach here */
373 : : return(FKO_ERROR_INVALID_DATA_DECODE_MSGTYPE_DECODEFAIL);
374 : : }
375 : :
376 : 2162520 : *ndx += *t_size + 1;
377 : 2162520 : return FKO_SUCCESS;
378 : : }
379 : :
380 : : static int
381 : 2296420 : parse_version(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
382 : : {
383 [ + + ]: 2296420 : if((*t_size = strcspn(*ndx, ":")) < 1)
384 : : return(FKO_ERROR_INVALID_DATA_DECODE_VERSION_MISSING);
385 : :
386 [ + + ]: 2293806 : if (*t_size > MAX_SPA_VERSION_SIZE)
387 : : return(FKO_ERROR_INVALID_DATA_DECODE_VERSION_TOOBIG);
388 : :
389 [ + + ]: 2228116 : if(ctx->version != NULL)
390 : 1529267 : free(ctx->version);
391 : :
392 : 2228116 : ctx->version = calloc(1, *t_size+1);
393 [ + - ]: 2228116 : if(ctx->version == NULL)
394 : : return(FKO_ERROR_MEMORY_ALLOCATION);
395 : :
396 : 2228116 : strlcpy(ctx->version, *ndx, *t_size+1);
397 : :
398 : 2228116 : *ndx += *t_size + 1;
399 : 2228116 : return FKO_SUCCESS;
400 : : }
401 : :
402 : : static int
403 : 2399523 : parse_timestamp(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
404 : : {
405 : : int is_err;
406 : :
407 [ + + ]: 2399523 : if((*t_size = strcspn(*ndx, ":")) < 1)
408 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMESTAMP_MISSING);
409 : :
410 [ + + ]: 2396898 : if (*t_size > MAX_SPA_TIMESTAMP_SIZE)
411 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMESTAMP_TOOBIG);
412 : :
413 : 2297054 : strlcpy(tbuf, *ndx, *t_size+1);
414 : :
415 : 2297054 : ctx->timestamp = (unsigned int) strtol_wrapper(tbuf,
416 : : 0, -1, NO_EXIT_UPON_ERR, &is_err);
417 [ + + ]: 2297054 : if(is_err != FKO_SUCCESS)
418 : : return(FKO_ERROR_INVALID_DATA_DECODE_TIMESTAMP_DECODEFAIL);
419 : :
420 : 2296420 : *ndx += *t_size + 1;
421 : :
422 : 2296420 : return FKO_SUCCESS;
423 : : }
424 : :
425 : : static int
426 : 2509826 : parse_username(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
427 : : {
428 [ + + ]: 2509826 : if((*t_size = strcspn(*ndx, ":")) < 1)
429 : : return(FKO_ERROR_INVALID_DATA_DECODE_USERNAME_MISSING);
430 : :
431 [ + + ]: 2507256 : if (*t_size > MAX_SPA_USERNAME_SIZE)
432 : : return(FKO_ERROR_INVALID_DATA_DECODE_USERNAME_TOOBIG);
433 : :
434 : 2461293 : strlcpy(tbuf, *ndx, *t_size+1);
435 : :
436 [ + + ]: 2461293 : if(ctx->username != NULL)
437 : 1661701 : free(ctx->username);
438 : :
439 : 2461293 : ctx->username = calloc(1, *t_size+1); /* Yes, more than we need */
440 [ + - ]: 2461293 : if(ctx->username == NULL)
441 : : return(FKO_ERROR_MEMORY_ALLOCATION);
442 : :
443 [ + + ]: 2461293 : if(b64_decode(tbuf, (unsigned char*)ctx->username) < 0)
444 : : return(FKO_ERROR_INVALID_DATA_DECODE_USERNAME_DECODEFAIL);
445 : :
446 [ + + ]: 2459034 : if(validate_username(ctx->username) != FKO_SUCCESS)
447 : : return(FKO_ERROR_INVALID_DATA_DECODE_USERNAME_VALIDFAIL);
448 : :
449 : 2399523 : *ndx += *t_size + 1;
450 : :
451 : 2399523 : return FKO_SUCCESS;
452 : : }
453 : :
454 : : static int
455 : 2520550 : parse_rand_val(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
456 : : {
457 [ + + ]: 2520550 : if((*t_size = strcspn(*ndx, ":")) < FKO_RAND_VAL_SIZE)
458 : : return(FKO_ERROR_INVALID_DATA_DECODE_RAND_MISSING);
459 : :
460 [ + + ]: 2509826 : if(ctx->rand_val != NULL)
461 : 1704334 : free(ctx->rand_val);
462 : :
463 : 2509826 : ctx->rand_val = calloc(1, FKO_RAND_VAL_SIZE+1);
464 [ + - ]: 2509826 : if(ctx->rand_val == NULL)
465 : : return(FKO_ERROR_MEMORY_ALLOCATION);
466 : :
467 : 5019652 : ctx->rand_val = strncpy(ctx->rand_val, *ndx, FKO_RAND_VAL_SIZE);
468 : :
469 : 2509826 : *ndx += *t_size + 1;
470 : :
471 : 2509826 : return FKO_SUCCESS;
472 : : }
473 : :
474 : : /* Decode the encoded SPA data.
475 : : */
476 : : int
477 : 3008326 : fko_decode_spa_data(fko_ctx_t ctx)
478 : : {
479 : : char *tbuf, *ndx;
480 : : int t_size, i, res;
481 : :
482 : : /* Array of function pointers to SPA field parsing functions
483 : : */
484 : 3008326 : int (*field_parser[FIELD_PARSERS])(char *tbuf, char **ndx, int *t_size, fko_ctx_t ctx)
485 : : = { parse_rand_val, /* Extract random value */
486 : : parse_username, /* Extract username */
487 : : parse_timestamp, /* Client timestamp */
488 : : parse_version, /* SPA version */
489 : : parse_msg_type, /* SPA msg type */
490 : : parse_msg, /* SPA msg string */
491 : : parse_nat_msg, /* SPA NAT msg string */
492 : : parse_server_auth, /* optional server authentication method */
493 : : parse_client_timeout /* client defined timeout */
494 : : };
495 : :
496 [ + + ]: 3008326 : if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
497 : : return(FKO_ERROR_INVALID_DATA_DECODE_MSGLEN_VALIDFAIL);
498 : :
499 : : /* Make sure there are no non-ascii printable chars
500 : : */
501 [ + + ]: 435196232 : for (i=0; i < (int)strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE); i++)
502 [ + + ]: 432585605 : if(isprint(ctx->encoded_msg[i]) == 0)
503 : : return(FKO_ERROR_INVALID_DATA_DECODE_NON_ASCII);
504 : :
505 : : /* Make sure there are enough fields in the SPA packet
506 : : * delimited with ':' chars
507 : : */
508 : 2610627 : ndx = ctx->encoded_msg;
509 : :
510 [ + + ]: 2610627 : if (num_fields(ndx) < MIN_SPA_FIELDS)
511 : : return(FKO_ERROR_INVALID_DATA_DECODE_LT_MIN_FIELDS);
512 : :
513 : 2530130 : ndx += last_field(ndx);
514 : :
515 : 2530130 : t_size = strnlen(ndx, SHA512_B64_LEN+1);
516 : :
517 : : /* Validate digest length
518 : : */
519 : 2530130 : res = is_valid_digest_len(t_size, ctx);
520 [ + + ]: 2530130 : if(res != FKO_SUCCESS)
521 : : return res;
522 : :
523 [ + + ]: 2527661 : if(ctx->digest != NULL)
524 : 1084528 : free(ctx->digest);
525 : :
526 : : /* Copy the digest into the context and terminate the encoded data
527 : : * at that point so the original digest is not part of the
528 : : * encoded string.
529 : : */
530 : 2527661 : ctx->digest = strdup(ndx);
531 [ + - ]: 2527661 : if(ctx->digest == NULL)
532 : : return(FKO_ERROR_MEMORY_ALLOCATION);
533 : :
534 : : /* Chop the digest off of the encoded_msg bucket...
535 : : */
536 : 2527661 : bzero((ndx-1), t_size);
537 : :
538 : 2527661 : ctx->encoded_msg_len -= t_size+1;
539 : :
540 : : /* Make a tmp bucket for processing base64 encoded data and
541 : : * other general use.
542 : : */
543 : 2527661 : tbuf = calloc(1, FKO_ENCODE_TMP_BUF_SIZE);
544 [ + - ]: 2527661 : if(tbuf == NULL)
545 : : return(FKO_ERROR_MEMORY_ALLOCATION);
546 : :
547 : : /* Can now verify the digest.
548 : : */
549 : 2527661 : res = verify_digest(tbuf, t_size, ctx);
550 [ + + ]: 2527661 : if(res != FKO_SUCCESS)
551 : : {
552 : 7111 : free(tbuf);
553 : 7111 : return(FKO_ERROR_DIGEST_VERIFICATION_FAILED);
554 : : }
555 : :
556 : : /* Now we will work through the encoded data and extract (and base64-
557 : : * decode where necessary), the SPA data fields and populate the context.
558 : : */
559 : 2520550 : ndx = ctx->encoded_msg;
560 : :
561 [ + + ]: 21333998 : for (i=0; i < FIELD_PARSERS; i++)
562 : : {
563 : 19601272 : res = (*field_parser[i])(tbuf, &ndx, &t_size, ctx);
564 [ + + ]: 19601272 : if(res != FKO_SUCCESS)
565 : : {
566 : 787824 : free(tbuf);
567 : 787824 : return res;
568 : : }
569 : : }
570 : :
571 : : /* Done with the tmp buffer.
572 : : */
573 : 1732726 : free(tbuf);
574 : :
575 : : /* Call the context initialized.
576 : : */
577 : 1732726 : ctx->initval = FKO_CTX_INITIALIZED;
578 : 1732726 : FKO_SET_CTX_INITIALIZED(ctx);
579 : :
580 : 1732726 : return(FKO_SUCCESS);
581 : : }
582 : :
583 : : /***EOF***/
|