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