From b6bf1d28bf1e13af872585b7f2533727f8762525 Mon Sep 17 00:00:00 2001 From: Damien Stuart Date: Sat, 27 Nov 2010 03:18:58 +0000 Subject: [PATCH] Added the Fko class code to wrap the _fko wrapper around libfko. git-svn-id: file:///home/mbr/svn/fwknop/trunk@303 510a4753-2344-4c79-9c09-4d669213fbeb --- python/README | 44 +++++- python/fko.py | 345 +++++++++++++++++++++++++++++++++++++++++++++ python/fkomodule.c | 8 +- python/setup.py | 5 +- 4 files changed, 394 insertions(+), 8 deletions(-) create mode 100644 python/fko.py diff --git a/python/README b/python/README index c909e18c..d98a55e4 100644 --- a/python/README +++ b/python/README @@ -14,6 +14,46 @@ To build and install the module: * Build with "python setup.py build" * Install with "python setup.py install" -Note: This version is just a plain wrapper around libfko. I do plan to - make a more complete OO Python module that wraps this one. --DSS + +Simple usage example: + +#!/usr/bin/python +# +# Import the Fko class and all constants. +# +from fko import * + +# Create an Fko instance with an empty context. +# +fko = Fko() + +# Set the SPA message (Note: Access request is default if not specified). +# +fko.spa_message("0.0.0.0,tcp/22") + +# Create the final SPA data message string. +# +fko.spa_data_final("mypassword") + +# print the spa message. +# +print fko.spa_data() + +(prints something like this): +81ugT7+dv6p0qKPmFKwZYz9qAtqThBib+mIeZae9FK2UYQF5CNyujAmEH2+0CBxm3DpArlyySWqdfITvmfSBd11XbFPksK3iqWAPR65lVTYXrNywOxVN65Nmm9D0Qzsczx1hkeNg+g8qxecxO1XBc/LdHEa5C0FmI + +# To decode SPA data: +# +fko = Fko("81ugT7+dv6p0qKPmFKwZYz9qAtqThBib+mIeZae9FK2UYQF5CNyujAmEH2+0CBxm3DpArlyySWqdfITvmfSBd11XbFPksK3iqWAPR65lVTYXrNywOxVN65Nmm9D0Qzsczx1hkeNg+g8qxecxO1XBc/LdHEa5C0FmI", "mypassword") + +# Print some of the data: +# +print "Version:", fko.version() +print "Timestamp:", fko.timestamp() +print "Username:", fko.username() +print "Digest Type (value):", fko.digest_type() +print "Digest Type (string):", fko.digest_type_str() +print "Digest:", fko.digest() +print "SPA Message:", fko.spa_message() + diff --git a/python/fko.py b/python/fko.py new file mode 100644 index 00000000..ec185703 --- /dev/null +++ b/python/fko.py @@ -0,0 +1,345 @@ +# +############################################################################## +# +# File: fko.py +# +# Author: Damien S. Stuart +# +# Purpose: Module that provides a class that implements the functions for +# managing fwknop Single Packet Authorization (SPA) via the fwknop +# library (libfko). +# +############################################################################## +# +import _fko + +# FKO Constants definitions +# +# Message types +FKO_COMMAND_MSG = 0 +FKO_ACCESS_MSG = 1 +FKO_NAT_ACCESS_MSG = 2 +FKO_CLIENT_TIMEOUT_ACCESS_MSG = 3 +FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG = 4 +FKO_LOCAL_NAT_ACCESS_MSG = 5 +FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG = 6 + +# Digest types +FKO_DIGEST_MD5 = 1 +FKO_DIGEST_SHA1 = 2 +FKO_DIGEST_SHA256 = 3 +FKO_DIGEST_SHA384 = 4 +FKO_DIGEST_SHA512 = 5 + +# Encryption types +FKO_ENCRYPTION_RIJNDAEL = 1 +FKO_ENCRYPTION_GPG = 2 + +# FKO error codes +FKO_SUCCESS = 0 +FKO_ERROR_CTX_NOT_INITIALIZED = 1 +FKO_ERROR_MEMORY_ALLOCATION = 2 +FKO_ERROR_FILESYSTEM_OPERATION = 3 +FKO_ERROR_INVALID_DATA = 4 +FKO_ERROR_DATA_TOO_LARGE = 5 +FKO_ERROR_USERNAME_UNKNOWN = 6 +FKO_ERROR_INCOMPLETE_SPA_DATA = 7 +FKO_ERROR_MISSING_ENCODED_DATA = 8 +FKO_ERROR_INVALID_DIGEST_TYPE = 9 +FKO_ERROR_INVALID_ALLOW_IP = 10 +FKO_ERROR_INVALID_SPA_COMMAND_MSG = 11 +FKO_ERROR_INVALID_SPA_ACCESS_MSG = 12 +FKO_ERROR_INVALID_SPA_NAT_ACCESS_MSG = 13 +FKO_ERROR_INVALID_ENCRYPTION_TYPE = 14 +FKO_ERROR_WRONG_ENCRYPTION_TYPE = 15 +FKO_ERROR_DECRYPTION_SIZE = 16 +FKO_ERROR_DECRYPTION_FAILURE = 17 +FKO_ERROR_DIGEST_VERIFICATION_FAILED = 18 +FKO_ERROR_UNSUPPORTED_FEATURE = 19 +FKO_ERROR_UNKNOWN = 20 +# Start GPGME-related errors +GPGME_ERR_START = 21 +FKO_ERROR_MISSING_GPG_KEY_DATA = 22 +FKO_ERROR_GPGME_NO_OPENPGP = 23 +FKO_ERROR_GPGME_CONTEXT = 24 +FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ = 25 +FKO_ERROR_GPGME_SET_PROTOCOL = 26 +FKO_ERROR_GPGME_CIPHER_DATA_OBJ = 27 +FKO_ERROR_GPGME_BAD_PASSPHRASE = 28 +FKO_ERROR_GPGME_ENCRYPT_SIGN = 29 +FKO_ERROR_GPGME_CONTEXT_SIGNER_KEY = 30 +FKO_ERROR_GPGME_SIGNER_KEYLIST_START = 31 +FKO_ERROR_GPGME_SIGNER_KEY_NOT_FOUND = 32 +FKO_ERROR_GPGME_SIGNER_KEY_AMBIGUOUS = 33 +FKO_ERROR_GPGME_ADD_SIGNER = 34 +FKO_ERROR_GPGME_CONTEXT_RECIPIENT_KEY = 35 +FKO_ERROR_GPGME_RECIPIENT_KEYLIST_START = 36 +FKO_ERROR_GPGME_RECIPIENT_KEY_NOT_FOUND = 37 +FKO_ERROR_GPGME_RECIPIENT_KEY_AMBIGUOUS = 38 +FKO_ERROR_GPGME_DECRYPT_FAILED = 39 +FKO_ERROR_GPGME_DECRYPT_UNSUPPORTED_ALGORITHM = 40 +FKO_ERROR_GPGME_BAD_GPG_EXE = 41 +FKO_ERROR_GPGME_BAD_HOME_DIR = 42 +FKO_ERROR_GPGME_SET_HOME_DIR = 43 +FKO_ERROR_GPGME_NO_SIGNATURE = 44 +FKO_ERROR_GPGME_BAD_SIGNATURE = 45 +FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED = 46 +### End FKO Constants ### + +class Fko: + """This class wraps the Firewall KNock OPerator (fwknop) library, + libfko. It provides the functionality to manage and process + Single Packet Authorization (SPA) data. + + """ + + def __init__(self, spa_data=None, key=None): + """Constructor for the Fko class. + + Creates and intitializes the fko context. + + If no arguments are given, and empty context is create with + some default values. See the libfko documentation for details + on these defaults. + + If spa_data and key is supplied, the context is created, then + the SPA data is decrypted using the key. If successful, the SPA + data is parsed into the context's data structure. + + If spa_data is supplied without the key, then the encrypted data + is stored in the context and can be decoded later (see libfko docs). + + """ + + # If there is SPA data, attempt to process it. Otherwise, create + # an empty context. + # + if(spa_data != None): + self.ctx = _fko.init_ctx_with_data(spa_data, key) + else: + self.ctx = _fko.init_ctx() + + # Destructor to make sure the fko context is properly destroyed and + # the memory it was using is released. + # + def __del__(self): + _fko.destroy_ctx(self.ctx) + + ### FKO data functions and operations. ### + + def version(self): + return _fko.get_version(self.ctx) + + def rand_value(self, val=None): + if(val != None): + _fko.set_rand_value(self.ctx, val) + else: + return _fko.get_rand_value(self.ctx) + + def username(self, val=None): + if(val != None): + _fko.set_username(self.ctx, val) + else: + return _fko.get_username(self.ctx) + + def timestamp(self, val=None): + if(val != None): + _fko.set_timestamp(self.ctx, val) + else: + return _fko.get_timestamp(self.ctx) + + def digest_type(self, val=None): + if(val != None): + _fko.set_spa_digest_type(self.ctx, val) + else: + return _fko.get_spa_digest_type(self.ctx) + + def encryption_type(self, val=None): + if(val != None): + _fko.set_spa_encryption_type(self.ctx, val) + else: + return _fko.get_spa_encryption_type(self.ctx) + + def message_type(self, val=None): + if(val != None): + _fko.set_spa_message_type(self.ctx, val) + else: + return _fko.get_spa_message_type(self.ctx) + + def spa_message(self, val=None): + if(val != None): + _fko.set_spa_message(self.ctx, val) + else: + return _fko.get_spa_message(self.ctx) + + def spa_nat_access(self, val=None): + if(val != None): + _fko.set_spa_nat_access(self.ctx, val) + else: + return _fko.get_spa_nat_access(self.ctx) + + def spa_server_auth(self, val=None): + if(val != None): + _fko.set_spa_server_auth(self.ctx, val) + else: + return _fko.get_spa_server_auth(self.ctx) + + def spa_client_timeout(self, val=None): + if(val != None): + _fko.set_spa_client_timeout(self.ctx, val) + else: + return _fko.get_spa_client_timeout(self.ctx) + + def spa_digest(self): + return _fko.get_spa_digest(self.ctx) + + def gen_spa_digest(self): + _fko.set_spa_digest(self.ctx) + + def spa_data(self, val=None): + if(val != None): + _fko.set_spa_data(self.ctx, val) + else: + return _fko.get_spa_data(self.ctx) + + def encoded_data(self): + return _fko.get_encoded_data(self.ctx) + + def spa_data_final(self, key): + _fko.spa_data_final(self.ctx, key) + + def gen_spa_data(self, key): + _fko.spa_data_final(self.ctx, key) + + def encode_spa_data(self): + _fko.encode_spa_data(self.ctx) + + def decode_spa_data(self): + _fko.decode_spa_data(self.ctx) + + def encrypt_spa_data(self, key): + _fko.encrypt_spa_data(self.ctx, key) + + def decrypt_spa_data(self, key): + _fko.decrypt_spa_data(self.ctx, key) + + # GPG-related functions. + + def gpg_recipient(self, val=None): + if(val != None): + _fko.set_gpg_recipient(self.ctx, val) + else: + return _fko.get_gpg_recipient(self.ctx) + + def gpg_signer(self, val=None): + if(val != None): + _fko.set_gpg_signer(self.ctx, val) + else: + return _fko.get_gpg_signer(self.ctx) + + def gpg_home_dir(self, val=None): + if(val != None): + _fko.set_gpg_home_dir(self.ctx, val) + else: + return _fko.get_gpg_home_dir(self.ctx) + + def gpg_signature_verify(self, val=None): + if(val != None): + _fko.set_gpg_signature_verify(self.ctx, val) + else: + return _fko.get_gpg_signature_verify(self.ctx) + + def gpg_ignore_verify_error(self, val=None): + if(val != None): + _fko.set_gpg_ignore_verify_error(self.ctx, val) + else: + return _fko.get_gpg_ignore_verify_error(self.ctx) + + def gpg_exe(self, val=None): + if(val != None): + _fko.set_gpg_exe(self.ctx, val) + else: + return _fko.get_gpg_exe(self.ctx) + + def gpg_signature_id(self): + return _fko.get_gpg_signature_id(self.ctx) + + def gpg_signature_fpr(self): + return _fko.get_gpg_signature_fpr(self.ctx) + + def gpg_signature_summary(self): + return _fko.get_gpg_signature_summary(self.ctx) + + def gpg_signature_status(self): + return _fko.get_gpg_signature_status(self.ctx) + + def gpg_signature_id_match(self, val): + if(_fko.gpg_signature_id_match(self.ctx) > 0): + return True + return False + + def gpg_signature_fpr_match(self, val): + if(_fko.gpg_signature_fpr_match(self.ctx) > 0): + return True + return False + + # Error message string function. + + def errstr(self, val): + return _fko.errstr(code) + + # FKO type lookup functions. + + def message_type_str(self, val=None): + if val == None: + val = _fko.get_spa_message_type(self.ctx) + + if val == FKO_COMMAND_MSG: + mts = "Command Message" + elif val == FKO_ACCESS_MSG: + mts = "Access Message" + elif val == FKO_NAT_ACCESS_MSG: + mts = "NAT Access Message" + elif val == FKO_CLIENT_TIMEOUT_ACCESS_MSG: + mts = "Access Message with timeout" + elif val == FKO_CLIENT_TIMEOUT_NAT_ACCESS_MSG: + mts = "NAT access Message with timeout" + elif val == FKO_LOCAL_NAT_ACCESS_MSG: + mts = "Local NAT Access Message" + elif val == FKO_CLIENT_TIMEOUT_LOCAL_NAT_ACCESS_MSG: + mts = "Local NAT Access Message with timeout" + else: + mts = "Unknown message type" + return mts + + def digest_type_str(self, val=None): + if val == None: + val = _fko.get_spa_digest_type(self.ctx) + + if val == FKO_DIGEST_MD5: + dts = "MD5" + elif val == FKO_DIGEST_SHA1: + dts = "SHA1" + elif val == FKO_DIGEST_SHA256: + dts = "SHA256" + elif val == FKO_DIGEST_SHA384: + dts = "SHA384" + elif val == FKO_DIGEST_SHA512: + dts = "SHA512" + else: + dts = "Unknown digest type" + return dts + + def encryption_type_str(self, val=None): + if val == None: + val = _fko.get_spa_encryption_type(self.ctx) + + if val == FKO_ENCRYPTION_RIJNDAEL: + ets = "Rijndael (AES)" + elif val == FKO_ENCRYPTION_GPG: + ets = "GPG" + else: + ets = "Unknown encryption type" + return ets + +###EOF### diff --git a/python/fkomodule.c b/python/fkomodule.c index bd5b0abc..ef96d6f0 100644 --- a/python/fkomodule.c +++ b/python/fkomodule.c @@ -209,11 +209,11 @@ static PyMethodDef FKOMethods[] = { * Module init */ PyMODINIT_FUNC -initfko(void) +init_fko(void) { PyObject *m; - m = Py_InitModule("fko", FKOMethods); + m = Py_InitModule("_fko", FKOMethods); if (m == NULL) return; @@ -423,7 +423,7 @@ get_timestamp(PyObject *self, PyObject *args) return NULL; } - return Py_BuildValue("I", timestamp); + return Py_BuildValue("k", timestamp); } /* set_timestamp @@ -434,7 +434,7 @@ set_timestamp(PyObject *self, PyObject *args) fko_ctx_t ctx; int res, offset; - if(!PyArg_ParseTuple(args, "ki", &ctx, &offset)) + if(!PyArg_ParseTuple(args, "kk", &ctx, &offset)) return NULL; res = fko_set_timestamp(ctx, offset); diff --git a/python/setup.py b/python/setup.py index 84e84adb..d1dca983 100644 --- a/python/setup.py +++ b/python/setup.py @@ -12,7 +12,7 @@ from distutils.core import setup, Extension module1 = Extension( - 'fko', + '_fko', define_macros = [('MAJOR_VERSION', '1'), ('MINOR_VERSION', '0')], libraries = ['fko'], sources = ['fkomodule.c'] @@ -29,5 +29,6 @@ setup ( Python module that wraps the fwknop library to provide the ability to generate, decode, parse, and process SPA formatted messages. ''', - ext_modules = [module1] + ext_modules = [module1], + py_modules = ['fko'] )