Example #1
0
static PyObject *
set_spa_hmac_type(PyObject *self, PyObject *args)
{
    fko_ctx_t ctx;
    short hmac_type;
    int res;

    if(!PyArg_ParseTuple(args, "kh", &ctx, &hmac_type))
        return NULL;

    res = fko_set_spa_hmac_type(ctx, hmac_type);

    if(res != FKO_SUCCESS)
    {
        PyErr_SetString(FKOError, fko_errstr(res));
        return NULL;
    }

    return Py_BuildValue("", NULL);
}
Example #2
0
static void spa_default_ctx(fko_ctx_t *ctx)
{
    fko_new(ctx);
    fko_set_rand_value(*ctx, NULL);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_message(*ctx, "123.123.123.123,tcp/22");
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_message_type(*ctx, FKO_ACCESS_MSG);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_username(*ctx, "someuser");
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_encryption_type(*ctx, FKO_ENCRYPTION_RIJNDAEL);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_encryption_mode(*ctx, FKO_ENC_MODE_CBC);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_digest_type(*ctx, FKO_DEFAULT_DIGEST);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    fko_set_spa_hmac_type(*ctx, FKO_HMAC_SHA256);
    fko_spa_data_final(*ctx, ENC_KEY, 16, HMAC_KEY, 16);
    // display_ctx(*ctx);

    spa_calls += 16;
    return;
}
Example #3
0
int
fko_verify_hmac(fko_ctx_t ctx,
    const char * const hmac_key, const int hmac_key_len)
{
    char    *hmac_digest_from_data = NULL;
    char    *tbuf = NULL;
    int      res = FKO_SUCCESS;
    int      hmac_b64_digest_len = 0, zero_free_rv = FKO_SUCCESS;

    /* Must be initialized
    */
    if(!CTX_INITIALIZED(ctx))
        return(FKO_ERROR_CTX_NOT_INITIALIZED);

    if (! is_valid_encoded_msg_len(ctx->encrypted_msg_len))
        return(FKO_ERROR_INVALID_DATA_HMAC_MSGLEN_VALIDFAIL);

    if(hmac_key_len > MAX_DIGEST_BLOCK_LEN)
        return(FKO_ERROR_INVALID_HMAC_KEY_LEN);

    if(ctx->hmac_type == FKO_HMAC_MD5)
        hmac_b64_digest_len = MD5_B64_LEN;
    else if(ctx->hmac_type == FKO_HMAC_SHA1)
        hmac_b64_digest_len = SHA1_B64_LEN;
    else if(ctx->hmac_type == FKO_HMAC_SHA256)
        hmac_b64_digest_len = SHA256_B64_LEN;
    else if(ctx->hmac_type == FKO_HMAC_SHA384)
        hmac_b64_digest_len = SHA384_B64_LEN;
    else if(ctx->hmac_type == FKO_HMAC_SHA512)
        hmac_b64_digest_len = SHA512_B64_LEN;
    else
        return(FKO_ERROR_UNSUPPORTED_HMAC_MODE);

    if((ctx->encrypted_msg_len - hmac_b64_digest_len)
            < MIN_SPA_ENCODED_MSG_SIZE)
        return(FKO_ERROR_INVALID_DATA_HMAC_ENCMSGLEN_VALIDFAIL);

    /* Get digest value
    */
    hmac_digest_from_data = strndup((ctx->encrypted_msg
            + ctx->encrypted_msg_len - hmac_b64_digest_len),
            hmac_b64_digest_len);

    if(hmac_digest_from_data == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    /* Now we chop the HMAC digest off of the encrypted msg
    */
    tbuf = strndup(ctx->encrypted_msg,
            ctx->encrypted_msg_len - hmac_b64_digest_len);

    if(tbuf == NULL)
    {
        if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
                MAX_SPA_ENCODED_MSG_SIZE)) == FKO_SUCCESS)
            return(FKO_ERROR_MEMORY_ALLOCATION);
        else
            return(FKO_ERROR_ZERO_OUT_DATA);
    }

    if(zero_free(ctx->encrypted_msg, ctx->encrypted_msg_len) != FKO_SUCCESS)
        zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;

    ctx->encrypted_msg      = tbuf;
    ctx->encrypted_msg_len -= hmac_b64_digest_len;

    if(ctx->encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
    {
        /* See if we need to add the "hQ" string to the front of the
         * encrypted data.
         */
        if(! ctx->added_gpg_prefix)
        {
            res = add_gpg_prefix(ctx);
        }
    }
    else
    {
        /* See if we need to add the "Salted__" string to the front of the
         * encrypted data.
         */
        if(! ctx->added_salted_str)
        {
            res = add_salted_str(ctx);
        }
    }

    if (res != FKO_SUCCESS)
    {
        if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
                        MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
            zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;

        if(zero_free_rv == FKO_SUCCESS)
            return(res);
        else
            return(zero_free_rv);
    }

    /* Calculate the HMAC from the encrypted data and then
     * compare
    */
    res = fko_set_spa_hmac_type(ctx, ctx->hmac_type);
    if(res == FKO_SUCCESS)
    {
        res = fko_set_spa_hmac(ctx, hmac_key, hmac_key_len);

        if(res == FKO_SUCCESS)
        {
            if(constant_runtime_cmp(hmac_digest_from_data,
                    ctx->msg_hmac, hmac_b64_digest_len) != 0)
            {
                res = FKO_ERROR_INVALID_DATA_HMAC_COMPAREFAIL;
            }
        }
    }

    if(zero_free(hmac_digest_from_data, strnlen(hmac_digest_from_data,
                    MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
        zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;

    if(res == FKO_SUCCESS)
        return(zero_free_rv);
    else
        return(res);
}
Example #4
0
/* Prompt for and receive a user password.
*/
static int
get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
    char *key, int *key_len, char *hmac_key, int *hmac_key_len)
{
#if !AFL_FUZZING
    char   *key_tmp = NULL, *hmac_key_tmp = NULL;
#endif
    int     use_hmac = 0, res = 0;

    memset(key, 0x0, MAX_KEY_LEN+1);
    memset(hmac_key, 0x0, MAX_KEY_LEN+1);

    if(options->have_key)
    {
        strlcpy(key, options->key, MAX_KEY_LEN+1);
        *key_len = strlen(key);
    }
    else if(options->have_base64_key)
    {
        *key_len = fko_base64_decode(options->key_base64,
                (unsigned char *) options->key);
        if(*key_len > 0 && *key_len < MAX_KEY_LEN)
        {
            memcpy(key, options->key, *key_len);
        }
        else
        {
            log_msg(LOG_VERBOSITY_ERROR, "[*] Invalid key length: '%d', must be in [1,%d]",
                    *key_len, MAX_KEY_LEN);
            return 0;
        }
    }
    else
    {
        /* If --get-key file was specified grab the key/password from it.
        */
        if(options->get_key_file[0] != 0x0)
        {
            if(get_key_file(key, key_len, options->get_key_file, ctx, options) != 1)
            {
                return 0;
            }
        }
        else if(options->use_gpg)
        {
            if(options->use_gpg_agent)
                log_msg(LOG_VERBOSITY_NORMAL,
                    "[+] GPG mode set, signing passphrase acquired via gpg-agent");
            else if(options->gpg_no_signing_pw)
                log_msg(LOG_VERBOSITY_NORMAL,
                    "[+] GPG mode set, signing passphrase not required");
            else if(strlen(options->gpg_signer_key))
            {
#if AFL_FUZZING
                strlcpy(key, AFL_ENC_KEY, MAX_KEY_LEN+1);
#else
                key_tmp = getpasswd("Enter passphrase for signing: ", options->input_fd);
                if(key_tmp == NULL)
                {
                    log_msg(LOG_VERBOSITY_ERROR, "[*] getpasswd() key error.");
                    return 0;
                }
                strlcpy(key, key_tmp, MAX_KEY_LEN+1);
#endif
                *key_len = strlen(key);
            }
        }
        else
        {
#if AFL_FUZZING
            strlcpy(key, AFL_ENC_KEY, MAX_KEY_LEN+1);
#else
            key_tmp = getpasswd("Enter encryption key: ", options->input_fd);
            if(key_tmp == NULL)
            {
                log_msg(LOG_VERBOSITY_ERROR, "[*] getpasswd() key error.");
                return 0;
            }
            strlcpy(key, key_tmp, MAX_KEY_LEN+1);
#endif
            *key_len = strlen(key);
        }
    }

    if(options->have_hmac_key)
    {
        strlcpy(hmac_key, options->hmac_key, MAX_KEY_LEN+1);
        *hmac_key_len = strlen(hmac_key);
        use_hmac = 1;
    }
    else if(options->have_hmac_base64_key)
    {
        *hmac_key_len = fko_base64_decode(options->hmac_key_base64,
            (unsigned char *) options->hmac_key);
        if(*hmac_key_len > MAX_KEY_LEN || *hmac_key_len < 0)
        {
            log_msg(LOG_VERBOSITY_ERROR,
                    "[*] Invalid decoded key length: '%d', must be in [0,%d]",
                    *hmac_key_len, MAX_KEY_LEN);
            return 0;
        }
        memcpy(hmac_key, options->hmac_key, *hmac_key_len);
        use_hmac = 1;
    }
    else if (options->use_hmac)
    {
        /* If --get-key file was specified grab the key/password from it.
        */
        if(options->get_hmac_key_file[0] != 0x0)
        {
            if(get_key_file(hmac_key, hmac_key_len,
                options->get_hmac_key_file, ctx, options) != 1)
            {
                return 0;
            }
            use_hmac = 1;
        }
        else
        {
#if AFL_FUZZING
            strlcpy(hmac_key, AFL_HMAC_KEY, MAX_KEY_LEN+1);
#else
            hmac_key_tmp = getpasswd("Enter HMAC key: ", options->input_fd);
            if(hmac_key_tmp == NULL)
            {
                log_msg(LOG_VERBOSITY_ERROR, "[*] getpasswd() key error.");
                return 0;
            }
            strlcpy(hmac_key, hmac_key_tmp, MAX_KEY_LEN+1);
#endif
            *hmac_key_len = strlen(hmac_key);
            use_hmac = 1;
        }
    }

    if (use_hmac)
    {
        if(*hmac_key_len < 0 || *hmac_key_len > MAX_KEY_LEN)
        {
            log_msg(LOG_VERBOSITY_ERROR, "[*] Invalid HMAC key length: '%d', must be in [0,%d]",
                    *hmac_key_len, MAX_KEY_LEN);
            return 0;
        }

        /* Make sure the same key is not used for both encryption and the HMAC
        */
        if(*hmac_key_len == *key_len)
        {
            if(memcmp(hmac_key, key, *key_len) == 0)
            {
                log_msg(LOG_VERBOSITY_ERROR,
                    "[*] The encryption passphrase and HMAC key should not be identical, no SPA packet sent. Exiting.");
                return 0;
            }
        }

        res = fko_set_spa_hmac_type(ctx, options->hmac_type);
        if(res != FKO_SUCCESS)
        {
            errmsg("fko_set_spa_hmac_type", res);
            return 0;
        }
    }

    return 1;
}
Example #5
0
/* JNI interface: constructs arguments and calls main function
*/
jstring Java_biz_incomsystems_fwknop2_SendSPA_sendSPAPacket(JNIEnv* env,
        jobject thiz)
{
    fko_ctx_t ctx;
    fwknop_options_t opts;

    int res, hmac_str_len = 0;
    short message_type;
    short digest_type = FKO_DIGEST_SHA256;
    short hmac_type = FKO_HMAC_SHA256;
    int key_len, hmac_key_len;
    char res_msg[MSG_BUFSIZE+1] = {0};
    char spa_msg[MSG_BUFSIZE+1] = {0};
    char nat_msg[MSG_BUFSIZE+1] = {0};
    jstring ourSpa;
    char *key_tmp[MAX_KEY_LEN+1] = {0}, *hmac_key_tmp[MAX_KEY_LEN+1] = {0};


    LOGV("**** Init fwknop ****");

    memset(&opts, 0, sizeof(fwknop_options_t));

    /* Read the member values from the Java Object that called sendSPAPacket() method
    */
    jclass c = (*env)->GetObjectClass(env,thiz);
    jfieldID fid = (*env)->GetFieldID(env, c, "access_str", "Ljava/lang/String;");
    jstring jaccess = (*env)->GetObjectField(env, thiz, fid);
    const char *access_str = (*env)->GetStringUTFChars(env, jaccess, 0);

    fid = (*env)->GetFieldID(env, c, "allowip_str", "Ljava/lang/String;");
    jstring jallowip = (*env)->GetObjectField(env, thiz, fid);
    const char *allowip_str = (*env)->GetStringUTFChars(env, jallowip, 0);

    fid = (*env)->GetFieldID(env, c, "passwd_str", "Ljava/lang/String;");
    jstring jpasswd = (*env)->GetObjectField(env, thiz, fid);
    char *passwd_str = (*env)->GetStringUTFChars(env, jpasswd, 0);

    fid = (*env)->GetFieldID(env, c, "passwd_b64", "Ljava/lang/String;");
    jstring jpasswd_b64 = (*env)->GetObjectField(env, thiz, fid);
    const char *passwd_b64 = (*env)->GetStringUTFChars(env, jpasswd_b64, 0);

    fid = (*env)->GetFieldID(env, c, "digest_type", "Ljava/lang/String;");
    jstring jdigest_type = (*env)->GetObjectField(env, thiz, fid);
    char *set_digest_type = (*env)->GetStringUTFChars(env, jdigest_type, 0);

    fid = (*env)->GetFieldID(env, c, "hmac_str", "Ljava/lang/String;");
    jstring jhmac = (*env)->GetObjectField(env, thiz, fid);
    char *hmac_str = (*env)->GetStringUTFChars(env, jhmac, 0);

    fid = (*env)->GetFieldID(env, c, "hmac_b64", "Ljava/lang/String;");
    jstring jhmac_b64 = (*env)->GetObjectField(env, thiz, fid);
    const char *hmac_b64 = (*env)->GetStringUTFChars(env, jhmac_b64, 0);

    fid = (*env)->GetFieldID(env, c, "hmac_type", "Ljava/lang/String;");
    jstring jhmac_type = (*env)->GetObjectField(env, thiz, fid);
    char *set_hmac_type = (*env)->GetStringUTFChars(env, jhmac_type, 0);

    fid = (*env)->GetFieldID(env, c, "fw_timeout_str", "Ljava/lang/String;");
    jstring jfwtimeout = (*env)->GetObjectField(env, thiz, fid);
    const char *fw_timeout_str = (*env)->GetStringUTFChars(env, jfwtimeout, 0);

    fid = (*env)->GetFieldID(env, c, "nat_access_str", "Ljava/lang/String;");
    jstring jnat_access_str = (*env)->GetObjectField(env, thiz, fid);
    const char *nat_access_str = (*env)->GetStringUTFChars(env, jnat_access_str, 0);

    fid = (*env)->GetFieldID(env, c, "nat_local", "Ljava/lang/String;");
    jstring jnat_local = (*env)->GetObjectField(env, thiz, fid);
    const char *nat_local = (*env)->GetStringUTFChars(env, jnat_local, 0);

    fid = (*env)->GetFieldID(env, c, "server_cmd_str", "Ljava/lang/String;");
    jstring jserver_cmd = (*env)->GetObjectField(env, thiz, fid);
    const char *server_cmd_str = (*env)->GetStringUTFChars(env, jserver_cmd, 0);

    fid = (*env)->GetFieldID(env, c, "legacy", "Ljava/lang/String;");
    jstring jlegacy = (*env)->GetObjectField(env, thiz, fid);
    const char *legacy = (*env)->GetStringUTFChars(env, jlegacy, 0);

    /* Sanity checks
    */
    if(access_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing access string");
        goto cleanup2;
    }
    if(allowip_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing allow IP");
        goto cleanup2;
    }
    if(passwd_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing password");
        goto cleanup2;
    }
    if(fw_timeout_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing firewall timeout value");
        goto cleanup2;
    }

    if(hmac_str != NULL) {
        hmac_str_len = (int)strlen(hmac_str);
    }
    key_len = (int)strlen(passwd_str);
    if(legacy == NULL) {
    sprintf(legacy, "false");
    }


    if(strcmp(hmac_b64, "true") == 0) {
        hmac_str_len = fko_base64_decode( hmac_str,
                                (unsigned char *)hmac_key_tmp);
        if(hmac_str_len > MAX_KEY_LEN || hmac_str_len < 0)
        {
            LOGV("[*] Invalid key length: '%d', must be in [1,%d]",
                    hmac_str_len, MAX_KEY_LEN);
            goto cleanup2;
        }
        else
        {
            memcpy(hmac_str, hmac_key_tmp, hmac_str_len);
        }
    }

    if(strcmp(passwd_b64, "true") == 0) {
        LOGV("Detected key b64");
        key_len = fko_base64_decode(passwd_str,
                        (unsigned char *)key_tmp);
        if(key_len > MAX_KEY_LEN || key_len < 0)
        {
            LOGV( "[*] Invalid key length: '%d', must be in [1,%d]",
                    key_len, MAX_KEY_LEN);
            goto cleanup2;
        }
        else
        {
            memcpy(passwd_str, key_tmp, key_len);
        }
    }
    /* Using an HMAC is optional in the pre-rfc mode.
    */

    if (server_cmd_str[0] != 0x0) {
        message_type = FKO_COMMAND_MSG;
    } else {
        message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
    }

    /* Intialize the context
    */
    res = fko_new(&ctx);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Unable to create FKO context", res));
        goto cleanup2;
    }

    /* Set server command
        */

    if (server_cmd_str[0] != 0x0) {
        message_type = FKO_COMMAND_MSG;
        fko_set_spa_message_type(ctx, message_type);
        res = fko_set_spa_message(ctx, server_cmd_str);
            if (res != FKO_SUCCESS) {
                strcpy(res_msg, fko_errmsg("Error setting SPA request message", res));
                goto cleanup;
            }
    } else {

        /* Set client timeout
        */
        res = fko_set_spa_client_timeout(ctx, atoi(fw_timeout_str));
        if (res != FKO_SUCCESS) {
            strcpy(res_msg, fko_errmsg("Error setting FW timeout", res));
            goto cleanup;
        }

        /* Set the spa message string
        */
        snprintf(spa_msg, MSG_BUFSIZE, "%s,%s", allowip_str, access_str);

        res = fko_set_spa_message(ctx, spa_msg);
        if (res != FKO_SUCCESS) {
            strcpy(res_msg, fko_errmsg("Error setting SPA request message", res));
            goto cleanup;
        }
    }

    /* Set the HMAC mode if necessary
    */
    if (strcmp(legacy, "true") == 0) {
        res = fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_CBC_LEGACY_IV);
        if (key_len > 16) {
            key_len = 16;
        }
    }


    if (hmac_str_len > 0) {
        if (strcmp(set_hmac_type, "MD5") == 0) {
            hmac_type = FKO_HMAC_MD5;
        } else if (strcmp(set_hmac_type, "SHA1") == 0) {
            hmac_type = FKO_HMAC_SHA1;
        } else if (strcmp(set_hmac_type, "SHA256") == 0) {
            hmac_type = FKO_HMAC_SHA256;
        } else if (strcmp(set_hmac_type, "SHA384") == 0) {
            hmac_type = FKO_HMAC_SHA384;
        } else if (strcmp(set_hmac_type, "SHA512") == 0) {
            hmac_type = FKO_HMAC_SHA512;
        }

        res = fko_set_spa_hmac_type(ctx, hmac_type);
        if (res != FKO_SUCCESS) {
            strcpy(res_msg, fko_errmsg("Error setting SPA HMAC type", res));
            goto cleanup;
        }
    }



    /* Set Nat
    */
    if (nat_access_str[0] != 0x0){
        // if nat_access_str is not blank, push it into fko context
        if (strncmp(nat_local, "true", 4) == 0) {
            message_type = FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG;
            fko_set_spa_message_type(ctx, message_type);
            LOGV("Finished setting local-nat.");
        }
        res = fko_set_spa_nat_access(ctx, nat_access_str);
        if (res != FKO_SUCCESS) {
                    strcpy(res_msg, fko_errmsg("Error setting NAT string", res));
                    goto cleanup;
                }
    }
    LOGV("Setting digest type to %s.", set_digest_type);
    if (strcmp(set_digest_type, "MD5") == 0) {
        digest_type = FKO_HMAC_MD5;
    } else if (strcmp(set_digest_type, "SHA1") == 0) {
        digest_type = FKO_HMAC_SHA1;
    } else if (strcmp(set_digest_type, "SHA256") == 0) {
        digest_type = FKO_HMAC_SHA256;
    } else if (strcmp(set_digest_type, "SHA384") == 0) {
        digest_type = FKO_HMAC_SHA384;
    } else if (strcmp(set_digest_type, "SHA512") == 0) {
        digest_type = FKO_HMAC_SHA512;
    }
    res = fko_set_spa_digest_type(ctx, digest_type);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error setting SPA digest type", res));
        goto cleanup;
    }
    LOGV("Finished setting digest type.");


    /* Finalize the context data (Encrypt and encode).
    */
    res = fko_spa_data_final(ctx, (char*)passwd_str,
            key_len, (char *)hmac_str, hmac_str_len);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error generating SPA data", res));
        goto cleanup;
    }
    LOGV("Finished finalize.");

    res = fko_get_spa_data(ctx, &opts.spa_data);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error getting SPA data", res));
        goto cleanup;
    }


    /* Generate the spa data packet
    */
    ourSpa = (*env)->NewStringUTF(env, opts.spa_data);

