*
* Author: Damien S. Stuart
*
- * Purpose: Decrypt and decode an FKO SPA message.
+ * Purpose: Decode an FKO SPA message after decryption.
*
* Copyright 2009-2010 Damien Stuart (dstuart@dstuart.org)
*
#include "base64.h"
#include "digest.h"
-/* Decrypt the encoded SPA data.
+/* Decode the encoded SPA data.
*/
int
fko_decode_spa_data(fko_ctx_t ctx)
{
- char *tbuf, *ndx;
- int t_size;
+ char *tbuf, *ndx, *tmp;
+ int t_size, i;
/* Check for required data.
*/
|| strlen(ctx->encoded_msg) < MIN_SPA_ENCODED_MSG_SIZE)
return(FKO_ERROR_INVALID_DATA);
- /* Move the Digest to its place in the context.
+ /* Make sure there are enough fields in the SPA packet
+ * delimited with ':' chars
*/
- ndx = strrchr(ctx->encoded_msg, ':'); /* Find the last : in the data */
- if(ndx == NULL)
- return(FKO_ERROR_INVALID_DATA);
+ ndx = ctx->encoded_msg;
+ for (i=0; i < MAX_SPA_FIELDS; i++)
+ {
+ if ((tmp = strchr(ndx, ':')) == NULL)
+ break;
- ndx++;
+ ndx = tmp;
+ ndx++;
+ }
+
+ if (i < MIN_SPA_FIELDS)
+ return(FKO_ERROR_INVALID_DATA);
t_size = strlen(ndx);
/* We give up here if the computed digest does not match the
* digest in the message data.
*/
- if(strcmp(ctx->digest, tbuf))
+ if(strncmp(ctx->digest, tbuf, t_size))
{
free(tbuf);
return(FKO_ERROR_DIGEST_VERIFICATION_FAILED);
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_USERNAME_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
strlcpy(tbuf, ndx, t_size+1);
ctx->username = malloc(t_size+1); /* Yes, more than we need */
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_TIMESTAMP_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
strlcpy(tbuf, ndx, t_size+1);
ctx->timestamp = (unsigned int)atoi(tbuf);
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_VERSION_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
ctx->version = malloc(t_size+1);
if(ctx->version == NULL)
{
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_MESSAGE_TYPE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
strlcpy(tbuf, ndx, t_size+1);
ctx->message_type = (unsigned int)atoi(tbuf);
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_MESSAGE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
strlcpy(tbuf, ndx, t_size+1);
ctx->message = malloc(t_size+1); /* Yes, more than we need */
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_MESSAGE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
strlcpy(tbuf, ndx, t_size+1);
ctx->nat_access = malloc(t_size+1); /* Yes, more than we need */
ndx += t_size + 1;
if((t_size = strlen(ndx)) > 0)
{
+ if (t_size > MAX_SPA_MESSAGE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
/* There is data, but what is it?
* If the message_type does not have a timeout, assume it is a
* server_auth field.
{
t_size = strcspn(ndx, ":");
+ if (t_size > MAX_SPA_MESSAGE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
+
/* Looks like we have both, so assume this is the
*/
strlcpy(tbuf, ndx, t_size+1);
free(tbuf);
return(FKO_ERROR_INVALID_DATA);
}
+ if (t_size > MAX_SPA_MESSAGE_SIZE)
+ {
+ free(tbuf);
+ return(FKO_ERROR_INVALID_DATA);
+ }
/* Should be a number only.
*/