cleanup:
    /* Release the resources used by the fko context.
    */
    fko_destroy(ctx);

cleanup2:
    /* Release mem
    */
    (*env)->ReleaseStringUTFChars(env, jaccess, access_str);
    (*env)->ReleaseStringUTFChars(env, jallowip, allowip_str);
    (*env)->ReleaseStringUTFChars(env, jpasswd, passwd_str);
    (*env)->ReleaseStringUTFChars(env, jpasswd_b64, passwd_b64);
    (*env)->ReleaseStringUTFChars(env, jdigest_type, set_digest_type);
    (*env)->ReleaseStringUTFChars(env, jhmac, hmac_str);
    (*env)->ReleaseStringUTFChars(env, jhmac_b64, hmac_b64);
    (*env)->ReleaseStringUTFChars(env, jhmac_type, set_hmac_type);
    (*env)->ReleaseStringUTFChars(env, jfwtimeout, fw_timeout_str);
    (*env)->ReleaseStringUTFChars(env, jnat_access_str, nat_access_str);
    (*env)->ReleaseStringUTFChars(env, jnat_local, nat_local);
    return ourSpa;
}
Example #6
0
static void
test_loop_compounded(void)
{
    fko_ctx_t  ctx = NULL, decrypt_ctx = NULL;
    char *spa_data = NULL;
    int i, j, k, l, res;

    for (i=0; i<FCN_CALLS; i++) {

        fko_new(&ctx);

        res = fko_set_spa_client_timeout(ctx, i);
        if (res != FKO_SUCCESS)
            printf("fko_set_spa_client_timeout(): %s\n", fko_errstr(res));

        for (j=-1; j<FKO_LAST_MSG_TYPE+1; j++) {

            res = fko_set_spa_message_type(ctx, j);
            if (res != FKO_SUCCESS)
                printf("fko_set_spa_message_type(): %s\n", fko_errstr(res));

            res = fko_set_timestamp(ctx, 100);
            if (res != FKO_SUCCESS)
                printf("fko_set_timestamp(): %s\n", fko_errstr(res));

            fko_set_spa_message(ctx, "1.1.1.1,tcp/22");
            res = fko_set_spa_message(ctx, "123.123.123.123,tcp/22");
            if (res != FKO_SUCCESS)
                printf("fko_set_spa_message(): %s\n", fko_errstr(res));

            res = fko_set_spa_nat_access(ctx, "1.2.3.4,1234");
            if (res != FKO_SUCCESS)
                printf("fko_set_spa_nat_access(): %s\n", fko_errstr(res));

            res = fko_set_username(ctx, "someuser");
            if (res != FKO_SUCCESS)
                printf("fko_set_username(): %s\n", fko_errstr(res));

            res = fko_set_spa_server_auth(ctx, "passwd");
            if (res != FKO_SUCCESS)
                printf("fko_set_spa_server_auth(): %s\n", fko_errstr(res));

            res = fko_set_spa_hmac_type(ctx, FKO_HMAC_SHA256);
            if (res != FKO_SUCCESS)
                printf("fko_set_spa_hmac_type(): %s\n", fko_errstr(res));

            for (k=-4; k<=16; k+=4) {
                for (l=-4; l<=16; l+=4) {

                    res = fko_spa_data_final(ctx, ENC_KEY, k, HMAC_KEY, l);
                    if (res == FKO_SUCCESS) {
                        res = fko_get_spa_data(ctx, &spa_data);
                        if (res == FKO_SUCCESS) {

                            res = fko_new_with_data(&decrypt_ctx, spa_data, NULL,
                                0, FKO_ENC_MODE_CBC, HMAC_KEY, l, FKO_HMAC_SHA256);

                            if (res == FKO_SUCCESS) {
                                res = fko_decrypt_spa_data(decrypt_ctx, ENC_KEY, k);
                                if (res != FKO_SUCCESS)
                                    printf("fko_decrypt_spa_data(): %s\n", fko_errstr(res));

                                fko_destroy(decrypt_ctx);
                                decrypt_ctx = NULL;
                                spa_calls += 13;
                                spa_compounded_calls += 13;

                            } else {
                                printf("fko_new_with_data(): %s\n", fko_errstr(res));
                            }
                        } else {
                            printf("fko_get_spa_data(): %s\n", fko_errstr(res));
                        }

                    } else {
                        printf("fko_spa_data_final(): %s\n", fko_errstr(res));
                    }
                }
            }
        }
        fko_destroy(ctx);
        ctx = NULL;

        spa_calls += 3;
        spa_compounded_calls += 3;
    }
}
Example #7
0
wxString Config::gen_SPA(wxString ip_resolver_url, wxString gpgEngine, wxString gpgHomeFolder, bool debug)
{
    CURLcode curl_Res;
    fko_ctx_t ctx;
    fwknop_options_t opts;
    int key_len = 0;
    int res;
    int hmac_str_len = 0;
    short message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
    short digest_type = FKO_DIGEST_SHA256;
    short hmac_type = FKO_HMAC_SHA256;
    char key_str[129] = {0}, hmac_str[129] = {0};
    char spa_msg[256] = {0};
//    char spa_buf[4096] = {0};
//    char * spa_buf_ptr;
//    char crypt_buf[4096] = {0};
    char nat_access_str[25] = {0};
//    char * hmac_buf;
//    char * spa_digest_ptr;


    memset(&opts, 0, sizeof(fwknop_options_t));

    if (this->KEY.IsEmpty() && !this->USE_GPG_CRYPT)
        return _("Key cannot be blank!");

    wxBusyInfo wait(_("Please wait, working..."));
    if (this->SERVER_PORT.CmpNoCase(wxT("random")) == 0)
    {
        srand((int)wxGetLocalTime());
        this->SERVER_PORT.Empty();
        this->SERVER_PORT << (rand()%55535 + 10000); // do this better, this isn't a horribly good random function
    }
    if (this->ACCESS_IP.CmpNoCase(wxT("Source IP")) == 0)
        this->ACCESS_IP = wxT("0.0.0.0");
    else if (this->ACCESS_IP.CmpNoCase(wxT("Resolve IP")) == 0)
    {
        std::ostringstream oss;
        curl_Res = curl_read(std::string(ip_resolver_url.mb_str()), oss);
        if (curl_Res == CURLE_OK)
        {
            wxString result_tmp = wxString::FromUTF8(oss.str().c_str());
            wxRegEx findIP( wxT("(([0-9]{1}|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]{1}|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])"));
            if (!findIP.Matches(result_tmp))
                return _("Unable to resolve our IP!");

            this->ACCESS_IP = findIP.GetMatch(result_tmp);
        } else
            return _("Libcurl returned the error: ") + wxString::FromUTF8(curl_easy_strerror(curl_Res));

    } //end resolve ip
    if (fko_new(&ctx) != FKO_SUCCESS)
        return _("Could not get new FKO context");

    if (USE_GPG_CRYPT) {
        fko_set_spa_encryption_type(ctx, FKO_ENCRYPTION_GPG);
        fko_set_gpg_exe(ctx, gpgEngine.mb_str());
        fko_set_gpg_home_dir(ctx, gpgHomeFolder.mb_str());


        fko_set_gpg_recipient(ctx, GPG_CRYPT_ID.mb_str());
        if (GPG_SIG_ID.CmpNoCase(_("None")) != 0)
        fko_set_gpg_signer(ctx, GPG_SIG_ID.mb_str());



        fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_ASYMMETRIC);

    } else {
        if (this->KEY_BASE64)
        {
            key_len = fko_base64_decode(this->KEY.mb_str(), (unsigned char *)key_str);
        } else {
            strncpy(key_str, (const char*)this->KEY.mb_str(wxConvUTF8), 128);
            key_len = (int)strlen(key_str);
        }
    }

    if (this->HMAC_BASE64)
    {
        hmac_str_len = fko_base64_decode(this->HMAC.mb_str(), (unsigned char *)hmac_str);
    } else {
        strncpy(hmac_str, (const char*)this->HMAC.mb_str(wxConvUTF8), 128);
        hmac_str_len = (int)strlen(hmac_str);
    }



    if (MESS_TYPE.CmpNoCase(wxT("Server Command")) == 0)
    {
        message_type = FKO_COMMAND_MSG;
        if (fko_set_spa_message_type(ctx, message_type) != FKO_SUCCESS)
            return _("Could not set message type");

        snprintf(spa_msg, 256, "%s,%s", (const char*)this->ACCESS_IP.mb_str(wxConvUTF8), (const char*)this->SERVER_CMD.mb_str(wxConvUTF8));
        res = fko_set_spa_message(ctx, spa_msg);
        if (res != FKO_SUCCESS)
            return _("Could not set command message");

    } else {
        if (fko_set_spa_client_timeout(ctx, wxAtoi(this->SERVER_TIMEOUT)) != FKO_SUCCESS)
            return _("Could not set SPA timeout");

        snprintf(spa_msg, 256, "%s,%s", (const char*)this->ACCESS_IP.mb_str(wxConvUTF8), (const char*)this->PORTS.mb_str(wxConvUTF8));
        if (fko_set_spa_message(ctx, spa_msg) != FKO_SUCCESS)
            return _("Could not set SPA Message");

    }
    if (this->LEGACY) { // technically should trim hmac keys
        if (fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_CBC_LEGACY_IV) != FKO_SUCCESS)
            return _("Could not set Legacy mode.");

    }
    if (!this->HMAC.IsEmpty()){
        if (this->HMAC_TYPE.CmpNoCase(wxT("MD5"))==0)
            hmac_type = FKO_HMAC_MD5;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA1"))==0)
            hmac_type = FKO_HMAC_SHA1;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA256"))==0)
            hmac_type = FKO_HMAC_SHA256;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA384"))==0)
            hmac_type = FKO_HMAC_SHA384;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA512"))==0)
            hmac_type = FKO_HMAC_SHA512;
        if (fko_set_spa_hmac_type(ctx, hmac_type) != FKO_SUCCESS)
            return _("Could not set HMAC type.");

    }
    if (this->MESS_TYPE.CmpNoCase(wxT("Nat Access")) == 0)
    {
        sprintf(nat_access_str, "%s,%s", (const char*)this->NAT_IP.mb_str(wxConvUTF8), (const char*)this->NAT_PORT.mb_str(wxConvUTF8));
        if (fko_set_spa_nat_access(ctx, nat_access_str) != FKO_SUCCESS)
            return _("Could not set nat access string.");

    } else if (this->MESS_TYPE.CmpNoCase(wxT("Local Nat Access")) == 0) {
        message_type = FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG;
        if (fko_set_spa_message_type(ctx, message_type) != FKO_SUCCESS)
        return _("Chould not set message type");
        sprintf(nat_access_str, "%s,%s", (const char*)this->SERVER_IP.mb_str(wxConvUTF8), (const char*)this->NAT_PORT.mb_str(wxConvUTF8));
        if (fko_set_spa_nat_access(ctx, nat_access_str) != FKO_SUCCESS)
            return _("Could not set nat access string.");
    }
    if (this->DIGEST_TYPE.CmpNoCase(wxT("MD5"))==0)
        digest_type = FKO_DIGEST_MD5;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA1"))==0)
        digest_type = FKO_DIGEST_SHA1;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA256"))==0)
        digest_type = FKO_DIGEST_SHA256;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA384"))==0)
        digest_type = FKO_DIGEST_SHA384;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA512"))==0)
        digest_type = FKO_DIGEST_SHA512;
    if (fko_set_spa_digest_type(ctx, digest_type) != FKO_SUCCESS)
        return _("Could not set SPA digest type.");
    if (fko_spa_data_final(ctx, key_str, key_len, hmac_str, hmac_str_len) != FKO_SUCCESS)
        return _("Could not generate SPA data.");

    if (fko_get_spa_data(ctx, &opts.spa_data) != FKO_SUCCESS)
        return _("Could not retrieve SPA data.");
   // if (!USE_GPG_CRYPT) {
        this->SPA_STRING = wxString::FromUTF8(opts.spa_data);
    /*} else {  //could retain this for libfko without gpg support
        fko_get_encoded_data(ctx, &spa_buf_ptr);
        fko_get_spa_digest(ctx, &spa_digest_ptr);
        sprintf(spa_buf,"%s:%s", spa_buf_ptr, spa_digest_ptr);
        ourGPG->encryptAndSign(GPG_CRYPT_ID, GPG_SIG_ID, spa_buf, crypt_buf);
        fko_set_spa_data(ctx, crypt_buf);
        fko_set_spa_hmac(ctx, hmac_str, hmac_str_len);
        fko_get_spa_hmac(ctx, &hmac_buf);
        strcat(crypt_buf, hmac_buf);
        this->SPA_STRING = wxString::FromUTF8(crypt_buf + 2);

    }*/

    if (debug) {
        wxTextEntryDialog *debugMessage = new wxTextEntryDialog(NULL, _("Debug info"), _("Debug info"),  "Source IP: " + this->ACCESS_IP +"\n" + "SPA String: " + this->SPA_STRING, wxOK | wxTE_MULTILINE );
        debugMessage->SetSize(620, 320);
        debugMessage->ShowModal();
        debugMessage->Destroy();
    }
    return _("Success");
}
Example #8
0
/* Initialize an fko context with external (encrypted/encoded) data.
 * This is used to create a context with the purpose of decoding
 * and parsing the provided data into the context data.
*/
int
fko_new_with_data(fko_ctx_t *r_ctx, const char * const enc_msg,
    const char * const dec_key, const int dec_key_len,
    int encryption_mode, const char * const hmac_key,
    const int hmac_key_len, const int hmac_type)
{
    fko_ctx_t   ctx = NULL;
    int         res = FKO_SUCCESS; /* Are we optimistic or what? */
    int         enc_msg_len;

#if HAVE_LIBFIU
    fiu_return_on("fko_new_with_data_msg",
            FKO_ERROR_INVALID_DATA_FUNCS_NEW_ENCMSG_MISSING);
#endif

    if(enc_msg == NULL)
        return(FKO_ERROR_INVALID_DATA_FUNCS_NEW_ENCMSG_MISSING);

#if HAVE_LIBFIU
    fiu_return_on("fko_new_with_data_keylen",
            FKO_ERROR_INVALID_KEY_LEN);
#endif

    if(dec_key_len < 0 || hmac_key_len < 0)
        return(FKO_ERROR_INVALID_KEY_LEN);

    ctx = calloc(1, sizeof *ctx);
    if(ctx == NULL)
        return(FKO_ERROR_MEMORY_ALLOCATION);

    enc_msg_len = strnlen(enc_msg, MAX_SPA_ENCODED_MSG_SIZE);

    if(! is_valid_encoded_msg_len(enc_msg_len))
    {
        free(ctx);
        return(FKO_ERROR_INVALID_DATA_FUNCS_NEW_MSGLEN_VALIDFAIL);
    }

    /* First, add the data to the context.
    */
    ctx->encrypted_msg     = strdup(enc_msg);
    ctx->encrypted_msg_len = enc_msg_len;

    if(ctx->encrypted_msg == NULL)
    {
        free(ctx);
        return(FKO_ERROR_MEMORY_ALLOCATION);
    }

    /* Default Encryption Mode (Rijndael in CBC mode)
    */
    ctx->initval = FKO_CTX_INITIALIZED;
    res = fko_set_spa_encryption_mode(ctx, encryption_mode);
    if(res != FKO_SUCCESS)
    {
        fko_destroy(ctx);
        ctx = NULL;
        return res;
    }

    /* HMAC digest type
    */
    res = fko_set_spa_hmac_type(ctx, hmac_type);
    if(res != FKO_SUCCESS)
    {
        fko_destroy(ctx);
        ctx = NULL;
        return res;
    }

    /* Check HMAC if the access stanza had an HMAC key
    */
    if(hmac_key_len > 0 && hmac_key != NULL)
        res = fko_verify_hmac(ctx, hmac_key, hmac_key_len);
    if(res != FKO_SUCCESS)
    {
        fko_destroy(ctx);
        ctx = NULL;
        return res;
    }

    /* Consider it initialized here.
    */
    FKO_SET_CTX_INITIALIZED(ctx);

    /* If a decryption key is provided, go ahead and decrypt and decode.
    */
    if(dec_key != NULL)
    {
        res = fko_decrypt_spa_data(ctx, dec_key, dec_key_len);

        if(res != FKO_SUCCESS)
        {
            fko_destroy(ctx);
            ctx = NULL;
            *r_ctx = NULL; /* Make sure the caller ctx is null just in case */
            return(res);
        }
    }

#if HAVE_LIBGPGME
    /* Set gpg signature verify on.
    */
    ctx->verify_gpg_sigs = 1;

#endif /* HAVE_LIBGPGME */

    *r_ctx = ctx;

    return(res);
}
Example #9
0
wxString Config::gen_SPA(wxString ip_resolver_url)
{
    CURLcode curl_Res;
    fko_ctx_t ctx;
    fwknop_options_t opts;
    int key_len, res;
    int hmac_str_len = 0;
    short message_type = FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG;
    short digest_type = FKO_DIGEST_SHA256;
    short hmac_type = FKO_HMAC_SHA256;
    char key_str[129] = {0}, hmac_str[129] = {0};
    char spa_msg[256] = {0};
    char debug_buf[4096] = {0};
    char nat_access_str[25] = {0};

    memset(&opts, 0, sizeof(fwknop_options_t));

    if (this->KEY.IsEmpty())
        return _("Key cannot be blank!");

    wxBusyInfo wait(_("Please wait, working..."));
    if (this->SERVER_PORT.CmpNoCase(wxT("random")) == 0)
    {
        srand((int)wxGetLocalTime());
        this->SERVER_PORT.Empty();
        this->SERVER_PORT << (rand()%55535 + 10000); // do this better, this isn't a horribly good random function
    }
    if (this->ACCESS_IP.CmpNoCase(wxT("Source IP")) == 0)
        this->ACCESS_IP = wxT("0.0.0.0");
    else if (this->ACCESS_IP.CmpNoCase(wxT("Resolve IP")) == 0)
    {
        std::ostringstream oss;
        curl_Res = curl_read(std::string(ip_resolver_url.mb_str()), oss); //Eventually make this a user definable service.
        if (curl_Res == CURLE_OK)
        {
            wxString result_tmp = wxString::FromUTF8(oss.str().c_str());
            wxRegEx findIP( wxT("(([0-9]{1}|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]{1}|[0-9]{2}|[0-1][0-9]{2}|2[0-4][0-9]|25[0-5])"));
            if (!findIP.Matches(result_tmp))
                return _("Unable to resolve our IP!");

            this->ACCESS_IP = findIP.GetMatch(result_tmp);
        } else
            return _("Libcurl returned the error: ") + wxString::FromUTF8(curl_easy_strerror(curl_Res));

    } //end resolve ip

    if (this->KEY_BASE64)
    {
        key_len = fko_base64_decode(this->KEY.mb_str(), (unsigned char *)key_str);
    } else {
        strncpy(key_str, (const char*)this->KEY.mb_str(wxConvUTF8), 128);
        key_len = (int)strlen(key_str);
    }

    if (this->HMAC_BASE64)
    {
        hmac_str_len = fko_base64_decode(this->HMAC.mb_str(), (unsigned char *)hmac_str);
    } else {
        strncpy(hmac_str, (const char*)this->HMAC.mb_str(wxConvUTF8), 128);
        hmac_str_len = (int)strlen(hmac_str);
    }

    if (fko_new(&ctx) != FKO_SUCCESS)
        return _("Could not get new FKO context");

    if (MESS_TYPE.CmpNoCase(wxT("Server Command")) == 0)
    {
        message_type = FKO_COMMAND_MSG;
        if (fko_set_spa_message_type(ctx, message_type) != FKO_SUCCESS)
            return _("Could not set message type");

        snprintf(spa_msg, 256, "%s,%s", (const char*)this->ACCESS_IP.mb_str(wxConvUTF8), (const char*)this->SERVER_CMD.mb_str(wxConvUTF8));
        res = fko_set_spa_message(ctx, spa_msg);
        if (res != FKO_SUCCESS)
            return _("Could not set command message");

    } else {
        if (fko_set_spa_client_timeout(ctx, wxAtoi(this->SERVER_TIMEOUT)) != FKO_SUCCESS)
            return _("Could not set SPA timeout");

        snprintf(spa_msg, 256, "%s,%s", (const char*)this->ACCESS_IP.mb_str(wxConvUTF8), (const char*)this->PORTS.mb_str(wxConvUTF8));
        if (fko_set_spa_message(ctx, spa_msg) != FKO_SUCCESS)
            return _("Could not set SPA Message");

    }
    if (this->LEGACY) { // technically should trim hmac keys
        if (fko_set_spa_encryption_mode(ctx, FKO_ENC_MODE_CBC_LEGACY_IV) != FKO_SUCCESS)
            return _("Could not set Legacy mode.");

    }
    if (!this->HMAC.IsEmpty()){
        if (this->HMAC_TYPE.CmpNoCase(wxT("MD5"))==0)
            hmac_type = FKO_HMAC_MD5;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA1"))==0)
            hmac_type = FKO_HMAC_SHA1;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA256"))==0)
            hmac_type = FKO_HMAC_SHA256;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA384"))==0)
            hmac_type = FKO_HMAC_SHA384;
        else if (this->HMAC_TYPE.CmpNoCase(wxT("SHA512"))==0)
            hmac_type = FKO_HMAC_SHA512;
        if (fko_set_spa_hmac_type(ctx, hmac_type) != FKO_SUCCESS)
            return _("Could not set HMAC type.");

    }
    if (this->MESS_TYPE.CmpNoCase(wxT("Nat Access")) == 0)
    {
        sprintf(nat_access_str, "%s,%s", (const char*)this->NAT_IP.mb_str(wxConvUTF8), (const char*)this->NAT_PORT.mb_str(wxConvUTF8));
        if (fko_set_spa_nat_access(ctx, nat_access_str) != FKO_SUCCESS)
            return _("Could not set nat access string.");

    } else if (this->MESS_TYPE.CmpNoCase(wxT("Local Nat Access")) == 0) {
        message_type = FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG;
        if (fko_set_spa_message_type(ctx, message_type) != FKO_SUCCESS)
        return _("Chould not set message type");
        sprintf(nat_access_str, "%s,%s", (const char*)this->SERVER_IP.mb_str(wxConvUTF8), (const char*)this->NAT_PORT.mb_str(wxConvUTF8));
        if (fko_set_spa_nat_access(ctx, nat_access_str) != FKO_SUCCESS)
            return _("Could not set nat access string.");
    }
    if (this->DIGEST_TYPE.CmpNoCase(wxT("MD5"))==0)
        digest_type = FKO_DIGEST_MD5;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA1"))==0)
        digest_type = FKO_DIGEST_SHA1;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA256"))==0)
        digest_type = FKO_DIGEST_SHA256;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA384"))==0)
        digest_type = FKO_DIGEST_SHA384;
    else if (this->DIGEST_TYPE.CmpNoCase(wxT("SHA512"))==0)
        digest_type = FKO_DIGEST_SHA512;
    if (fko_set_spa_digest_type(ctx, digest_type) != FKO_SUCCESS)
        return _("Could not set SPA digest type.");

    if (fko_spa_data_final(ctx, key_str, key_len, hmac_str, hmac_str_len) != FKO_SUCCESS)
        return _("Could not generate SPA data.");

    if (fko_get_spa_data(ctx, &opts.spa_data) != FKO_SUCCESS)
        return _("Could not retrieve SPA data.");

    //dump_ctx_to_buffer(ctx, debug_buf, sizeof(debug_buf));

    this->SPA_STRING = wxString::FromUTF8(opts.spa_data);
    return _("Success");
}
Example #10
0
/* JNI interface: constructs arguments and calls main function
*/
jstring Java_com_max2idea_android_fwknop_Fwknop_sendSPAPacket(JNIEnv* env,
        jobject thiz)
{
    fko_ctx_t ctx;
    fwknop_options_t opts;

    int res, hmac_str_len = 0;
    char res_msg[MSG_BUFSIZE+1] = {0};
    char spa_msg[MSG_BUFSIZE+1] = {0};

    LOGV("**** Init fwknop ****");

    memset(&opts, 0, sizeof(fwknop_options_t));

    /* Read the member values from the Java Object that called sendSPAPacket() method
    */
    jclass c = (*env)->GetObjectClass(env, thiz);
    jfieldID fid = (*env)->GetFieldID(env, c, "access_str", "Ljava/lang/String;");
    jstring jaccess = (*env)->GetObjectField(env, thiz, fid);
    const char *access_str = (*env)->GetStringUTFChars(env, jaccess, 0);

    fid = (*env)->GetFieldID(env, c, "allowip_str", "Ljava/lang/String;");
    jstring jallowip = (*env)->GetObjectField(env, thiz, fid);
    const char *allowip_str = (*env)->GetStringUTFChars(env, jallowip, 0);

    fid = (*env)->GetFieldID(env, c, "destip_str", "Ljava/lang/String;");
    jstring jdestip = (*env)->GetObjectField(env, thiz, fid);
    const char *destip_str = (*env)->GetStringUTFChars(env, jdestip, 0);

    fid = (*env)->GetFieldID(env, c, "passwd_str", "Ljava/lang/String;");
    jstring jpasswd = (*env)->GetObjectField(env, thiz, fid);
    const char *passwd_str = (*env)->GetStringUTFChars(env, jpasswd, 0);

    fid = (*env)->GetFieldID(env, c, "hmac_str", "Ljava/lang/String;");
    jstring jhmac = (*env)->GetObjectField(env, thiz, fid);
    const char *hmac_str = (*env)->GetStringUTFChars(env, jhmac, 0);

    fid = (*env)->GetFieldID(env, c, "fw_timeout_str", "Ljava/lang/String;");
    jstring jfwtimeout = (*env)->GetObjectField(env, thiz, fid);
    const char *fw_timeout_str = (*env)->GetStringUTFChars(env, jfwtimeout, 0);

    /* Sanity checks
    */
    if(access_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing access string");
        goto cleanup2;
    }
    if(allowip_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing allow IP");
        goto cleanup2;
    }
    if(destip_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing destination IP");
        goto cleanup2;
    }
    if(passwd_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing password");
        goto cleanup2;
    }
    if(fw_timeout_str == NULL) {
        sprintf(res_msg, "Error: Invalid or missing firewall timeout value");
        goto cleanup2;
    }

    /* Using an HMAC is optional (currently)
    */
    if(hmac_str != NULL) {
        hmac_str_len = (int)strlen(hmac_str);
    }

    /* Set our spa server info
    */
    opts.spa_server_str = (char*)destip_str;
    opts.spa_dst_port   = FKO_DEFAULT_PORT; /* Until we make this settable. */

    /* Intialize the context
    */
    res = fko_new(&ctx);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Unable to create FKO context", res));
        goto cleanup2;
    }

    /* Set client timeout
    */
    res = fko_set_spa_client_timeout(ctx, atoi(fw_timeout_str));
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error setting FW timeout", res));
        goto cleanup;
    }

    /* Set the spa message string
    */
    snprintf(spa_msg, MSG_BUFSIZE, "%s,%s", allowip_str, access_str);

    res = fko_set_spa_message(ctx, spa_msg);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error setting SPA request message", res));
        goto cleanup;
    }

    /* Set the HMAC mode if necessary
    */
    if (hmac_str_len > 0) {
        res = fko_set_spa_hmac_type(ctx, FKO_DEFAULT_HMAC_MODE);
        if (res != FKO_SUCCESS) {
            strcpy(res_msg, fko_errmsg("Error setting SPA HMAC type", res));
            goto cleanup;
        }
    }

    /* Finalize the context data (Encrypt and encode).
    */
    res = fko_spa_data_final(ctx, (char*)passwd_str,
            (int)strlen(passwd_str), (char *)hmac_str, hmac_str_len);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error generating SPA data", res));
        goto cleanup;
    }

    res = fko_get_spa_data(ctx, &opts.spa_data);
    if (res != FKO_SUCCESS) {
        strcpy(res_msg, fko_errmsg("Error getting SPA data", res));
        goto cleanup;
    }

    /* --DSS NOTE:  At this point, we could just return the SPA data
     *              to the caller and use the Java network libs to send
     *              the packet and eliminate the spa_comm code altogether.
    */

    /* Send the spa data packet
    */
    res = send_spa_packet(&opts);

    if (res < 0) {
        sprintf(res_msg, "Error: send_spa_packet: packet not sent.");
    } else if (res == 0) {
        sprintf(res_msg, "Error: send_spa_packet: Empty packet sent.");
    } else {
        sprintf(res_msg, "SPA Packet sent successfully.");
    }

cleanup:
    /* Release the resources used by the fko context.
    */
    fko_destroy(ctx);

cleanup2:
    /* Release mem
    */
    (*env)->ReleaseStringUTFChars(env, jaccess, access_str);
    (*env)->ReleaseStringUTFChars(env, jallowip, allowip_str);
    (*env)->ReleaseStringUTFChars(env, jdestip, destip_str);
    (*env)->ReleaseStringUTFChars(env, jpasswd, passwd_str);
    (*env)->ReleaseStringUTFChars(env, jhmac, hmac_str);
    (*env)->ReleaseStringUTFChars(env, jfwtimeout, fw_timeout_str);

    /* Log and return a string of success or error message.
     * This can be enhanced semantically with codes.
    */
    LOGV("%s", res_msg);

    return (*env)->NewStringUTF(env, res_msg);
}