diff options
author | Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com> | 2014-08-11 17:25:21 -0700 |
---|---|---|
committer | Jack Magne <jmagne@dhcp-16-213.sjc.redhat.com> | 2014-08-22 17:20:24 -0700 |
commit | 20b9d956aab21a5a2a61162e6c88fbee5828a9e9 (patch) | |
tree | 510da67f5ffd2e16f78af469c7fd182d81ded281 /base/tps-client/src/main | |
parent | 8f418fbcec0bda83ea4247059f5142be3c3d1ca5 (diff) | |
download | pki-20b9d956aab21a5a2a61162e6c88fbee5828a9e9.tar.gz pki-20b9d956aab21a5a2a61162e6c88fbee5828a9e9.tar.xz pki-20b9d956aab21a5a2a61162e6c88fbee5828a9e9.zip |
Misc TPS packaging tasks:
1. Make sure the new TPS packages all the applet files, like the old TPS has done.
2. Create a small new package called "pki-tps-client", which will hold ONLY the
command line utility "tpsclient" and all of its supporting libraries.
3. Move the directory pki/base/tps to pki/base/tps-client
We will do this until we can rewrite "tpclien" on the new Java TPS system.
Add package pki-tps-client.
Diffstat (limited to 'base/tps-client/src/main')
-rw-r--r-- | base/tps-client/src/main/AttributeSpec.cpp | 115 | ||||
-rw-r--r-- | base/tps-client/src/main/AuthParams.cpp | 72 | ||||
-rw-r--r-- | base/tps-client/src/main/Authentication.cpp | 105 | ||||
-rw-r--r-- | base/tps-client/src/main/AuthenticationEntry.cpp | 91 | ||||
-rw-r--r-- | base/tps-client/src/main/Buffer.cpp | 253 | ||||
-rw-r--r-- | base/tps-client/src/main/ConfigStore.cpp | 893 | ||||
-rw-r--r-- | base/tps-client/src/main/LogFile.cpp | 298 | ||||
-rw-r--r-- | base/tps-client/src/main/Login.cpp | 72 | ||||
-rw-r--r-- | base/tps-client/src/main/Memory.cpp | 268 | ||||
-rw-r--r-- | base/tps-client/src/main/NameValueSet.cpp | 322 | ||||
-rw-r--r-- | base/tps-client/src/main/ObjectSpec.cpp | 528 | ||||
-rw-r--r-- | base/tps-client/src/main/PKCS11Obj.cpp | 491 | ||||
-rw-r--r-- | base/tps-client/src/main/RA_Context.cpp | 56 | ||||
-rw-r--r-- | base/tps-client/src/main/RA_Msg.cpp | 45 | ||||
-rw-r--r-- | base/tps-client/src/main/RA_Session.cpp | 75 | ||||
-rw-r--r-- | base/tps-client/src/main/RA_pblock.cpp | 176 | ||||
-rw-r--r-- | base/tps-client/src/main/RollingLogFile.cpp | 493 | ||||
-rw-r--r-- | base/tps-client/src/main/SecureId.cpp | 71 | ||||
-rw-r--r-- | base/tps-client/src/main/Util.cpp | 1168 |
19 files changed, 5592 insertions, 0 deletions
diff --git a/base/tps-client/src/main/AttributeSpec.cpp b/base/tps-client/src/main/AttributeSpec.cpp new file mode 100644 index 000000000..23c2cd978 --- /dev/null +++ b/base/tps-client/src/main/AttributeSpec.cpp @@ -0,0 +1,115 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <string.h> +#include "prmem.h" +#include "pk11func.h" +#include "main/Buffer.h" +#include "main/AttributeSpec.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +AttributeSpec::AttributeSpec () +{ +} + +AttributeSpec::~AttributeSpec () +{ +} + +AttributeSpec *AttributeSpec::Parse(Buffer *b, int offset) +{ + AttributeSpec *o = new AttributeSpec(); + unsigned long id = (((unsigned char *)*b)[offset+0] << 24) + + (((unsigned char *)*b)[offset+1] << 16) + + (((unsigned char *)*b)[offset+2] << 8) + + (((unsigned char *)*b)[offset+3]); + o->SetAttributeID(id); + // The following line generates the following known benign warning + // message on Windows platforms: + // + // AttributeSpec.cpp(40) : warning C4244: 'argument' : conversion + // from 'unsigned long' to 'unsigned char', possible loss of data + // + o->SetType((unsigned long)(((unsigned char *)*b)[offset+4])); + // DatatypeString contains two bytes for AttributeLen of AttributeData + Buffer data; + if (o->GetType() == (BYTE) 0) + data = b->substr(offset+5+2, b->size() - 5-2); + else + data = b->substr(offset+5, b->size() - 5); + + o->SetData(data); + return o; +} + +void AttributeSpec::SetAttributeID(unsigned long v) +{ + m_id = v; +} + +unsigned long AttributeSpec::GetAttributeID() +{ + return m_id; +} + +void AttributeSpec::SetType(BYTE v) +{ + m_type = v; +} + +BYTE AttributeSpec::GetType() +{ + return m_type; +} + +// sets AttributeData (for string type, contains AttributeLen+AttributeValue) +void AttributeSpec::SetData(Buffer data) +{ + m_data = data; +} + +// gets AttributeData +Buffer AttributeSpec::GetValue() +{ + return m_data; +} + +// gets AttributeSpec +Buffer AttributeSpec::GetData() +{ + Buffer data = Buffer(); + data += Buffer(1, (BYTE)(m_id >> 24) & 0xff); + data += Buffer(1, (BYTE)(m_id >> 16) & 0xff); + data += Buffer(1, (BYTE)(m_id >> 8) & 0xff); + data += Buffer(1, (BYTE)m_id & 0xff); + data += Buffer(1, m_type); + if (m_type == 0) { /* String */ + data += Buffer(1, (m_data.size() >> 8) & 0xff); + data += Buffer(1, m_data.size() & 0xff); + } + data += m_data; + return data; +} + diff --git a/base/tps-client/src/main/AuthParams.cpp b/base/tps-client/src/main/AuthParams.cpp new file mode 100644 index 000000000..3a124252e --- /dev/null +++ b/base/tps-client/src/main/AuthParams.cpp @@ -0,0 +1,72 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "authentication/AuthParams.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +TPS_PUBLIC AuthParams::AuthParams () { +} + +/** + * Destructs processor. + */ +AuthParams::~AuthParams () { +} + +TPS_PUBLIC void AuthParams::SetUID(char *uid) { + Add("UID", uid); +} + +TPS_PUBLIC char *AuthParams::GetUID() { + return GetValue("UID"); +} + +TPS_PUBLIC void AuthParams::SetPassword(char *pwd) { + Add("PASSWORD", pwd); +} + +TPS_PUBLIC char *AuthParams::GetPassword() { + return GetValue("PASSWORD"); +} + +void AuthParams::SetSecuridValue(char *securidValue) { + Add("SECURID_VALUE", securidValue); +} + +TPS_PUBLIC char *AuthParams::GetSecuridValue() { + return GetValue("SECURID_VALUE"); +} + +void AuthParams::SetSecuridPin(char *securidPin) { + Add("SECURID_PIN", securidPin); +} + +TPS_PUBLIC char *AuthParams::GetSecuridPin() { + return GetValue("SECURID_PIN"); +} + diff --git a/base/tps-client/src/main/Authentication.cpp b/base/tps-client/src/main/Authentication.cpp new file mode 100644 index 000000000..34ab76f0a --- /dev/null +++ b/base/tps-client/src/main/Authentication.cpp @@ -0,0 +1,105 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "main/RA_Session.h" +#include "main/Login.h" +#include "main/SecureId.h" +#include "main/Util.h" +#include "main/Memory.h" +#include "authentication/Authentication.h" +#include "authentication/AuthParams.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +/** + * Constructs a base authentication + */ +TPS_PUBLIC Authentication::Authentication () +{ +} + +/** + * Destructs processor. + */ +TPS_PUBLIC Authentication::~Authentication () +{ +} + +void Authentication::Initialize(int index) +{ +} + +int Authentication::Authenticate(AuthParams *params) +{ + return -1; +} + +int Authentication::GetNumOfRetries() { + return m_retries; +} + +const char *Authentication::GetTitle(char *locale) +{ + return NULL; +} + +const char *Authentication::GetDescription(char *locale) +{ + return NULL; +} + +int Authentication::GetNumOfParamNames() +{ + return 0; +} + +char *Authentication::GetParamID(int index) +{ + return NULL; +} + +const char *Authentication::GetParamName(int index, char *locale) +{ + return NULL; +} + +char *Authentication::GetParamType(int index) +{ + return NULL; +} + +const char *Authentication::GetParamDescription(int index, char *locale) +{ + return NULL; +} + +char *Authentication::GetParamOption(int index) +{ + return NULL; +} + diff --git a/base/tps-client/src/main/AuthenticationEntry.cpp b/base/tps-client/src/main/AuthenticationEntry.cpp new file mode 100644 index 000000000..eb7f75419 --- /dev/null +++ b/base/tps-client/src/main/AuthenticationEntry.cpp @@ -0,0 +1,91 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "plstr.h" +#include "main/AuthenticationEntry.h" + +/** + * Constructs a base authentication + */ +AuthenticationEntry::AuthenticationEntry () +{ + m_lib = NULL; + m_Id = NULL; + m_type = NULL; + m_authentication = NULL; +} + +/** + * Destructs processor. + */ +AuthenticationEntry::~AuthenticationEntry () +{ + if (m_lib != NULL) { + PR_UnloadLibrary(m_lib); + m_lib = NULL; + } + + if( m_Id != NULL ) { + PL_strfree( m_Id ); + m_Id = NULL; + } + + if( m_type != NULL ) { + PL_strfree( m_type ); + m_type = NULL; + } + + m_authentication = NULL; +} + +void AuthenticationEntry::SetLibrary(PRLibrary* lib) { + m_lib = lib; +} + +PRLibrary *AuthenticationEntry::GetLibrary() { + return m_lib; +} + +void AuthenticationEntry::SetId(const char *id) { + m_Id = PL_strdup(id); +} + +char *AuthenticationEntry::GetId() { + return m_Id; +} + +void AuthenticationEntry::SetAuthentication(Authentication *auth) { + m_authentication = auth; +} + +Authentication *AuthenticationEntry::GetAuthentication() { + return m_authentication; +} + +void AuthenticationEntry::SetType(const char *type) { + m_type = PL_strdup(type); +} + +char *AuthenticationEntry::GetType() { + return m_type; +} diff --git a/base/tps-client/src/main/Buffer.cpp b/base/tps-client/src/main/Buffer.cpp new file mode 100644 index 000000000..94311fc50 --- /dev/null +++ b/base/tps-client/src/main/Buffer.cpp @@ -0,0 +1,253 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <memory.h> +#include <assert.h> +#include <stdio.h> + +#include "main/Buffer.h" +#include "main/Memory.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +TPS_PUBLIC Buffer::Buffer(const BYTE *buf_, unsigned int len_) : len(len_), res(len_) +{ + buf = new BYTE[len]; + memcpy(buf, buf_, len); +} + +TPS_PUBLIC Buffer::Buffer(const Buffer& cpy) +{ + buf = 0; + *this = cpy; +} + +TPS_PUBLIC Buffer::Buffer(unsigned int len_) : len(len_), res(len_) +{ + buf = new BYTE[res]; + memset(buf, 0, len_); +} + +TPS_PUBLIC Buffer::Buffer(unsigned int len_, BYTE b) : len(len_), res(len_) +{ + if (len_ == 0) { + buf = NULL; + } else { + buf = new BYTE[res]; + memset(buf, b, len); + } +} + +TPS_PUBLIC Buffer::~Buffer() +{ + if( buf != NULL ) { + delete [] buf; + buf = NULL; + } +} + +TPS_PUBLIC bool +Buffer::operator==(const Buffer& cmp) const +{ + if( len != cmp.len ) return false; + for( unsigned int i=0; i < len; ++i ) { + if( buf[i] != cmp.buf[i] ) { + return false; + } + } + return true; +} + +TPS_PUBLIC Buffer& +Buffer::operator=(const Buffer& cpy) +{ + if( this == &cpy ) return *this; + len = cpy.len; + if( buf != NULL ) { + delete [] buf; + buf = NULL; + } + if (cpy.len == 0) { + buf = NULL; + } else { + buf = new BYTE[len]; + memcpy(buf, cpy.buf, len); + } + res = len; + + return *this; +} + +TPS_PUBLIC void +Buffer::zeroize() +{ + if( len > 0 ) { + memset( buf, 0, len ); + } +} + +TPS_PUBLIC Buffer +Buffer::operator+(const Buffer& addend) const +{ + Buffer result(len + addend.len); + memcpy(result.buf, buf, len); + memcpy(result.buf+len, addend.buf, addend.len); + return result; +} + +TPS_PUBLIC Buffer& +Buffer::operator+=(const Buffer& addend) +{ + unsigned int oldLen = len; + resize(len + addend.len); + memcpy(buf+oldLen, addend.buf, addend.len); + return *this; +} + +TPS_PUBLIC Buffer& +Buffer::operator+=(BYTE b) +{ + resize(len+1); + buf[len-1] = b; + return *this; +} + +TPS_PUBLIC void +Buffer::reserve(unsigned int n) +{ + if( n > res ) { + BYTE *newBuf = new BYTE[n]; + memcpy(newBuf, buf, len); + if( buf != NULL ) { + delete [] buf; + buf = NULL; + } + buf = newBuf; + res = n; + } +} + +TPS_PUBLIC void +Buffer::resize(unsigned int newLen) +{ + if( newLen == len ) { + return; + } else if( newLen < len ) { + len = newLen; + } else if( newLen <= res ) { + assert( newLen > len ); + memset(buf+len, 0, newLen-len); + len = newLen; + } else { + assert( newLen > len && newLen > res ); + BYTE *newBuf = new BYTE[newLen]; + memcpy(newBuf, buf, len); + memset(newBuf+len, 0, newLen-len); + if( buf != NULL ) { + delete [] buf; + buf = NULL; + } + buf = newBuf; + len = newLen; + res = newLen; + } +} + +TPS_PUBLIC Buffer +Buffer::substr(unsigned int i, unsigned int n) const +{ + assert( i < len && (i+n) <= len ); + return Buffer( buf+i, n ); +} + +TPS_PUBLIC void +Buffer::replace(unsigned int i, const BYTE* cpy, unsigned int n) +{ + if (len > i+n) { + resize( len); + }else { + resize( i+n ); + } + memcpy(buf+i, cpy, n); +} + +TPS_PUBLIC void +Buffer::dump() const +{ + unsigned int i; + + for( i=0; i < len; ++i ) { + printf("%02x ", buf[i]); + if( i % 16 == 15 ) printf("\n"); + } + printf("\n"); +} + +/* + * if caller knows it's a string, pad with ending 0 and return. + * note: + * It is the caller's responsibility to make sure it's a string. + * Memory needs to be released by the caller. + */ +TPS_PUBLIC char * +Buffer::string() +{ + unsigned int i; + char *s = (char *) PR_Malloc(len+1); + for (i = 0; i < len; i++) { + s[i] = buf[i]; + } + s[i] = '\0'; + return s; +} + +TPS_PUBLIC unsigned char* +Buffer::getBuf() { + return (unsigned char *) buf; +} + +TPS_PUBLIC unsigned int +Buffer::getLen() { + return len; +} + +TPS_PUBLIC char * +Buffer::toHex() +{ + unsigned int i; + + char *hx = (char *)PR_Malloc(1024); + if (hx == NULL) + return NULL; + for( i=0; i < len; ++i ) { + PR_snprintf(hx+(i*2),1024-(i*2),"%02x", (unsigned char)buf[i]); + } + + return hx; +} + +static const char hextbl[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; diff --git a/base/tps-client/src/main/ConfigStore.cpp b/base/tps-client/src/main/ConfigStore.cpp new file mode 100644 index 000000000..e526b4039 --- /dev/null +++ b/base/tps-client/src/main/ConfigStore.cpp @@ -0,0 +1,893 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <string.h> +#include <regex.h> +#include "prmem.h" +#include "prsystem.h" +#include "plstr.h" +#include "prio.h" +#include "prprf.h" +#include "main/ConfigStore.h" +#include "main/Memory.h" +#include "main/Util.h" +#include "engine/RA.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +#ifdef XP_WIN32 +#define TOKENDB_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TOKENDB_PUBLIC +#endif /* !XP_WIN32 */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +static PR_CALLBACK void* +_AllocTable(void* pool, PRSize size) +{ + return PR_MALLOC(size); +} + +static PR_CALLBACK void +_FreeTable(void* pool, void* item) +{ + PR_DELETE(item); +} + +static PR_CALLBACK PLHashEntry* +_AllocEntry(void* pool, const void* key) +{ + return PR_NEW(PLHashEntry); +} + +static PR_CALLBACK void +_FreeEntry(void* pool, PLHashEntry* he, PRUintn flag) +{ + if( he == NULL ) { + return; + } + + if (flag == HT_FREE_VALUE) { + if( he->value != NULL ) { + PL_strfree( (char*) he->value ); + he->value = NULL; + } + } else if (flag == HT_FREE_ENTRY) { + if( he->key != NULL ) { + PL_strfree( (char*) he->key ); + he->key = NULL; + } + if( he->value != NULL ) { + PL_strfree( (char*) he->value ); + he->value = NULL; + } + PR_DELETE(he); + } +} + +static PLHashAllocOps _AllocOps = { + _AllocTable, + _FreeTable, + _AllocEntry, + _FreeEntry +}; + +#ifdef __cplusplus +} +#endif + +///// ConfigStoreRoot + +ConfigStoreRoot::ConfigStoreRoot() +{ + m_set = PL_NewHashTable(3, PL_HashString, + PL_CompareStrings, PL_CompareValues, + &_AllocOps, NULL); + + m_set_refcount = 0; +} + +// If the ConfigStoreRoot goes out of scope, we can't destroy +// the Hashtable because others maybe depending on the values +// inside. +ConfigStoreRoot::~ConfigStoreRoot () +{ + if( m_set != NULL ) { + if (m_set_refcount==0) { + PL_HashTableDestroy( m_set ); + m_set = NULL; + } + } +} + +void ConfigStoreRoot::addref() +{ + m_set_refcount++; +} + +void ConfigStoreRoot::release() +{ + m_set_refcount--; +} + +PLHashTable *ConfigStoreRoot::getSet() +{ + return m_set; +} + + +// ConfigureStore + +ConfigStore::ConfigStore(ConfigStoreRoot* root, const char *subStoreName) +{ + m_substore_name = PL_strdup(subStoreName); + m_root = root; + root->addref(); + m_lock = PR_NewLock(); +} + +ConfigStore::~ConfigStore () +{ + if (m_substore_name != NULL) { + PR_Free(m_substore_name); + } + if (m_cfg_file_path != NULL) { + PR_Free(m_cfg_file_path); + } + m_root->release(); + delete m_root; + + if (m_lock != NULL ) + PR_DestroyLock(m_lock); +} + + + +/* +ConfigStore::ConfigStore(const ConfigStore &X) +{ + m_substore_name = X.m_substore_name; + m_root = X.m_root; + m_root.addref(); +} + +*/ + + + +ConfigStore ConfigStore::GetSubStore(const char *substore) +{ + char *newname=NULL; + const char *name = m_substore_name; + if (strlen(name)==0) { // this is the root + newname = PL_strdup(substore); + } else { + newname = PR_smprintf("%s.%s",name,substore); + } + return ConfigStore(m_root,newname); +} + +/** + * Reads configuration file and puts name value + * pair into the global hashtable. + */ +static int ReadLine(PRFileDesc *f, char *buf, int buf_len, int *removed_return) +{ + char *cur = buf; + int sum = 0; + PRInt32 rc; + + *removed_return = 0; + while (1) { + rc = PR_Read(f, cur, 1); + if (rc == -1 || rc == 0) + break; + if (*cur == '\r') { + continue; + } + if (*cur == '\n') { + *cur = '\0'; + *removed_return = 1; + break; + } + sum++; + cur++; + } + return sum; +} + +#define MAX_CFG_LINE_LEN 4096 + +ConfigStore *ConfigStore::CreateFromConfigFile(const char *cfg_path) +{ + PRFileDesc *f = NULL; + int removed_return; + char line[MAX_CFG_LINE_LEN]; + ConfigStoreRoot *root = NULL; + ConfigStore *cfg = NULL; + + f = PR_Open(cfg_path, PR_RDWR, 00400|00200); + if (f == NULL) + goto loser; + + root = new ConfigStoreRoot(); + cfg = new ConfigStore(root,""); + + while (1) { + int n = ReadLine(f, line, MAX_CFG_LINE_LEN, &removed_return); + if (n > 0) { + if (line[0] == '#') // handle comment line + continue; + int c = 0; + while ((c < n) && (line[c] != '=')) { + c++; + } + if (c < n) { + line[c] = '\0'; + } else { + continue; /* no '=', skip this line */ + } + cfg->Add(line, &line[c+1]); + } else if (n == 0 && removed_return == 1) { + continue; /* skip empty line */ + } else { + break; + } + } + if( f != NULL ) { + PR_Close( f ); + f = NULL; + } + cfg->SetFilePath(cfg_path); + +loser: + return cfg; +} + +/** + * Parses string of format "n1=v1&n2=v2..." + * into a ConfigStore. + */ +ConfigStore *ConfigStore::Parse(const char *s, const char *separator) +{ + char *pair; + char *line = NULL; + int i; + int len; + char *lasts = NULL; + + if (s == NULL) + return NULL; + ConfigStoreRoot *root = new ConfigStoreRoot(); + ConfigStore *set= new ConfigStore(root,""); + + line = PL_strdup(s); + pair = PL_strtok_r(line, separator, &lasts); + while (pair != NULL) { + len = strlen(pair); + i = 0; + while (1) { + if (i >= len) { + goto skip; + } + if (pair[i] == '\0') { + goto skip; + } + if (pair[i] == '=') { + pair[i] = '\0'; + break; + } + i++; + } + set->Add(&pair[0], &pair[i+1]); +skip: + pair = PL_strtok_r(NULL, separator, &lasts); + } + if( line != NULL ) { + PL_strfree( line ); + line = NULL; + } + return set; +} + +typedef struct { + int index; + char *key; +} Criteria; + +typedef struct { + PRCList list; + char *key; +} OrderedEntry_t; + +typedef struct { + regex_t *regex; + ConfigStore *store; +} PatternEntry_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +static PRIntn CountLoop(PLHashEntry *he, PRIntn index, void *arg) +{ + Criteria *criteria = (Criteria *)arg; + criteria->index++; + return HT_ENUMERATE_NEXT; +} + +static PRIntn Loop(PLHashEntry *he, PRIntn index, void *arg) +{ + Criteria *criteria = (Criteria *)arg; + if (criteria != NULL && index == criteria->index) { + criteria->key = (char *)he->key; + return HT_ENUMERATE_STOP; + } else { + return HT_ENUMERATE_NEXT; + } +} + +/** + * Called from PL_HashTableEnumerateEntries + * A pointer to a PRCList (circular linked list) is passed in. + * Once enumeration is complete, the PRCList will contain a lexically + * ordered list of a copy of the keys in the hash. + * The caller needs to free the copies + */ +static PRIntn OrderLoop(PLHashEntry *he, PRIntn index, void *arg) +{ + PRCList *qp = (PRCList *)arg; + OrderedEntry_t *entry; + + if (he != NULL) { + entry = (OrderedEntry_t *) PR_Malloc(sizeof(OrderedEntry_t)); + entry->key = PL_strdup((char *) he->key); + if (index ==0) { + PR_APPEND_LINK((PRCList *)entry, qp); + return HT_ENUMERATE_NEXT; + } + PRCList *head = PR_LIST_HEAD(qp); + PRCList *next; + while (head != qp) { + OrderedEntry_t *current = (OrderedEntry_t *) head; + if (strcmp((char *) he->key, (char *) current->key) <=0) + break; + next = PR_NEXT_LINK(head); + head = next; + } + PR_INSERT_BEFORE((PRCList*) entry, head); + return HT_ENUMERATE_NEXT; + } else { + return HT_ENUMERATE_STOP; + } +} + +/** + * Called from PL_HashTableEnumerateEntries + * A pointer to a PatternEntry is passed in. A PatternEntry consists of + * a pointer a regex_t and a pointer to a new config store. + * Once enumeration is complete, the new config store will contain + * all the parameters (key and values) whose keys match the regex. + */ +static PRIntn PatternLoop(PLHashEntry *he, PRIntn index, void *arg) +{ + PatternEntry_t *entry = (PatternEntry_t *) arg; + + if (entry == NULL) { + return HT_ENUMERATE_STOP; + } + + regex_t *r = entry->regex; + ConfigStore *store = entry->store; + + if ((r == NULL) || (store == NULL)) { + return HT_ENUMERATE_STOP; + } + + size_t no_sub = r->re_nsub+1; + regmatch_t *result = NULL; + + result = (regmatch_t *) PR_Malloc(sizeof(regmatch_t) * no_sub); + + if ((he != NULL) && (he->key != NULL) && (he->value != NULL)) { + if (regexec(r, (char *) he->key, no_sub, result, 0)==0) { + // Found a match + store->Add((const char*) he->key, (const char *) he->value); + } + } else { + return HT_ENUMERATE_STOP; + } + + if (result != NULL) PR_Free(result); + return HT_ENUMERATE_NEXT; +} + +#ifdef __cplusplus +} +#endif + +int ConfigStore::Size() +{ + Criteria criteria; + criteria.index = 0; + criteria.key = NULL; + + PR_Lock(m_lock); + PL_HashTableEnumerateEntries(m_root->getSet(), &CountLoop, &criteria); + PR_Unlock(m_lock); + + return criteria.index; +} + +const char *ConfigStore::GetNameAt(int pos) +{ + Criteria criteria; + criteria.index = pos; + criteria.key = NULL; + + PR_Lock(m_lock); + PL_HashTableEnumerateEntries(m_root->getSet(), &Loop, &criteria); + PR_Unlock(m_lock); + + return criteria.key; +} + +/** + * Checks if a key is defined. + */ +int ConfigStore::IsNameDefined(const char *name) +{ + if (m_root->getSet()!= NULL) { + if (GetConfig(name) != NULL) + return 1; + } + return 0; +} + +void ConfigStore::SetFilePath(const char* cfg_file_path) +{ + m_cfg_file_path = PL_strdup(cfg_file_path); +} + +void ConfigStore::Add(const char *name, const char *value) +{ + if (IsNameDefined(name)) { + PR_Lock(m_lock); + PL_HashTableRemove(m_root->getSet(), name); + PL_HashTableAdd(m_root->getSet(), PL_strdup(name), PL_strdup(value)); + PR_Unlock(m_lock); + } else { + PR_Lock(m_lock); + PL_HashTableAdd(m_root->getSet(), PL_strdup(name), PL_strdup(value)); + PR_Unlock(m_lock); + } +} + +void ConfigStore::Remove(const char *name) +{ + if (IsNameDefined(name)) { + PR_Lock(m_lock); + PL_HashTableRemove(m_root->getSet(), name); + PR_Unlock(m_lock); + } +} + +const char *ConfigStore::GetConfig(const char *name) +{ + char buf[256]; + char *ret; + if (m_root->getSet() ==NULL) { + return NULL; + } + if (PL_strlen(m_substore_name) == 0) { + PL_strncpy(buf,name,256); + } else { + PR_snprintf(buf,256,"%s.%s",m_substore_name,name); + } + + PR_Lock(m_lock); + ret = (char *)PL_HashTableLookupConst(m_root->getSet(), buf); + PR_Unlock(m_lock); + + return ret; +} + +/** + * Retrieves configuration value as integer. + */ +int ConfigStore::GetConfigAsInt(const char *name) +{ + char *value = NULL; + value = (char *)GetConfig(name); + if (value == NULL) + return 0; + return atoi(value); +} + +/** + * Retrieves configuration value as integer. If name is + * not defined, default value is returned. + */ +TPS_PUBLIC int ConfigStore::GetConfigAsInt(const char *name, int def) +{ + char *value = NULL; + + value = (char *)GetConfig(name); + if (value == NULL) + return def; + return atoi(value); +} + + +/** + * Retrieves configuration value as unsigned integer. + */ +unsigned int ConfigStore::GetConfigAsUnsignedInt(const char *name) +{ + char *value = NULL; + int i = 0; + + value = (char *)GetConfig(name); + if (value == NULL) { + return 0; + } + + i = atoi(value); + if (i < 0) { + return 0; + } + return i; +} + +/** + * Retrieves configuration value as unsigned integer. If name is + * not defined, default value is returned. + */ +TPS_PUBLIC unsigned int ConfigStore::GetConfigAsUnsignedInt(const char *name, unsigned int def) +{ + char *value = NULL; + int i = 0; + + value = (char *)GetConfig(name); + if (value == NULL) { + return def; + } + + i = atoi(value); + if (i < 0) { + return def; + } + return i; +} + + +/** + * Retrieves configuration value as boolean. + */ +bool ConfigStore::GetConfigAsBool(const char *name) +{ + char *value = NULL; + + value = (char *)GetConfig(name); + if (value == NULL) + return false; + if (PL_CompareStrings("true", value) != 0) + return true; + else + return false; +} + +/** + * Retrieves configuration value as boolean. If name is + * not defined, default value is returned. + */ +TPS_PUBLIC bool ConfigStore::GetConfigAsBool(const char *name, bool def) +{ + char *value = NULL; + + value = (char *)GetConfig(name); + if (value == NULL) + return def; + + if (PL_CompareStrings("true", value) != 0) + return true; + else if (PL_CompareStrings("false", value) != 0) + return false; + else + return def; +} + +/** + * Retrieves configuration value as string. If key is + * not defined, default value is returned. + */ +TOKENDB_PUBLIC const char *ConfigStore::GetConfigAsString(const char *name, const char *def) +{ + char *value = NULL; + + value = (char *)GetConfig(name); + if (value == NULL) + return def; + return value; +} + +/** + * Retrieves configuration value as string. + */ +TPS_PUBLIC const char *ConfigStore::GetConfigAsString(const char *name) +{ + return (char *)GetConfig(name); +} + + +/** + * Allow operator[] overloading for retrieval of config strings + */ +const char* ConfigStore::operator[](const char*name) +{ + return GetConfigAsString(name); +} + + +Buffer *ConfigStore::GetConfigAsBuffer(const char *key) +{ + return GetConfigAsBuffer(key, NULL); +} + +Buffer *ConfigStore::GetConfigAsBuffer(const char *key, const char *def) +{ + const char *value = NULL; + + value = (char *)GetConfig(key); + if (value == NULL) { + if (def == NULL) { + return NULL; + } else { + return Util::Str2Buf(def); + } + } else { + return Util::Str2Buf(value); + } +} + +/** + * returns a string containing all the parameters in the ConfigStore hash set in the + * format key1=value1&&key2=value2&& ... + * The list will be lexically ordered by parameter key values. + * The string needs to be freed by the caller. + **/ +TPS_PUBLIC const char* ConfigStore::GetOrderedList() +{ + char *outstr = NULL; + char *new_string = NULL; + PRCList order_list; + PR_INIT_CLIST(&order_list); + + PR_Lock(m_lock); + PL_HashTableEnumerateEntries(m_root->getSet(), &OrderLoop, &order_list); + PR_Unlock(m_lock); + + PRCList *current = PR_LIST_HEAD(&order_list); + PRCList *next; + + outstr = (char*) PR_Malloc(128); + int allocated = 128; + int needed = 0; + PR_snprintf(outstr, 128, ""); + + while (current != &order_list) { + OrderedEntry_t *entry = (OrderedEntry_t *) current; + const char *value = GetConfigAsString(entry->key, ""); + + if ((entry != NULL) && (entry->key != NULL)) { + needed = PL_strlen(outstr) + PL_strlen(entry->key) + PL_strlen(value) + 4; + if (allocated <= needed) { + while (allocated <= needed) { + allocated = allocated * 2; + } + new_string = (char *)PR_Malloc(allocated); + PR_snprintf(new_string, allocated, "%s", outstr); + PR_Free(outstr); + outstr = new_string; + } + + PL_strcat(outstr, entry->key); + PL_strcat(outstr, "="); + PL_strcat(outstr, value); + + // free the memory for the Ordered Entry + PL_strfree(entry->key); + } + + next = PR_NEXT_LINK(current); + PR_REMOVE_AND_INIT_LINK(current); + if (current != NULL) { + PR_Free(current); + } + current = next; + + if (current != &order_list) PL_strcat(outstr, "&&"); + } + return outstr; +} + +/** + * Commits changes to the config file + */ +TPS_PUBLIC int ConfigStore::Commit(const bool backup, char *error_msg, int len) +{ + char name_tmp[256], cdate[256], name_bak[256], bak_dir[256]; + char basename[256], dirname[256]; + PRFileDesc *ftmp = NULL; + PRExplodedTime time; + PRTime now; + PRStatus status; + + if (m_cfg_file_path == NULL) { + PR_snprintf(error_msg, len, "ConfigStore::Commit(): m_cfg_file_path is NULL!"); + return 1; + } + + if (strrchr(m_cfg_file_path, '/') != NULL) { + PR_snprintf((char *) basename, 256, "%s", strrchr(m_cfg_file_path, '/') +1); + PR_snprintf((char *) dirname, PL_strlen(m_cfg_file_path) - PL_strlen(basename), "%s", m_cfg_file_path); + PL_strcat(dirname, '\0'); + } else { + PR_snprintf((char *) basename, 256, "%s", m_cfg_file_path); + PR_snprintf((char *) dirname, 256, "."); + } + PR_snprintf(bak_dir, 256, "%s/bak", dirname); + + now = PR_Now(); + PR_ExplodeTime(now, PR_LocalTimeParameters, &time); + PR_snprintf(cdate, 16, "%04d%02d%02d%02d%02d%02dZ", + time.tm_year, (time.tm_month + 1), time.tm_mday, + time.tm_hour, time.tm_min, time.tm_sec); + PR_snprintf(name_tmp, 256, "%s.%s.tmp", m_cfg_file_path,cdate); + PR_snprintf(name_bak, 256, "%s/%s.%s", bak_dir, basename, cdate); + + ftmp = PR_Open(name_tmp, PR_WRONLY| PR_CREATE_FILE, 00400|00200); + if (ftmp == NULL) { + // unable to create temporary config file + PR_snprintf(error_msg, len, "ConfigStore::Commit(): unable to create temporary config file"); + return 1; + } + + PRCList order_list; + PR_INIT_CLIST(&order_list); + + PR_Lock(m_lock); + PL_HashTableEnumerateEntries(m_root->getSet(), &OrderLoop, &order_list); + PR_Unlock(m_lock); + + PRCList *current = PR_LIST_HEAD(&order_list); + PRCList *next; + + while (current != &order_list) { + OrderedEntry_t *entry = (OrderedEntry_t *) current; + PR_Write(ftmp, entry->key, PL_strlen(entry->key)); + PR_Write(ftmp, "=", 1); + const char *value = GetConfigAsString(entry->key, ""); + PR_Write(ftmp, value, PL_strlen(value)); + PR_Write(ftmp, "\n", 1); + + // free the memory for the Ordered Entry + if (entry->key != NULL) PL_strfree(entry->key); + + next = PR_NEXT_LINK(current); + PR_REMOVE_AND_INIT_LINK(current); + if (current != NULL) { + PR_Free(current); + } + current = next; + } + + PR_Close(ftmp); + + if (backup) { + // create the backup directory if it does not exist + if (PR_Access(bak_dir, PR_ACCESS_EXISTS) != PR_SUCCESS) { + PR_MkDir(bak_dir, 00770); + } + status = PR_Rename(m_cfg_file_path, name_bak); + if (status != PR_SUCCESS) { + // failed to back up CS.cfg + } + } + if (PR_Access(m_cfg_file_path, PR_ACCESS_EXISTS) == PR_SUCCESS) { + // backup is false, or backup failed + status = PR_Delete(m_cfg_file_path); + if (status != PR_SUCCESS) { + // failed to delete old CS.cfg file + PR_snprintf(error_msg, len, "ConfigStore::Commit(): unable to delete old CS.cfg file"); + return 1; + } + } + + status = PR_Rename(name_tmp, m_cfg_file_path); + if (status != PR_SUCCESS) { + // failed to move tmp to CS.cfg + // major badness - we now have only tmp file, no CS.cfg + PR_snprintf(error_msg, len, "ConfigStore::Commit(): failed to move tmp file to CS.cfg"); + return 1; + } + + return 0; +} + +/** + * Takes in a string containing a regular expression. + * Returns a new ConfigStore which contains only those parameters whose + * keys match the pattern. + * The new Configstore must of course be freed by the caller. + **/ +ConfigStore *ConfigStore::GetPatternSubStore(const char *pattern) +{ + + ConfigStoreRoot *root = NULL; + ConfigStore *ret = NULL; + PatternEntry_t entry; + regex_t *regex = NULL; + int err_no=0; /* For regerror() */ + + regex = (regex_t *) malloc(sizeof(regex_t)); + memset(regex, 0, sizeof(regex_t)); + + if((err_no=regcomp(regex, pattern, 0))!=0) /* Compile the regex */ + { + // Error in computing the regex + size_t length; + char *buffer; + length = regerror (err_no, regex, NULL, 0); + buffer = (char *) PR_Malloc(length); + regerror (err_no, regex, buffer, length); + // PR_fprintf(m_dump_f, "%s\n", buffer); /* Print the error */ + PR_Free(buffer); + regfree(regex); + return NULL; + } + + entry.regex = regex; + root = new ConfigStoreRoot(); + ret = new ConfigStore(root, ""); + entry.store = ret; + + PR_Lock(m_lock); + PL_HashTableEnumerateEntries(m_root->getSet(), &PatternLoop, &entry); + PR_Unlock(m_lock); + + /* cleanup */ + //regfree(entry.regex); + //entry.store = NULL; + + ret->SetFilePath(""); + return ret; +} + diff --git a/base/tps-client/src/main/LogFile.cpp b/base/tps-client/src/main/LogFile.cpp new file mode 100644 index 000000000..d908ca0c5 --- /dev/null +++ b/base/tps-client/src/main/LogFile.cpp @@ -0,0 +1,298 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2010 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +#ifdef __cplusplus +extern "C" +{ +#endif +#include <unistd.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "prmem.h" +#include "prsystem.h" +#include "plstr.h" +#include "prio.h" + +#ifdef __cplusplus +} +#endif + +#include "main/ConfigStore.h" +#include "engine/RA.h" +#include "main/LogFile.h" +#include "main/RA_Context.h" +#include "main/Util.h" + +//default constructor +LogFile::LogFile(): + m_fd(NULL), + m_fname(NULL), + m_signed_log(false), + m_bytes_written(0), + m_signed(false), + m_monitor(NULL), + m_ctx(NULL) { } + +int LogFile::startup(RA_Context *ctx, const char* prefix, const char *fname, bool signed_audit) +{ + if (ctx == NULL) { + return PR_FAILURE; + } + + if (fname == NULL) { + ctx->LogError("LogFile::startup", + __LINE__, + "startup error, fname is NULL"); + return PR_FAILURE; + } + + m_ctx = ctx; + m_signed_log = signed_audit; + m_fname = PL_strdup(fname); + m_bytes_written =0; + m_signed = false; + m_fd = (PRFileDesc*) NULL; + m_monitor = PR_NewMonitor(); + + m_ctx->LogInfo( "LogFile::startup", + __LINE__, + "thread = 0x%lx: Logfile %s startup complete", + PR_GetCurrentThread(), m_fname); + return PR_SUCCESS; +} + +bool LogFile::isOpen() +{ + if (m_fd != NULL) return true; + return false; +} + +void LogFile::shutdown() +{ + m_ctx->LogInfo( "LogFile::shutdown", + __LINE__, + "thread = 0x%lx: Logfile %s shutting down pid: %d", + PR_GetCurrentThread(), m_fname,getpid()); + + PR_EnterMonitor(m_monitor); + if (m_fd != NULL) { + close(); + m_fd = (PRFileDesc *) NULL; + } + + if (m_fname != NULL) { + PR_Free(m_fname); + m_fname = NULL; + } + + PR_ExitMonitor(m_monitor); + + if (m_monitor != NULL) { + PR_DestroyMonitor(m_monitor); + m_monitor = (PRMonitor *) NULL; + } +} + +int LogFile::open() +{ + PRFileInfo info; + PR_EnterMonitor(m_monitor); + + m_ctx->LogInfo( "LogFile::open", + __LINE__, + "Opening Log File: %s pid: %d", + m_fname,getpid()); + + if (m_fd == NULL) { + m_fd = PR_Open(m_fname, PR_RDWR | PR_CREATE_FILE | PR_APPEND, 440|200); + if (m_fd == NULL) { + m_ctx->LogError( "LogFile::open", + __LINE__, + "Unable to open log file %s error no: %d", + m_fname,PR_GetError()); + + + goto loser; + } + PRStatus status = PR_GetOpenFileInfo(m_fd, &info); + if (status != PR_SUCCESS) { + m_ctx->LogError( "LogFile::open", + __LINE__, + "Unable to get file information for log file %s", + m_fname); + goto loser; + } + + set_bytes_written(info.size); + } + PR_ExitMonitor(m_monitor); + return PR_SUCCESS; + + loser: + if (m_fd != NULL) { + PR_Close(m_fd); + m_fd = (PRFileDesc *)NULL; + } + set_bytes_written(0); + PR_ExitMonitor(m_monitor); + return PR_FAILURE; +} + +int LogFile::close() +{ + PRStatus status; + PR_EnterMonitor(m_monitor); + status = PR_Close(m_fd); + if (status != PR_SUCCESS) { + m_ctx->LogError( "LogFile::close", + __LINE__, + "Failed to close log file %s", + m_fname); + } + PR_ExitMonitor(m_monitor); + return status; +} + +int LogFile::ReadLine(char *buf, int buf_len, int *removed_return) +{ + return Util::ReadLine(m_fd, buf,buf_len, removed_return); +} + +int LogFile::printf(const char* fmt, ...) +{ + PRInt32 status; + char msg[4096]; + va_list ap; + va_start(ap, fmt); + PR_vsnprintf((char *) msg, 4096, fmt, ap); + status = this->write(msg); + va_end(ap); + return status; +} + +int LogFile::write(char *msg_in, size_t n) +{ + char msg[4096]; + PRInt32 status; + + if (n > 4096) { + m_ctx->LogError("LogFile::write", + __LINE__, + "Trying to write more than 4096 bytes in one write to log file %s. Truncating ...", + m_fname); + n=4096; + } + + PR_snprintf(msg, n, "%s", msg_in); + status = this->write(msg); + return status; +} + +int LogFile::vfprintf(const char* fmt, va_list ap) +{ + char msg[4096]; + PRInt32 status; + + PR_vsnprintf((char *) msg, 4096, fmt, ap); + status = this->write(msg); + return status; +} + +int LogFile::write(const char * msg) +{ + PRErrorCode error; + PRInt32 status; + int len; + + if (msg == NULL) { + return PR_SUCCESS; + } + + PR_EnterMonitor(m_monitor); + len = PL_strlen(msg); + if (m_fd != NULL) { + status = PR_Write(m_fd, msg, len); + if (status != len) { + m_ctx->LogError( "LogFile::write", + __LINE__, + "Too few or too many bytes written to log file %s", + m_fname); + goto loser; + } else if (status < 0) { + // write failed + error = PR_GetError(); + m_ctx->LogError( "LogFile::write", + __LINE__, + "Write to log file %s failed: code %d", + m_fname, error); + goto loser; + } else { + set_bytes_written(get_bytes_written() + len); + } + } + PR_ExitMonitor(m_monitor); + return PR_SUCCESS; + loser: + PR_ExitMonitor(m_monitor); + return PR_FAILURE; +} + +void LogFile::setSigned(bool val) { + m_signed = val; +} + +bool LogFile::getSigned() { + return m_signed; +} + +int LogFile::get_bytes_written() { + return m_bytes_written; +} + +void LogFile::set_bytes_written(int val) { + if (val >=0) { + m_bytes_written = val; + } else { + m_ctx->LogError("LogFile::set_bytes_written", + __LINE__, + "Attempt to set m_bytes_written to a negative value. Ignoring"); + } +} + +RA_Context * LogFile::get_context() { + return m_ctx; +} + +void LogFile::set_context(RA_Context *ctx) { + m_ctx = ctx; +} + + diff --git a/base/tps-client/src/main/Login.cpp b/base/tps-client/src/main/Login.cpp new file mode 100644 index 000000000..116ac7769 --- /dev/null +++ b/base/tps-client/src/main/Login.cpp @@ -0,0 +1,72 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include "plstr.h" +#include "main/Base.h" +#include "main/Login.h" +#include "main/Memory.h" + +/** + * Constructs a login object. + */ +Login::Login (char *uid, char *pwd) +{ + if (uid == NULL) { + m_uid = NULL; + } else { + m_uid = PL_strdup(uid); + } + if (pwd == NULL) { + m_pwd = NULL; + } else { + m_pwd = PL_strdup(pwd); + } +} + +/** + * Destructs login object. + */ +Login::~Login () +{ + if( m_uid != NULL ) { + PL_strfree( m_uid ); + m_uid = NULL; + } + if( m_pwd != NULL ) { + PL_strfree( m_pwd ); + m_pwd = NULL; + } +} + +/** + * Retrieves user id. + */ +char *Login::GetUID() +{ + return m_uid; +} + +/** + * Retrieves password. + */ +char *Login::GetPassword() +{ + return m_pwd; +} diff --git a/base/tps-client/src/main/Memory.cpp b/base/tps-client/src/main/Memory.cpp new file mode 100644 index 000000000..1ee5027d0 --- /dev/null +++ b/base/tps-client/src/main/Memory.cpp @@ -0,0 +1,268 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "prmem.h" +#include "prsystem.h" +#include "plstr.h" +#include "prio.h" +#include "prprf.h" +#include "plhash.h" +#include "pk11func.h" + +#include "main/MemoryMgr.h" + +#ifdef MEM_PROFILING + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct _ref_block +{ + int id; + void *ptr; + const char *file; + const char *func; + const char *type; + int line; + int size; + int used; + PRTime time; +} ref_block; + +#define MAX_BLOCKS 8096 +static ref_block m_rb[MAX_BLOCKS]; + +static PRLock *m_free_block_lock = NULL; +static PRLock *m_dump_lock = NULL; +static PRLock *m_audit_lock = NULL; + +ref_block *get_free_block() +{ + int i; + PR_Lock(m_free_block_lock); + for (i = 0; i < MAX_BLOCKS; i++) { + if (m_rb[i].used == 0) { + // lock + m_rb[i].used = 1; + m_rb[i].time = PR_Now(); + PR_Unlock(m_free_block_lock); + return &m_rb[i]; + } + } + PR_Unlock(m_free_block_lock); + return NULL; +} + +ref_block *find_block(void *ptr) +{ + int i; + for (i = 0; i < MAX_BLOCKS; i++) { + if (m_rb[i].used == 1 && m_rb[i].ptr == ptr) { + return &m_rb[i]; + } + } + return NULL; +} + +void free_block(ref_block *rb) +{ + rb->used = 0; +} + +static PRFileDesc *m_audit_f = NULL; +static PRFileDesc *m_dump_f = NULL; + +void MEM_init(char *audit_file, char *dump_file) +{ + m_audit_f = PR_Open(audit_file, PR_RDWR|PR_CREATE_FILE|PR_APPEND, + 00200|00400); + m_dump_f = PR_Open(dump_file, PR_RDWR|PR_CREATE_FILE|PR_APPEND, + 00200|00400); + + int i; + for (i = 0; i < MAX_BLOCKS; i++) { + m_rb[i].id = i; + m_rb[i].used = 0; + } + m_free_block_lock = PR_NewLock(); + m_dump_lock = PR_NewLock(); + m_audit_lock = PR_NewLock(); +} + +void MEM_shutdown() +{ + PR_DestroyLock(m_free_block_lock); + PR_DestroyLock(m_dump_lock); + PR_DestroyLock(m_audit_lock); + if (m_dump_f != NULL) { + PR_Close(m_dump_f); + } + if (m_audit_f != NULL) { + PR_Close(m_audit_f); + } +} + +static void MEM_audit_block(ref_block *ref, const char *type, const char *func, const char *file, int line, PRFileDesc *f) +{ + PRTime now; + const char* time_fmt = "%Y-%m-%d %H:%M:%S"; + char datetime[1024]; + PRExplodedTime time; + char datetime1[1024]; + PRExplodedTime time1; + + now = PR_Now(); + PR_ExplodeTime(now, PR_LocalTimeParameters, &time); + PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time); + + PR_ExplodeTime(ref->time, PR_LocalTimeParameters, &time1); + PR_FormatTimeUSEnglish(datetime1, 1024, time_fmt, &time1); + + PR_Lock(m_audit_lock); + PR_fprintf(f, "[%s] ID='%d' Size='%d' Type='%s' Func='%s' File='%s' Line='%d' Time='%s'\n", + datetime, ref->id, ref->size, type, func, file, line, datetime1); + PR_Sync(f); + PR_Unlock(m_audit_lock); +} + +void MEM_dump_unfree() +{ + int i; + PRTime now; + const char* time_fmt = "%Y-%m-%d %H:%M:%S"; + char datetime[1024]; + PRExplodedTime time; + char datetime1[1024]; + PRExplodedTime time1; + int sum_count = 0; + int sum_mem = 0; + + now = PR_Now(); + PR_ExplodeTime(now, PR_LocalTimeParameters, &time); + PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time); + + PR_Lock(m_dump_lock); + PR_fprintf(m_dump_f, "--------------------------------------------\n"); + PR_fprintf(m_dump_f, "Memory Report - '%s'\n", datetime); + PR_fprintf(m_dump_f, "1) Unfree Blocks:\n"); + PR_fprintf(m_dump_f, "\n"); + for (i = 0; i < MAX_BLOCKS; i++) { + if (!m_rb[i].used) + continue; + PR_ExplodeTime(m_rb[i].time, PR_LocalTimeParameters, &time1); + PR_FormatTimeUSEnglish(datetime1, 1024, time_fmt, &time1); + PR_fprintf(m_dump_f, " ID='%d' Size='%d' Type='%s' Func='%s' File='%s' Line='%d' Time='%s'\n", m_rb[i].id, m_rb[i].size, m_rb[i].type, m_rb[i].func, m_rb[i].file, m_rb[i].line, datetime1); + sum_mem += m_rb[i].size; + sum_count += 1; + } + PR_fprintf(m_dump_f, "\n"); + PR_fprintf(m_dump_f, "2) Total Unfree Memory Size:\n"); + PR_fprintf(m_dump_f, " %d bytes\n", sum_mem); + PR_fprintf(m_dump_f, "\n"); + PR_fprintf(m_dump_f, "3) Total Unfree Memory Blocks:\n"); + PR_fprintf(m_dump_f, " %d\n", sum_count); + PR_fprintf(m_dump_f, "\n"); + PR_fprintf(m_dump_f, "--------------------------------------------\n"); + PR_Sync(m_dump_f); + PR_Unlock(m_dump_lock); +} + +char *MEM_strdup(const char *s, const char *type, const char *func, const char *file, int line) +{ + ref_block *rb = get_free_block(); + if (rb == NULL) + return NULL; + + char *buf = strdup(s); + + rb->ptr = buf; + rb->func = func; + rb->file = file; + rb->line = line; + rb->type = type; + rb->size = strlen(s) + 1; + MEM_audit_block(rb, rb->type, rb->func, rb->file, rb->line, m_audit_f); + + return buf; +} + +void *MEM_malloc(int size, const char *type, const char *func, const char *file, int line) +{ + ref_block *rb = get_free_block(); + if (rb == NULL) + return NULL; + void *buf = malloc(size); + + rb->ptr = buf; + rb->func = func; + rb->file = file; + rb->line = line; + rb->type = type; + rb->size = size; + MEM_audit_block(rb, rb->type, rb->func, rb->file, rb->line, m_audit_f); + + return buf; +} + +void MEM_free(void *p, const char *type, const char *func, const char *file, int line) +{ + if (p == NULL) + return; + ref_block *rb = find_block(p); + if (rb == NULL) + return; + MEM_audit_block(rb, type, func, file, line, m_audit_f); + free(p); + free_block(rb); +} + +#ifdef __cplusplus +} +#endif + +#if 0 +void *operator new(size_t size, const char *func, const char *file, int line) +{ + return MEM_malloc(size, func, file, line); +} + +void *operator new[](size_t size, const char *func, const char *file, int line) +{ + return MEM_malloc(size, func, file, line); +} + +#endif +void operator delete(void *p) +{ + MEM_free(p,"delete","", "", 0); +} + +void operator delete[](void *p) +{ + MEM_free(p,"delete[]","", "", 0); +} + +#endif /* MEM_PROFILING */ + diff --git a/base/tps-client/src/main/NameValueSet.cpp b/base/tps-client/src/main/NameValueSet.cpp new file mode 100644 index 000000000..bd95a8e4a --- /dev/null +++ b/base/tps-client/src/main/NameValueSet.cpp @@ -0,0 +1,322 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> +#include <string.h> +#include "prmem.h" +#include "prsystem.h" +#include "plstr.h" +#include "prio.h" +#include "prprf.h" +#include "main/NameValueSet.h" +#include "main/Memory.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +static PR_CALLBACK void* +_AllocTable(void* pool, PRSize size) +{ + return PR_MALLOC(size); +} + +static PR_CALLBACK void +_FreeTable(void* pool, void* item) +{ + PR_DELETE(item); +} + +static PR_CALLBACK PLHashEntry* +_AllocEntry(void* pool, const void* key) +{ + return PR_NEW(PLHashEntry); +} + +static PR_CALLBACK void +_FreeEntry(void* pool, PLHashEntry* he, PRUintn flag) +{ + if( he == NULL ) { + return; + } + + if (flag == HT_FREE_VALUE) { + if( he->value != NULL ) { + PL_strfree( ( char* ) he->value ); + he->value = NULL; + } + } else if (flag == HT_FREE_ENTRY) { + if( he->key != NULL ) { + PL_strfree( ( char* ) he->key ); + he->key = NULL; + } + if( he->value != NULL ) { + PL_strfree( ( char* ) he->value ); + he->value = NULL; + } + PR_DELETE(he); + } +} + +static PLHashAllocOps _AllocOps = { + _AllocTable, + _FreeTable, + _AllocEntry, + _FreeEntry +}; + +#ifdef __cplusplus +} +#endif + +TPS_PUBLIC NameValueSet::NameValueSet() +{ + m_set = PL_NewHashTable(3, PL_HashString, + PL_CompareStrings, PL_CompareValues, + &_AllocOps, NULL); +} + +TPS_PUBLIC NameValueSet::~NameValueSet () +{ + if( m_set != NULL ) { + PL_HashTableDestroy( m_set ); + m_set = NULL; + } + + return; +} + +/** + * Parsers string of format "n1=v1&n2=v2..." + * into a NameValueSet. + */ +TPS_PUBLIC NameValueSet *NameValueSet::Parse(const char *s, const char *separator) +{ + NameValueSet *set = NULL; + char *pair; + char *line = NULL; + int i; + int len; + char *lasts = NULL; + + if (s == NULL) + return NULL; + set = new NameValueSet(); + line = PL_strdup(s); + pair = PL_strtok_r(line, separator, &lasts); + while (pair != NULL) { + len = strlen(pair); + i = 0; + while (1) { + if (i >= len) { + goto skip; + } + if (pair[i] == '\0') { + goto skip; + } + if (pair[i] == '=') { + pair[i] = '\0'; + break; + } + i++; + } + set->Add(&pair[0], &pair[i+1]); +skip: + pair = PL_strtok_r(NULL, separator, &lasts); + } + if( line != NULL ) { + PL_strfree( line ); + line = NULL; + } + return set; +} + +typedef struct { + int index; + char *key; +} Criteria; + +#ifdef __cplusplus +extern "C" +{ +#endif + +static PRIntn CountLoop(PLHashEntry *he, PRIntn index, void *arg) +{ + Criteria *criteria = (Criteria *)arg; + criteria->index++; + return HT_ENUMERATE_NEXT; +} + +static PRIntn Loop(PLHashEntry *he, PRIntn index, void *arg) +{ + Criteria *criteria = (Criteria *)arg; + if (criteria != NULL && index == criteria->index) { + criteria->key = (char *)he->key; + return HT_ENUMERATE_STOP; + } else { + return HT_ENUMERATE_NEXT; + } +} + +#ifdef __cplusplus +} +#endif + +TPS_PUBLIC int NameValueSet::Size() +{ + Criteria criteria; + criteria.index = 0; + criteria.key = NULL; + PL_HashTableEnumerateEntries(m_set, &CountLoop, &criteria); + return criteria.index; +} + +TPS_PUBLIC char *NameValueSet::GetNameAt(int pos) +{ + Criteria criteria; + criteria.index = pos; + criteria.key = NULL; + PL_HashTableEnumerateEntries(m_set, &Loop, &criteria); + return criteria.key; +} + +/** + * Checks if a key is defined. + */ +TPS_PUBLIC int NameValueSet::IsNameDefined(const char *name) +{ + if (GetValue(name) == NULL) + return 0; + else + return 1; +} + +TPS_PUBLIC void NameValueSet::Add(const char *name, const char *value) +{ + if (IsNameDefined(name)) { + PL_HashTableAdd(m_set, PL_strdup(name), PL_strdup(value)); + } else { + PL_HashTableAdd(m_set, PL_strdup(name), PL_strdup(value)); + } +} + +TPS_PUBLIC void NameValueSet::Remove(const char *name) +{ + if (IsNameDefined(name)) { + PL_HashTableRemove(m_set, name); + } +} + +TPS_PUBLIC char *NameValueSet::GetValue(const char *name) +{ + return (char *)PL_HashTableLookupConst(m_set, name); +} + +/** + * Retrieves configuration value as integer. + */ +TPS_PUBLIC int NameValueSet::GetValueAsInt(const char *name) +{ + char *value = NULL; + + value = (char *)GetValue(name); + if (value == NULL) + return 0; + return atoi(value); +} + +/** + * Retrieves configuration value as integer. If name is + * not defined, default value is returned. + */ +TPS_PUBLIC int NameValueSet::GetValueAsInt(const char *name, int def) +{ + char *value = NULL; + + value = (char *)GetValue(name); + if (value == NULL) + return def; + return atoi(value); +} + + +/** + * Retrieves configuration value as boolean. + */ +TPS_PUBLIC int NameValueSet::GetValueAsBool(const char *name) +{ + char *value = NULL; + + value = (char *)GetValue(name); + if (value == NULL) + return 0; + if (PL_CompareStrings("true", value) != 0) + return 1; + else + return 0; +} + +/** + * Retrieves configuration value as boolean. If name is + * not defined, default value is returned. + */ +TPS_PUBLIC int NameValueSet::GetValueAsBool(const char *name, int def) +{ + char *value = NULL; + + value = (char *)GetValue(name); + if (value == NULL) + return def; + if (PL_CompareStrings("true", value) != 0) + return 1; + else + return 0; +} + +/** + * Retrieves configuration value as string. If key is + * not defined, default value is returned. + */ +TPS_PUBLIC char *NameValueSet::GetValueAsString(const char *name, char *def) +{ + char *value = NULL; + + value = (char *)GetValue(name); + if (value == NULL) + return def; + return value; +} + +/** + * Retrieves configuration value as string. + */ +TPS_PUBLIC char *NameValueSet::GetValueAsString(const char *name) +{ + return (char *)GetValue(name); +} + diff --git a/base/tps-client/src/main/ObjectSpec.cpp b/base/tps-client/src/main/ObjectSpec.cpp new file mode 100644 index 000000000..b339fcfa6 --- /dev/null +++ b/base/tps-client/src/main/ObjectSpec.cpp @@ -0,0 +1,528 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <string.h> +#include "prmem.h" +#include "pk11func.h" +#include "main/Buffer.h" +#include "main/ObjectSpec.h" +#include "engine/RA.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +ObjectSpec::ObjectSpec () +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + m_attributeSpec[i] = NULL; + } + m_fixedAttributes = 0; +} + +ObjectSpec::~ObjectSpec () +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] != NULL) { + delete m_attributeSpec[i]; + m_attributeSpec[i] = NULL; + } + } +} + +#define DATATYPE_STRING 0 +#define DATATYPE_INTEGER 1 +#define DATATYPE_BOOL_FALSE 2 +#define DATATYPE_BOOL_TRUE 3 + +/** + * Parse 'c' object. + */ +void ObjectSpec::ParseAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + int curpos = 7; + unsigned long fixedAttrs = 0; + unsigned int xclass = 0; + unsigned int id = 0; + + /* skip first 7 bytes */ + + while (curpos < ((int)(b->size()))) { + unsigned long attribute_id = + (((BYTE*)*b)[curpos] << 24) + + (((BYTE*)*b)[curpos+1] << 16) + + (((BYTE*)*b)[curpos+2] << 8) + + ((BYTE*)*b)[curpos+3]; + unsigned short attribute_size = + (((BYTE*)*b)[curpos+4] << 8) + + ((BYTE*)*b)[curpos+5]; + BYTE type = 0; + Buffer data; + int found = 0; + /* modify fixed attributes */ + + switch (attribute_id) { + case CKA_TOKEN: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000080; + } + break; + case CKA_PRIVATE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000100; + } else { + } + break; + case CKA_MODIFIABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000200; + } + break; + case CKA_DERIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000400; + } + break; + case CKA_LOCAL: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00000800; + } + break; + case CKA_ENCRYPT: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00001000; + } + break; + case CKA_DECRYPT: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00002000; + } + break; + case CKA_WRAP: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00004000; + } + break; + case CKA_UNWRAP: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00008000; + } + break; + case CKA_SIGN: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00010000; + } + break; + case CKA_SIGN_RECOVER: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00020000; + } + break; + case CKA_VERIFY: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00040000; + } + break; + case CKA_VERIFY_RECOVER: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00080000; + } + break; + case CKA_SENSITIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00100000; + } + break; + case CKA_ALWAYS_SENSITIVE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00200000; + } + break; + case CKA_EXTRACTABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00400000; + } + break; + case CKA_NEVER_EXTRACTABLE: + if (((BYTE*)*b)[curpos+6]) { + fixedAttrs |= 0x00800000; + } + break; + case CKA_SUBJECT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_LABEL: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; + case CKA_MODULUS: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_ID: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_KEY_TYPE: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + found = 1; + /* build by PKCS11 */ + break; + case CKA_CLASS: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + xclass = ((BYTE*)data)[0]; + /* build by PKCS11 */ + break; + case CKA_PUBLIC_EXPONENT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + /* build by PKCS11 */ + break; + case CKA_CERTIFICATE_TYPE: + type = DATATYPE_INTEGER; + data = b->substr(curpos+6, 4); + /* build by PKCS11 */ + break; + + case CKA_EC_PARAMS: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; + + case CKA_EC_POINT: + type = DATATYPE_STRING; + data = b->substr(curpos+6, attribute_size); + found = 1; + break; + default: + RA::Debug("ObjectSpec::ParseKeyBlob", + "skipped attribute_id = %lx", + attribute_id); + break; + } + + + if (found) { + /* add attribute spec */ + AttributeSpec *attrSpec = new AttributeSpec(); + attrSpec->SetAttributeID(attribute_id); + attrSpec->SetType(type); + + switch (type) { + case DATATYPE_STRING: + attrSpec->SetData(data); + break; + case DATATYPE_INTEGER: + attrSpec->SetData(data); + break; + case DATATYPE_BOOL_FALSE: + break; + case DATATYPE_BOOL_TRUE: + break; + default: + break; + } + + ObjectSpec->AddAttributeSpec(attrSpec); + } + + + curpos += 4 + 2 + attribute_size; + } + + //Here the objectID fixed attribute gets massaged. Here's how: + // The objectID becomes the cert container id, ex: 01 + // Each key pair associated with the cert must have the same ID. + // This is done by math using the following formula: + // Given a cert id of "2", the keyAttrIds of the keys are originally + // configured as k4 and k5. Note that one is twice the cert id, and + // the other is twice the cert id plus 1. In order to map the key ids + // down to the cert's id, the code below changes both "4" and "5" back + // to "2". + + int val = (objectID[1] - '0'); + switch (objectID[0]) { + case 'c': + id = val; +#if 0 + fixedAttrs |= + 0x00000080 /* CKA_TOKEN */ + ; +#endif + break; + case 'k': + if (val % 2) { + id = (val-1)/2; + } else { + id = (val/2); + } +#if 0 + if (xclass == CKO_PUBLIC_KEY) { + fixedAttrs |= + 0x00000800 /* CKA_LOCAL */ | + 0x00000080 /* CKA_TOKEN */ + ; + } + if (xclass == CKO_PRIVATE_KEY) { + fixedAttrs |= + 0x00000800 /* CKA_LOCAL */ | + 0x00000080 /* CKA_TOKEN */ + ; + } +#endif + break; + } + + ObjectSpec->SetFixedAttributes(fixedAttrs | (xclass << 4) | id); +} + +/** + * Parse 'c' object. + */ +void ObjectSpec::ParseCertificateAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + ParseAttributes(objectID, ObjectSpec, b); +} + +/** + * Parse 'k' object. + */ +void ObjectSpec::ParseKeyAttributes(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + ParseAttributes(objectID, ObjectSpec, b); +} + +/** + * Parse 'C' object. + */ +void ObjectSpec::ParseCertificateBlob(char *objectID, ObjectSpec *ObjectSpec, Buffer *b) +{ + unsigned long fixedAttrs = 0; + unsigned int xclass = 0; + unsigned int id = 0; + + AttributeSpec *value = new AttributeSpec(); + value->SetAttributeID(CKA_VALUE); + value->SetType(DATATYPE_STRING); + value->SetData(*b); + ObjectSpec->AddAttributeSpec(value); + + fixedAttrs = 0x00000080; /* CKA_TOKEN */ + xclass = CKO_CERTIFICATE; + id = objectID[1] - '0'; + + ObjectSpec->SetFixedAttributes(fixedAttrs| (xclass << 4) | id); +} + +/** + * Convert object from token into object spec. + * + * Reference: + * http://netkey/design/applet_readable_object_spec-0.1.txt + * http://netkey/design/pkcs11obj.txt + */ +ObjectSpec *ObjectSpec::ParseFromTokenData(unsigned long objid, Buffer *b) +{ + char objectID[4]; + + ObjectSpec *o = new ObjectSpec(); + o->SetObjectID(objid); + + objectID[0] = (char)((objid >> 24) & 0xff); + objectID[1] = (char)((objid >> 16) & 0xff); + objectID[2] = (char)((objid >> 8) & 0xff); + objectID[3] = (char)((objid) & 0xff); + + switch (objectID[0]) { + case 'c': /* certificate attributes */ + ParseCertificateAttributes(objectID, o, b); + break; + case 'k': /* public key or private key attributes */ + ParseKeyAttributes(objectID, o, b); + break; + case 'C': /* certificate in DER */ + ParseCertificateBlob(objectID, o, b); + break; + default: + RA::Debug("ObjectSpec::ParseKeyBlob", + "unknown objectID = %c", objectID[0]); + /* error */ + break; + } + + return o; +} + +ObjectSpec *ObjectSpec::Parse(Buffer *b, int offset, int *nread) +{ + int sum = 0; + + + if((b->size() - offset) < 10) + return NULL; + + ObjectSpec *o = new ObjectSpec(); + unsigned long id = + (((unsigned char *)*b)[offset + 0] << 24) + + (((unsigned char *)*b)[offset + 1] << 16) + + (((unsigned char *)*b)[offset + 2] << 8) + + (((unsigned char *)*b)[offset + 3]); + + o->SetObjectID(id); + unsigned long attribute = + (((unsigned char *)*b)[offset + 4] << 24) + + (((unsigned char *)*b)[offset + 5] << 16) + + (((unsigned char *)*b)[offset + 6] << 8) + + (((unsigned char *)*b)[offset + 7]); + o->SetFixedAttributes(attribute); + unsigned short count = (((unsigned char *)*b)[offset + 8] << 8) + + ((unsigned char *)*b)[offset + 9]; + sum += 10; + int curpos = offset + 10; + for (int i = 0; i < count; i++) { + int len = 0; + switch (((unsigned char *)*b)[curpos+4]) { + case DATATYPE_STRING: + len = 4 + 1 + 2 + (((unsigned char *)*b)[curpos+5]<<8) + ((unsigned char *)*b)[curpos+6]; + break; + case DATATYPE_INTEGER: + len = 4 + 1 + 4; + break; + case DATATYPE_BOOL_FALSE: + len = 4 + 1; + break; + case DATATYPE_BOOL_TRUE: + len = 4 + 1; + break; + } + Buffer attr = b->substr(curpos, len); + AttributeSpec *attrSpec = AttributeSpec::Parse(&attr, 0); + o->AddAttributeSpec(attrSpec); + curpos += len; + sum += len; + } + *nread = sum; + return o; +} + +void ObjectSpec::SetObjectID(unsigned long v) +{ + m_objectID = v; +} + +unsigned long ObjectSpec::GetObjectID() +{ + return m_objectID; +} + +void ObjectSpec::SetFixedAttributes(unsigned long v) +{ + m_fixedAttributes = v; +} + +unsigned long ObjectSpec::GetFixedAttributes() +{ + return m_fixedAttributes; +} + + +int ObjectSpec::GetAttributeSpecCount() +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] == NULL) { + return i; + } + } + return 0; +} + +AttributeSpec *ObjectSpec::GetAttributeSpec(int p) +{ + if (p < MAX_ATTRIBUTE_SPEC) { + if (m_attributeSpec[p] != NULL) { + return m_attributeSpec[p]; + } + } + return NULL; +} + +void ObjectSpec::AddAttributeSpec(AttributeSpec *p) +{ + for (int i = 0; i < MAX_ATTRIBUTE_SPEC; i++) { + if (m_attributeSpec[i] == NULL) { + m_attributeSpec[i] = p; + return; + } + } +} + +void ObjectSpec::RemoveAttributeSpec(int p) +{ + if (p < MAX_ATTRIBUTE_SPEC) { + if (m_attributeSpec[p] != NULL) { + delete m_attributeSpec[p]; + m_attributeSpec[p] = NULL; + } + // fill hole + int empty = p; + for (int x = p+1; x < MAX_ATTRIBUTE_SPEC; x++) { + if (m_attributeSpec[x] != NULL) { + m_attributeSpec[empty] = m_attributeSpec[x]; + m_attributeSpec[x] = NULL; + empty++; + } + } + } + +} + +Buffer ObjectSpec::GetData() +{ + Buffer data = Buffer(); + + data += Buffer(1, (BYTE)(m_objectID >> 24) & 0xff); + data += Buffer(1, (BYTE)(m_objectID >> 16) & 0xff); + data += Buffer(1, (BYTE)(m_objectID >> 8) & 0xff); + data += Buffer(1, (BYTE)(m_objectID & 0xff)); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 24) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 16) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes >> 8) & 0xff); + data += Buffer(1, (BYTE)(m_fixedAttributes & 0xff)); + + unsigned short attributeCount = GetAttributeSpecCount(); + data += Buffer(1, (attributeCount >> 8) & 0xff); + data += Buffer(1, attributeCount & 0xff); + for (int i = 0; i < attributeCount; i++) { + AttributeSpec *spec = GetAttributeSpec(i); + data += spec->GetData(); + } + + return data; +} diff --git a/base/tps-client/src/main/PKCS11Obj.cpp b/base/tps-client/src/main/PKCS11Obj.cpp new file mode 100644 index 000000000..061dc7a91 --- /dev/null +++ b/base/tps-client/src/main/PKCS11Obj.cpp @@ -0,0 +1,491 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <string.h> +#include "prmem.h" +#include "pk11func.h" +#include "zlib.h" +#include "engine/RA.h" +#include "main/Buffer.h" +#include "main/PKCS11Obj.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +PKCS11Obj::PKCS11Obj () +{ + for (int i = 0; i < MAX_OBJECT_SPEC; i++) { + m_objSpec[i] = NULL; + } +} + +PKCS11Obj::~PKCS11Obj () +{ + for (int i = 0; i < MAX_OBJECT_SPEC; i++) { + if (m_objSpec[i] != NULL) { + delete m_objSpec[i]; + m_objSpec[i] = NULL; + } + } +} + +PKCS11Obj *PKCS11Obj::Parse(Buffer *b, int offset) +{ + PKCS11Obj *o = new PKCS11Obj(); + + unsigned short formatVersion = (((BYTE *)*b)[offset + 0] << 8) + + (((BYTE *)*b)[offset + 1]); + o->SetFormatVersion(formatVersion); + unsigned short objectVersion = (((BYTE *)*b)[offset + 2] << 8) + + + (((BYTE *)*b)[offset + 3]); + o->SetObjectVersion(objectVersion); + o->SetCUID(b->substr(offset + 4, 10)); + + unsigned short compressionType = + (((BYTE *)*b)[offset + 14] << 8) + (((BYTE *)*b)[offset + 15]); + unsigned short compressedDataSize = + (((BYTE *)*b)[offset + 16] << 8) + (((BYTE *)*b)[offset + 17]); +#if 0 + unsigned short compressedDataOffset = + (unsigned short)(((unsigned char *)*b)[offset + 18] << 8) + (((unsigned char *)*b)[offset + 19]); +#endif + + Buffer data; + if (compressionType == 0) { /* no compression */ + data = b->substr(offset + 20, compressedDataSize); + } else if (compressionType == 1) { /* zlib */ + Buffer compressedData = b->substr(offset + 20, compressedDataSize); + +#define MAX_UNCOMPRESS_SIZE 20000 + unsigned char buf[MAX_UNCOMPRESS_SIZE]; + int rc = 0; + uLong len = MAX_UNCOMPRESS_SIZE; + rc = uncompress((Bytef*)buf, (uLongf*)&len, + (Bytef*)((BYTE*)compressedData), + (uLong)compressedData.size()); + RA::Debug("PKCS11Obj::Parse","uncompress ret=%d",rc); + data = Buffer(buf,(unsigned int) len); + } else { + /* error */ + } + + + unsigned short objOffset = (((BYTE *)data)[0] << 8) + + ((BYTE *)data)[1]; + unsigned short objCount = (((BYTE *)data)[2] << 8) + + ((BYTE *)data)[3]; + Buffer tokenName = data.substr(5, ((BYTE *)data)[4]); + o->SetTokenName(tokenName); + + RA::Debug("PKCS11Obj::Parse", "objcount = %d", objCount); + + int curpos = (int)objOffset; + int nread = 0; + for (int i = 0; i < objCount; i++) { + RA::Debug("PKCS11Obj::Parse", "working on object %d", i); + ObjectSpec *objSpec = ObjectSpec::Parse(&data, curpos, &nread); + if(!objSpec) + continue; + o->AddObjectSpec(objSpec); + + unsigned long oid = objSpec->GetObjectID(); + char b[2]; + + b[0] = (char)((oid >> 24) & 0xff); + b[1] = (char)((oid >> 16) & 0xff); + + RA::Debug("PKCS11Obj::Parse", "About to parse = %c%c", b[0],b[1]); + + // add corresponding 'C' object for 'c' + if (b[0] == 'c') { + for (int j = 0; j < objSpec->GetAttributeSpecCount(); + j++) { + AttributeSpec *as = objSpec->GetAttributeSpec(j); + if (as->GetAttributeID() == CKA_VALUE) { + if (as->GetType() == (BYTE) 0) { + Buffer cert = as->GetValue(); + + unsigned long certid = + ('C' << 24) + (b[1] << 16); + ObjectSpec *certSpec = + ObjectSpec::ParseFromTokenData( + certid, &cert); + o->AddObjectSpec(certSpec); + + objSpec->RemoveAttributeSpec(j); + break; + } + } + } + + } + + Buffer objSpecData = objSpec->GetData(); + curpos += nread; + } + + return o; +} + + +void PKCS11Obj::SetFormatVersion(unsigned short v) +{ + m_formatVersion = v; +} + +void PKCS11Obj::SetObjectVersion(unsigned short v) +{ + m_objectVersion = v; +} + +unsigned short PKCS11Obj::GetFormatVersion() +{ + return m_formatVersion; +} + +unsigned short PKCS11Obj::GetObjectVersion() +{ + return m_objectVersion; +} + +void PKCS11Obj::SetCUID(Buffer CUID) +{ + m_CUID = CUID; +} + +Buffer PKCS11Obj::GetCUID() +{ + return m_CUID; +} + +void PKCS11Obj::SetTokenName(Buffer tokenName) +{ + m_tokenName = tokenName; +} + +Buffer PKCS11Obj::GetTokenName() +{ + return m_tokenName; +} + +int PKCS11Obj::GetObjectSpecCount() +{ + for (int i = 0; i < MAX_OBJECT_SPEC; i++) { + if (m_objSpec[i] == NULL) { + return i; + } + } + return 0; +} + +ObjectSpec *PKCS11Obj::GetObjectSpec(int p) +{ + if (p < MAX_OBJECT_SPEC) { + if (m_objSpec[p] != NULL) { + return m_objSpec[p]; + } + } + return NULL; +} + +void PKCS11Obj::AddObjectSpec(ObjectSpec *p) +{ + for (int i = 0; i < MAX_OBJECT_SPEC; i++) { + if (m_objSpec[i] == NULL) { + m_objSpec[i] = p; + return; + } else { + // check duplicated + if (p->GetObjectID() == m_objSpec[i]->GetObjectID()) { + delete m_objSpec[i]; + m_objSpec[i] = p; + return; + } + } + } +} + +void PKCS11Obj::RemoveObjectSpec(int p) +{ + if (p < MAX_OBJECT_SPEC) { + if (m_objSpec[p] != NULL) { + delete m_objSpec[p]; + m_objSpec[p] = NULL; + } + // fill hole + int empty = p; + for (int x = p+1; x < MAX_OBJECT_SPEC; x++) { + if (m_objSpec[x] != NULL) { + m_objSpec[empty] = m_objSpec[x]; + m_objSpec[x] = NULL; + empty++; + } + } + } +} + +Buffer PKCS11Obj::GetData() +{ + Buffer data = Buffer(); + + unsigned short objectOffset = m_tokenName.size() + 2 + 3; + data += Buffer(1, (objectOffset >> 8) & 0xff); + data += Buffer(1, objectOffset & 0xff); + unsigned short objectCount = GetObjectSpecCount(); + unsigned short objectCountX = objectCount; + if (objectCountX == 0) { + objectCountX = 0; + } else { + objectCountX = objectCountX - (objectCountX / 4); + } + data += Buffer(1, (objectCountX >> 8) & 0xff); + data += Buffer(1, objectCountX & 0xff); + data += Buffer(1, m_tokenName.size() & 0xff); + data += m_tokenName; + for (int i = 0; i < objectCount; i++) { + ObjectSpec *spec = GetObjectSpec(i); + unsigned long objectID = spec->GetObjectID(); + char c = (char)((objectID >> 24) & 0xff); + unsigned long fixedAttrs = spec->GetFixedAttributes(); + unsigned int xclass = (fixedAttrs & 0x70) >> 4; + char cont_id = (char) ((objectID >> 16) & 0xff); + unsigned int id = (fixedAttrs & 0x0f); + /* locate all certificate objects */ + if (c == 'c' && xclass == CKO_CERTIFICATE) { + + //We need to use the container id, there may be more than one cert + //with the same CKA_ID byte + + id = (unsigned int) (cont_id - '0'); + + /* locate the certificate object */ + for (int u = 0; u < objectCount; u++) { + ObjectSpec *u_spec = GetObjectSpec(u); + unsigned long u_objectID = u_spec->GetObjectID(); + char u_c = (char)((u_objectID >> 24) & 0xff); + unsigned long u_fixedAttrs = + u_spec->GetFixedAttributes(); + unsigned int u_xclass = (u_fixedAttrs & 0x70) >> 4; + unsigned int u_id = (u_fixedAttrs & 0x0f); + if (u_c == 'C' && u_xclass == CKO_CERTIFICATE && u_id == id) { + AttributeSpec * u_attr = + u_spec->GetAttributeSpec(0); + AttributeSpec * n_attr = new AttributeSpec(); + n_attr->SetAttributeID(u_attr->GetAttributeID()); + n_attr->SetType(u_attr->GetType()); + n_attr->SetData(u_attr->GetValue()); + spec->AddAttributeSpec(n_attr); + } + } + + data += spec->GetData(); + + /* locate public object */ + for (int x = 0; x < objectCount; x++) { + ObjectSpec *x_spec = GetObjectSpec(x); + unsigned long x_fixedAttrs = + x_spec->GetFixedAttributes(); + unsigned int x_xclass = (x_fixedAttrs & 0x70) >> 4; + unsigned int x_id = (x_fixedAttrs & 0x0f); + if (x_xclass == CKO_PUBLIC_KEY && x_id == id) { + data += x_spec->GetData(); + } + } + + /* locate private object */ + for (int y = 0; y < objectCount; y++) { + ObjectSpec *y_spec = GetObjectSpec(y); + unsigned long y_fixedAttrs = + y_spec->GetFixedAttributes(); + unsigned int y_xclass = (y_fixedAttrs & 0x70) >> 4; + unsigned int y_id = (y_fixedAttrs & 0x0f); + if (y_xclass == CKO_PRIVATE_KEY && y_id == id) { + data += y_spec->GetData(); + } + } + } + } + + Buffer header = Buffer(); + header += Buffer(1, (m_formatVersion >> 8) & 0xff); + header += Buffer(1, m_formatVersion & 0xff); + header += Buffer(1, (m_objectVersion >> 8) & 0xff); + header += Buffer(1, m_objectVersion & 0xff); + header += m_CUID; + // COMP_NONE = 0x00 + // COMP_ZLIB = 0x01 + unsigned short compressionType = 0x00; + header += Buffer(1, (compressionType >> 8) & 0xff); + header += Buffer(1, compressionType & 0xff); + unsigned short compressedDataSize = data.size(); + header += Buffer(1, (compressedDataSize >> 8) & 0xff); + header += Buffer(1, compressedDataSize & 0xff); + unsigned short compressedDataOffset = 20; + header += Buffer(1, (compressedDataOffset >> 8) & 0xff); + header += Buffer(1, compressedDataOffset & 0xff); + + return header + data; +} + +Buffer PKCS11Obj::GetCompressedData() +{ + Buffer data = Buffer(); + Buffer error = Buffer(0); + + unsigned short objectOffset = m_tokenName.size() + 2 + 3; + data += Buffer(1, (objectOffset >> 8) & 0xff); + data += Buffer(1, objectOffset & 0xff); + unsigned short objectCount = GetObjectSpecCount(); + unsigned short objectCountX = objectCount; + if (objectCountX == 0) { + objectCountX = 0; + } else { + objectCountX = objectCountX - (objectCountX / 4); + } + data += Buffer(1, (objectCountX >> 8) & 0xff); + data += Buffer(1, objectCountX & 0xff); + data += Buffer(1, m_tokenName.size() & 0xff); + data += m_tokenName; + RA::Debug("PKCS11Obj::GetCompressedData", "object count = %d", objectCount); + for (int i = 0; i < objectCount; i++) { + ObjectSpec *spec = GetObjectSpec(i); + unsigned long objectID = spec->GetObjectID(); + RA::Debug("PKCS11Obj::GetCompressedData", "objid = %lu", objectID); + char c = (char)((objectID >> 24) & 0xff); + unsigned long fixedAttrs = spec->GetFixedAttributes(); + unsigned int xclass = (fixedAttrs & 0x70) >> 4; + char cont_id = (char) ((objectID >> 16) & 0xff); + unsigned int id = (fixedAttrs & 0x0f); + + /* locate all certificate objects */ + if (c == 'c' && xclass == CKO_CERTIFICATE) { + + //We need to use the container id, there may be more than one cert + //with the same CKA_ID byte + + id = (unsigned int) (cont_id - '0'); + + /* locate the certificate object */ + for (int u = 0; u < objectCount; u++) { + ObjectSpec *u_spec = GetObjectSpec(u); + unsigned long u_objectID = u_spec->GetObjectID(); + char u_c = (char)((u_objectID >> 24) & 0xff); + unsigned long u_fixedAttrs = + u_spec->GetFixedAttributes(); + unsigned int u_xclass = (u_fixedAttrs & 0x70) >> 4; + unsigned int u_id = (u_fixedAttrs & 0x0f); + char cont_u_id = (char) ((u_objectID >> 16) & 0xff); + if (u_c == 'C' && u_xclass == CKO_CERTIFICATE && u_id == id) { + RA::Debug("PKCS11Obj::GetCompressedData", "located Certificate id = %d cont_u_id = %c", u_id,cont_u_id); + AttributeSpec * u_attr = + u_spec->GetAttributeSpec(0); + AttributeSpec * n_attr = new AttributeSpec(); + n_attr->SetAttributeID(u_attr->GetAttributeID()); + n_attr->SetType(u_attr->GetType()); + n_attr->SetData(u_attr->GetValue()); + spec->AddAttributeSpec(n_attr); + } + } + + /* output certificate attribute object */ + data += spec->GetData(); + + /* locate public object */ + for (int x = 0; x < objectCount; x++) { + ObjectSpec *x_spec = GetObjectSpec(x); + unsigned long x_fixedAttrs = + x_spec->GetFixedAttributes(); + unsigned int x_xclass = (x_fixedAttrs & 0x70) >> 4; + unsigned int x_id = (x_fixedAttrs & 0x0f); + if (x_xclass == CKO_PUBLIC_KEY && x_id == id) { + RA::Debug("PKCS11Obj::GetCompressedData", "located Public Key = %d", x_id); + data += x_spec->GetData(); + } + + } + + /* locate private object */ + for (int y = 0; y < objectCount; y++) { + ObjectSpec *y_spec = GetObjectSpec(y); + unsigned long y_fixedAttrs = + y_spec->GetFixedAttributes(); + unsigned int y_xclass = (y_fixedAttrs & 0x70) >> 4; + unsigned int y_id = (y_fixedAttrs & 0x0f); + if (y_xclass == CKO_PRIVATE_KEY && y_id == id) { + RA::Debug("PKCS11Obj::GetCompressedData", "located Private Key = %d", y_id); + data += y_spec->GetData(); + } + } + } + } + +#define MAX_COMPRESS_SIZE 50000 + char buffer[MAX_COMPRESS_SIZE]; + unsigned long len = MAX_COMPRESS_SIZE ; + + int rc = 0; + + RA::Debug("PKCS11Obj", "before compress length = %d", len); + + BYTE *src_buffer = (BYTE*)data; + + RA::Debug("PKCS11Obj", "sizeof src_buffer = %d", sizeof(src_buffer)); + RA::Debug("PKCS11Obj", "data size = %d", data.size()); + + rc = compress((Bytef*)buffer, (uLongf*)&len, (Bytef*)src_buffer, + (uLong)data.size()); + + + if(rc != Z_OK) { + RA::Debug("PKCS11Obj", "failure compressing data, possibly buffer overrun! Error: %d ",rc); + + return error; + } + + RA::Debug("PKCS11Obj", "after compress length = %d", len); + RA::Debug("PKCS11Obj", "rc = %d", rc); + + Buffer compressedData = Buffer((BYTE*)buffer, len); + + Buffer header = Buffer(); + header += Buffer(1, (m_formatVersion >> 8) & 0xff); + header += Buffer(1, m_formatVersion & 0xff); + header += Buffer(1, (m_objectVersion >> 8) & 0xff); + header += Buffer(1, m_objectVersion & 0xff); + header += m_CUID; + // COMP_NONE = 0x00 + // COMP_ZLIB = 0x01 + unsigned short compressionType = 0x01; + header += Buffer(1, (compressionType >> 8) & 0xff); + header += Buffer(1, compressionType & 0xff); + unsigned short compressedDataSize = compressedData.size(); + header += Buffer(1, (compressedDataSize >> 8) & 0xff); + header += Buffer(1, compressedDataSize & 0xff); + unsigned short compressedDataOffset = 20; + header += Buffer(1, (compressedDataOffset >> 8) & 0xff); + header += Buffer(1, compressedDataOffset & 0xff); + + return header + compressedData; +} + diff --git a/base/tps-client/src/main/RA_Context.cpp b/base/tps-client/src/main/RA_Context.cpp new file mode 100644 index 000000000..e3a66cdbb --- /dev/null +++ b/base/tps-client/src/main/RA_Context.cpp @@ -0,0 +1,56 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include "main/RA_Msg.h" +#include "main/RA_Context.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +/** + * Constructs a session that represents the + * connection between RA and the netkey client. + */ +TPS_PUBLIC RA_Context::RA_Context () +{ +} + +/** + * Destructs the session. + */ +TPS_PUBLIC RA_Context::~RA_Context () +{ +} + +void RA_Context::LogError(const char *func, int line, const char *fmt,...) +{ +} + +void RA_Context::LogInfo(const char *func, int line, const char *fmt,...) +{ +} + +void RA_Context::InitializationError(const char *func, int line) +{ +} + diff --git a/base/tps-client/src/main/RA_Msg.cpp b/base/tps-client/src/main/RA_Msg.cpp new file mode 100644 index 000000000..d54db69fb --- /dev/null +++ b/base/tps-client/src/main/RA_Msg.cpp @@ -0,0 +1,45 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include "main/RA_Msg.h" +#include "main/Memory.h" + +/** + * Constructs a message that represents the + * message between RA and the netkey client. + */ +RA_Msg::RA_Msg () +{ +} + +/** + * Destructs the message. + */ +RA_Msg::~RA_Msg () +{ +} + +/** + * Retrieves the message type. + */ +RA_Msg_Type RA_Msg::GetType () +{ + return MSG_UNDEFINED; +} diff --git a/base/tps-client/src/main/RA_Session.cpp b/base/tps-client/src/main/RA_Session.cpp new file mode 100644 index 000000000..57f7e4efa --- /dev/null +++ b/base/tps-client/src/main/RA_Session.cpp @@ -0,0 +1,75 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include "engine/RA.h" +#include "main/RA_Msg.h" +#include "main/RA_Session.h" +#include "main/Memory.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +/** + * Constructs a session that represents the + * connection between RA and the netkey client. + */ +TPS_PUBLIC RA_Session::RA_Session () +{ +} + +/** + * Destructs the session. + */ +TPS_PUBLIC RA_Session::~RA_Session () +{ +} + +char *RA_Session::GetRemoteIP() +{ + return NULL; +} + +RA_pblock *RA_Session::create_pblock( char *data ) +{ + // Since this method is virtual, + // report an error if no subclass method has been defined. + RA::Error( "RA_pblock::find_val", + "No subclass method has been defined for this virtual method!" ); + return NULL; +} + +/** + * Reads a message that is sent by + * the client. + */ +RA_Msg *RA_Session::ReadMsg() +{ + return NULL; +} + +/** + * Sends a message to the client. + */ +void RA_Session::WriteMsg(RA_Msg *msg) +{ +} diff --git a/base/tps-client/src/main/RA_pblock.cpp b/base/tps-client/src/main/RA_pblock.cpp new file mode 100644 index 000000000..e59e4c7f1 --- /dev/null +++ b/base/tps-client/src/main/RA_pblock.cpp @@ -0,0 +1,176 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "prmem.h" + +#ifdef __cplusplus +} +#endif + +#include <string.h> +#include "engine/RA.h" +#include "main/Buffer.h" +#include "main/Memory.h" +#include "main/Util.h" +#include "main/RA_pblock.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +TPS_PUBLIC RA_pblock::RA_pblock( int tm_nargs, Buffer_nv** tm_nvs ) +{ + m_nargs = tm_nargs; + + if( tm_nvs != NULL ) { + for( int i = 0; i < MAX_NVS; i++ ) { + m_nvs[i] = tm_nvs[i]; + } + } else { + for( int i = 0; i < MAX_NVS; i++ ) { + m_nvs[i] = NULL; + } + } +} + +TPS_PUBLIC RA_pblock::~RA_pblock() +{ + free_pblock(); +} + +Buffer_nv **RA_pblock::GetNVs() +{ + return m_nvs; +} + +// returns url-decoded value +TPS_PUBLIC Buffer *RA_pblock::find_val( const char * name ) +{ + for( int i = 0; i < m_nargs; i++ ) { + if( i >= MAX_NVS ) { + continue; + } + + if( ( m_nvs[i] == NULL ) || + ( m_nvs[i]->name == NULL ) || + ( m_nvs[i]->value == NULL ) ) { + continue; + } + + if( PR_CompareStrings( m_nvs[i]->name, name ) == 1 ) { + return m_nvs[i]->value; + } + } + + return NULL; +} + +TPS_PUBLIC char *RA_pblock::get_name( int i ) +{ + return m_nvs[i]->name; +} + +TPS_PUBLIC int RA_pblock::get_num_of_names() +{ + return m_nargs; +} + +// returns non-urldecoded value +TPS_PUBLIC char* RA_pblock::find_val_s( const char * name ) +{ + RA::Debug( LL_PER_PDU, "RA_pblock::find_val_s", + "searching for name= %s", name ); + + int end = m_nargs; + + if( MAX_NVS < m_nargs ) { + RA::Error( "RA_pblock::find_val_s", + "MAX_NVS too small, needs increasing... " + "m_nargs= %d, MAX_NVS=%d", m_nargs, MAX_NVS ); + end = MAX_NVS; + } + + for( int i = 0; i < end; i++ ) { + if( ( m_nvs[i] == NULL ) || + ( m_nvs[i]->name == NULL ) || + ( m_nvs[i]->value_s == NULL ) ) { + continue; + } + + /* RA::Debug( LL_PER_PDU, "RA_pblock::find_val_s", */ + /* "found %s", m_nvs[i]->name ); */ + + if( PR_CompareStrings( m_nvs[i]->name, name ) == 1 ) { + return m_nvs[i]->value_s; + } + } + + return NULL; +} + +void RA_pblock::free_pblock() +{ + RA::Debug( LL_PER_PDU, "RA_pblock::free_pblock", "in free_pblock" ); + + int end = m_nargs; + + if( MAX_NVS < m_nargs ) { + RA::Error( "RA_pblock::free_pblock", + "MAX_NVS too small, needs increasing... " + "m_nargs= %d, MAX_NVS=%d", m_nargs, MAX_NVS ); + end = MAX_NVS; + } + + for( int i = 0; i < end ; i++ ) { + if( m_nvs[i] == NULL ) { + continue; + } + + if( m_nvs[i]->value ) { + delete( m_nvs[i]->value ); + m_nvs[i]->value = NULL; + } + + if( m_nvs[i]->value_s ) { + PL_strfree( m_nvs[i]->value_s ); + m_nvs[i]->value_s = NULL; + } + + if( m_nvs[i]->name != NULL ) { + PL_strfree( m_nvs[i]->name ); + m_nvs[i]->name = NULL; + } + + if( m_nvs[i] != NULL ) { + PR_Free( m_nvs[i] ); + m_nvs[i] = NULL; + } + } + + RA::Debug( LL_PER_PDU, "RA_pblock::free_pblock", "in free_pblock done" ); +} + diff --git a/base/tps-client/src/main/RollingLogFile.cpp b/base/tps-client/src/main/RollingLogFile.cpp new file mode 100644 index 000000000..692a94334 --- /dev/null +++ b/base/tps-client/src/main/RollingLogFile.cpp @@ -0,0 +1,493 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2010 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <stdio.h> + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +#ifdef __cplusplus +extern "C" +{ +#endif +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "prmem.h" +#include "prsystem.h" +#include "plstr.h" +#include "prio.h" + +#ifdef __cplusplus +} +#endif + +#include "main/ConfigStore.h" +#include "engine/RA.h" +#include "main/RA_Context.h" +#include "main/LogFile.h" +#include "main/RollingLogFile.h" + +const char *RollingLogFile::CFG_MAX_FILE_SIZE= "maxFileSize"; +const char *RollingLogFile::CFG_ROLLOVER_INTERVAL= "rolloverInterval"; +const char *RollingLogFile::CFG_EXPIRATION_INTERVAL= "expirationTime"; +const int RollingLogFile::MAX_SLEEP = 21600; /* 6 hours */ + +RollingLogFile::RollingLogFile() : + m_max_file_size(2000), + m_rollover_interval(0), + m_expiration_time(0), + m_expiration_sleep_time(0), + m_rotation_needed(false), + m_rollover_thread(NULL), + m_expiration_thread(NULL) { } + +int RollingLogFile::startup(RA_Context *ctx, const char* prefix, const char *fname, bool signed_audit) +{ + char configname[256]; + + if (ctx == NULL) { + return PR_FAILURE; + } + + if (fname == NULL) { + ctx->LogError("RollingLogFile::startup", + __LINE__, + "startup error, fname is NULL"); + return PR_FAILURE; + } + + if (prefix == NULL) { + ctx->LogError("RollingLogFile::startup", + __LINE__, + "startup error for file %s: prefix is NULL", + fname); + return PR_FAILURE; + } + + ConfigStore* store = RA::GetConfigStore(); + + if (store == NULL) { + ctx->LogError("RollingLogFile::startup", + __LINE__, + "Error in obtaining config store to set up rolling log for %s", + fname); + return PR_FAILURE; + } + + PR_snprintf((char *)configname, 256, "%s.%s", prefix, CFG_MAX_FILE_SIZE); + m_max_file_size = store->GetConfigAsInt(configname, 2000); /* 2 MB */ + + PR_snprintf((char *)configname, 256, "%s.%s", prefix, CFG_ROLLOVER_INTERVAL); + m_rollover_interval = store->GetConfigAsInt(configname, 2592000); /* 30 days */ + + PR_snprintf((char *)configname, 256, "%s.%s", prefix, CFG_EXPIRATION_INTERVAL); + m_expiration_time = store->GetConfigAsInt(configname, 0); /* disabled, by default */ + + m_rollover_thread = (PRThread *) NULL; + m_expiration_thread = (PRThread*) NULL; + m_rotation_needed = false; + + LogFile::startup(ctx, prefix, fname, signed_audit); + + m_ctx->LogInfo( "RollingLogFile::startup", + __LINE__, + "thread = 0x%lx: Rolling log file %s startup complete", + PR_GetCurrentThread(), m_fname); + return PR_SUCCESS; +} + +void RollingLogFile::shutdown() +{ + m_ctx->LogInfo( "RollingLogFile::shutdown", + __LINE__, + "thread = 0x%lx: Rolling log file %s shutting down", + PR_GetCurrentThread(), m_fname); + + // interrupt and join threads + + set_expiration_time(0); + if (m_expiration_thread != NULL) { + PR_Interrupt(m_expiration_thread); + PR_JoinThread(m_expiration_thread); + m_expiration_thread = (PRThread*) NULL; + } + + set_rollover_interval(0); + if (m_rollover_thread != NULL) { + PR_Interrupt(m_rollover_thread); + PR_JoinThread(m_rollover_thread); + m_rollover_thread = (PRThread*) NULL; + } + + LogFile::shutdown(); +} + +int RollingLogFile::write(char *msg) { + int status; + PR_EnterMonitor(m_monitor); + + if (m_rotation_needed && m_signed && m_signed_log) { + rotate(); + m_rotation_needed = false; + } + + status = LogFile::write(msg); + if ((get_bytes_written() >= ((int) m_max_file_size*1024)) && (m_max_file_size >0)) { + if (! m_signed_log) { + rotate(); + m_rotation_needed = false; + } else { + m_rotation_needed = true; + } + } + PR_ExitMonitor(m_monitor); + return status; +} + +/* this is always called under a monitor */ +void RollingLogFile::rotate() { + PRTime now; + const char* time_fmt = "%Y%m%d-%H%M%S"; + char datetime[1024]; + char backup_fname[1024]; + char *first_sig = (char *) NULL; + PRExplodedTime time; + int status; + + now = PR_Now(); + PR_ExplodeTime(now, PR_LocalTimeParameters, &time); + PR_FormatTimeUSEnglish(datetime, 1024, time_fmt, &time); + PR_snprintf((char *) backup_fname, 1024, "%s.%s", m_fname, datetime); + + /* close the old file */ + status = LogFile::close(); + if (status != PR_SUCCESS) { + m_ctx->LogError( "RollingLogFile::rotate", + __LINE__, + "Failed to close log file %s", + m_fname); + goto loser; + } else { + m_fd = (PRFileDesc *) NULL; + } + + status = PR_Rename(m_fname, backup_fname); + if (status != PR_SUCCESS) { + m_ctx->LogError( "RollingLogFile::rotate", + __LINE__, + "Failed to rename %s to %s", + m_fname, backup_fname); + + status = LogFile::open(); + if (status != PR_SUCCESS) { + m_ctx->LogError("RollingLogFile::rotate", + __LINE__, + "Failed to reopen log file %s", + m_fname); + } + goto loser; + } + + /* open the new file */ + m_fd = PR_Open(m_fname, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 440|200); + set_bytes_written(0); + if (m_fd == NULL) { + m_ctx->LogError( "RollingLogFile::rotate", + __LINE__, + "Failed to reopen log file %s", + m_fname); + } else { + if (m_signed_log) { + first_sig = RA::GetAuditSigningMessage(""); + if (first_sig != NULL) { + status = LogFile::write(first_sig); + if (status != PR_SUCCESS) { + m_ctx->LogError("RollingLogFile::rotate", + __LINE__, + "Failed to write signature to new (rotated) log file %s", + m_fname); + } else { + status = LogFile::write("\n"); + if (RA::m_last_audit_signature != NULL) { + PR_Free( RA::m_last_audit_signature ); + } + RA::m_last_audit_signature = PL_strdup(first_sig); + m_signed = true; + } + PR_Free(first_sig); + } else { + m_ctx->LogError("RollingLogFile::rotate", + __LINE__, + "Failed to generate signature for new (rotated) log file %s", + m_fname); + } + } + } + + + loser: + m_rotation_needed = false; +} + +void RollingLogFile::child_init() +{ + set_rollover_interval(m_rollover_interval); + set_expiration_time(m_expiration_time); +} + + +void RollingLogFile::set_rollover_interval(int interval) +{ + m_rollover_interval = interval; + if ((m_rollover_interval>0) && (m_rollover_thread == NULL)) { + m_rollover_thread = PR_CreateThread( PR_USER_THREAD, + start_rollover_thread, + (void *) this, + PR_PRIORITY_NORMAL, /* Priority */ + PR_LOCAL_THREAD, /* Scope */ + PR_JOINABLE_THREAD, /* State */ + 0 /* Stack Size */); + + } else { + if (m_rollover_thread != NULL) PR_Interrupt(m_rollover_thread); + } +} + +void RollingLogFile::start_rollover_thread(void *args) { + RollingLogFile *rf; + if (args != NULL) { + rf = (RollingLogFile *) args; + rf->run_rollover_thread(); + } +} + +void RollingLogFile::run_rollover_thread() { + + m_ctx->LogInfo( "RollingLogFile::run_rollover_thread", + __LINE__, + "thread = 0x%lx: Rollover thread for %s starting", + PR_GetCurrentThread(), m_fname); + + while (m_rollover_interval > 0) { + PR_Sleep(PR_SecondsToInterval(m_rollover_interval)); + + PR_EnterMonitor(m_monitor); + if (m_rollover_interval == 0) break; + if (get_bytes_written()>0) { + if (! m_signed_log) { + rotate(); + } else { + m_rotation_needed = true; + } + } + PR_ExitMonitor(m_monitor); + } + + m_ctx->LogInfo( "RollingLogFile::run_rollover_thread", + __LINE__, + "thread = 0x%lx: Rollover thread for %s ending", + PR_GetCurrentThread(), m_fname); + + PR_ExitMonitor(m_monitor); +} + +void RollingLogFile::set_expiration_time(int interval) +{ + m_expiration_time = interval; + m_expiration_sleep_time = interval; + + if ((interval>0) && (m_expiration_thread == NULL)) { + m_expiration_thread = PR_CreateThread( PR_USER_THREAD, + start_expiration_thread, + (void *) this, + PR_PRIORITY_NORMAL, /* Priority */ + PR_GLOBAL_THREAD, /* Scope */ + PR_JOINABLE_THREAD, /* State */ + 0 /* Stack Size */); + + } else { + if (m_expiration_thread != NULL) PR_Interrupt(m_expiration_thread); + } +} + +void RollingLogFile::start_expiration_thread(void *args) { + RollingLogFile *rf; + if (args != NULL) { + rf = (RollingLogFile *) args; + rf->run_expiration_thread(); + } +} + +/* wait for a bit and then call expire(). + Note that PR_Sleep() requires a small interval + (about 6 hrs to prevent overflow) */ +void RollingLogFile::run_expiration_thread() { + int interval; + + m_ctx->LogInfo( "RollingLogFile::run_expiration_thread", + __LINE__, + "thread = 0x%lx: Expiration thread for %s starting", + PR_GetCurrentThread(), m_fname); + + while (m_expiration_time > 0) { + expire(); + while (m_expiration_sleep_time > 0) { + if (m_expiration_sleep_time > MAX_SLEEP) { + interval = MAX_SLEEP; + } else { + interval = m_expiration_sleep_time; + } + + PR_Sleep(PR_SecondsToInterval(interval)); + m_expiration_sleep_time = m_expiration_sleep_time - interval; + + if (m_expiration_time == 0) break; + } + + if (m_expiration_time == 0) break; + } + + m_ctx->LogInfo( "RollingLogFile::run_expiration_thread", + __LINE__, + "thread = 0x%lx: Expiration thread for %s ending", + PR_GetCurrentThread(), m_fname); +} + +/* remove log files that have not been modified in specified time */ +void RollingLogFile::expire() { + char basename[256]; + char dirname[256]; + char searchStr[256]; + char full_search_name[256]; + PRDir *dir; + PRDirEntry *entry; + PRFileInfo info; + PRTime expireTime; + PRTime now; + PRTime earliestModTime; + PRInt64 expiration_interval; + PRInt64 usec_per_sec; + PRInt64 tmp, tmp1; + PRStatus status; + + if (m_expiration_time == 0) { + return; + } + + if (strrchr(m_fname, '/') != NULL) { + PR_snprintf((char *) basename, 256, "%s", strrchr(m_fname, '/') +1); + PR_snprintf((char *) dirname, PL_strlen(m_fname) - PL_strlen(basename), "%s", m_fname); + PL_strcat(dirname, '\0'); + } else { + PR_snprintf((char *) basename, 256, "%s", m_fname); + PR_snprintf((char *) dirname, 256, "."); + } + + LL_I2L(tmp, m_expiration_time); + LL_I2L(usec_per_sec, PR_USEC_PER_SEC); + LL_MUL(expiration_interval, tmp, usec_per_sec); + + now = PR_Now(); + earliestModTime=now; + LL_SUB(expireTime, now, expiration_interval); + + dir = PR_OpenDir(dirname); + + if (dir == NULL) { + m_ctx->LogError( "RollingLogFile::expire", + __LINE__, + "Failed to open log file directory %s", + dirname); + return; + } + + PR_snprintf(searchStr, 256, "%s.", basename); + + while ((entry=PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) { + /* look only for entries of form basename. */ + + if (PL_strstr(entry->name, searchStr) != NULL) { + PR_snprintf(full_search_name, 256, "%s/%s", dirname, entry->name); + status = PR_GetFileInfo(full_search_name, &info); + + if (status != PR_SUCCESS) { + m_ctx->LogError( "RollingLogFile::expire", + __LINE__, + "Failed to get file info for log file %s", + full_search_name); + // log failure to get file info + } else { + if (LL_CMP(info.modifyTime,<, expireTime)) { + status = PR_Delete(full_search_name); + if (status != PR_SUCCESS) { + m_ctx->LogError( "RollingLogFile::expire", + __LINE__, + "Failed to delete expired log file %s", + full_search_name); + } else { + RA::Debug("RollingLogFile::expire", "Deleted expired file: %s", + full_search_name); + } + } else { + if (LL_CMP(info.modifyTime,<,earliestModTime)) { + earliestModTime = info.modifyTime; + } + } + } + } + } + + PR_CloseDir(dir); + + /* set next wakeup interval */ + /* A complicated 64-bit way of calculating : + m_expiration_sleep_time = (earliestModTime + m_expiration_time * 1000000 - PR_Now())/1000000; + */ + + LL_ADD(tmp, earliestModTime, expiration_interval); + LL_SUB(tmp1, tmp, now); + LL_DIV(tmp, tmp1, usec_per_sec); + LL_L2I(m_expiration_sleep_time, tmp); + +} + +int RollingLogFile::get_rollover_interval() { + return m_rollover_interval; +} + +void RollingLogFile::set_rotation_needed(bool val) { + m_rotation_needed = val; +} + +bool RollingLogFile::get_rotation_needed() { + return m_rotation_needed; +} + +int RollingLogFile::get_expiration_time() { + return m_expiration_time; +} + + diff --git a/base/tps-client/src/main/SecureId.cpp b/base/tps-client/src/main/SecureId.cpp new file mode 100644 index 000000000..46394100e --- /dev/null +++ b/base/tps-client/src/main/SecureId.cpp @@ -0,0 +1,71 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include "plstr.h" +#include "main/SecureId.h" +#include "main/Memory.h" + +/** + * Creates a Secure ID object. + */ +SecureId::SecureId (char *value, char *pin) +{ + if (value == NULL) { + m_value = NULL; + } else { + m_value = PL_strdup(value); + } + if (pin == NULL) { + m_pin = NULL; + } else { + m_pin = PL_strdup(pin); + } +} + +/** + * Destructs a Secure ID object. + */ +SecureId::~SecureId () +{ + if( m_value != NULL ) { + PL_strfree( m_value ); + m_value = NULL; + } + if( m_pin != NULL ) { + PL_strfree( m_pin ); + m_pin = NULL; + } +} + +/** + * Retrieves the optional Secure ID value. + */ +char *SecureId::GetValue() +{ + return m_value; +} + +/** + * Retrieves the Secure ID PIN. + */ +char *SecureId::GetPIN() +{ + return m_pin; +} diff --git a/base/tps-client/src/main/Util.cpp b/base/tps-client/src/main/Util.cpp new file mode 100644 index 000000000..2849121e4 --- /dev/null +++ b/base/tps-client/src/main/Util.cpp @@ -0,0 +1,1168 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301 USA +// +// Copyright (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +#include <string.h> +#include "prmem.h" +#include "prio.h" +#include "pk11func.h" +#include "main/Util.h" +#include "main/Buffer.h" +#include "engine/RA.h" +#include "main/Memory.h" + +#ifdef XP_WIN32 +#define TPS_PUBLIC __declspec(dllexport) +#else /* !XP_WIN32 */ +#define TPS_PUBLIC +#endif /* !XP_WIN32 */ + +TPS_PUBLIC Util::Util () +{ +} + +TPS_PUBLIC Util::~Util () +{ +} + +/* + * Reads a line from file + */ +TPS_PUBLIC int Util::ReadLine(PRFileDesc *f, char *buf, int buf_len, int *removed_return) +{ + char *cur = buf; + int sum = 0; + PRInt32 rc; + + *removed_return = 0; + while (1) { + rc = PR_Read(f, cur, 1); + if (rc == -1 || rc == 0) + break; + if (*cur == '\r') { + continue; + } + if (*cur == '\n') { + *cur = '\0'; + *removed_return = 1; + break; + } + sum++; + cur++; + } + return sum; +} + +TPS_PUBLIC int Util::ascii2numeric (char c) +{ + int num; + switch (c) { + case '0': case '1': case '2':case '3':case '4':case '5': + case '6': case '7': case '8': case '9': + num = c - '0'; + break; + default: + num = -1; + break; + } + return num; +} + +static BYTE ZERO[1] = { 0 }; +static BYTE ONE[1] = { 1 }; + +TPS_PUBLIC BYTE* Util::bool2byte(bool b) { + if (b) + return ONE; + else + return ZERO; +} + +static int isAlphaNumeric (char ch) +{ + return (((ch >='a') && (ch <= 'z')) || /* logical AND &&, OR || */ + ((ch >='A') && (ch <= 'Z')) || + ((ch >='0') && (ch <= '9')) ); +} + +static char bin2hex (BYTE ch) +{ + ch = ch & 0x0f; + ch += '0'; + if (ch > '9') + ch += 7; + return (ch); +} + +static BYTE hex2bin (BYTE ch) +{ + if (ch > '9') + ch = ch - 'A' + 10; + else + ch = ch - '0'; + return (ch); +} + + +TPS_PUBLIC char *Util::SpecialURLEncode(Buffer &data) { + int i; + BYTE *buf = (BYTE*)data; + int len = (int)data.size(); + char *ret = NULL; + int sum = 0; + + for (i = 0; i < len; i ++) { + if (buf[i] == ' ') { + sum+=1; + } else if (isAlphaNumeric(buf[i])) { + sum+=1; + } else { + sum+=3; + } + } + ret = (char *)PR_Malloc(sum + 1); // allocate more than we may need + if (ret == NULL) + return NULL; + char *cur = ret; + + for (i = 0; i < len; i ++) { + if (buf[i] == ' ') { + *cur++ = '+'; + } else if (isAlphaNumeric(buf[i])) { + *cur++ = buf[i]; + } else { + *cur++ = '#'; + *cur++ = bin2hex(buf[i] >> 4); + *cur++ = bin2hex(buf[i]); + } + } + *cur = '\0'; // null-terminated + return ret; +} + +TPS_PUBLIC char *Util::URLEncode (Buffer &data) +{ + int i; + BYTE *buf = (BYTE*)data; + int len = (int)data.size(); + int sum = 0; + + for (i = 0; i < len; i ++) { + if (buf[i] == ' ') { + sum+=1; + } else if (isAlphaNumeric(buf[i])) { + sum+=1; + } else { + sum+=3; + } + } + char *ret = (char *)PR_Malloc(sum + 1); // allocate more than we may need + char *cur = ret; + + for (i = 0; i < len; i ++) { + if (buf[i] == ' ') { + *cur++ = '+'; + } else if (isAlphaNumeric(buf[i])) { + *cur++ = buf[i]; + } else { + *cur++ = '%'; + *cur++ = bin2hex(buf[i] >> 4); + *cur++ = bin2hex(buf[i]); + } + } + *cur = '\0'; // null-terminated + return ret; +} + +TPS_PUBLIC char *Util::URLEncodeInHex (Buffer &data) +{ + int i; + BYTE *buf = (BYTE*)data; + int len = (int)data.size(); + int sum = 0; + + for (i = 0; i < len; i ++) { + sum+=3; + } + + char *ret = (char *)PR_Malloc(sum + 1); // allocate more than we may need + char *cur = ret; + + for (i = 0; i < len; i ++) { + *cur++ = '%'; + *cur++ = bin2hex(buf[i] >> 4); + *cur++ = bin2hex(buf[i]); + } + *cur = '\0'; // null-terminated + return ret; +} + +TPS_PUBLIC char * Util::URLEncode1(const char *str) +{ + int sum = 0; + if (str == NULL) + return NULL; + + // URL-encode the base-64 encoded public key. This code copies + // From input buffer str[] to output buffer encoded_str[] + int i = 0; + int j = 0; + char c; + + i = 0; + j = 0; + while (1) { + c = str[j]; + if (c == '/') { + sum+=3; + } else if (c == '=') { + sum+=3; + } else if (c == '\r') { + sum+=3; + } else if (c == '\n') { + sum+=3; + } else if (c == '+') { + sum+=3; + } else if (c == '&') { + sum+=3; + } else if (c == ' ') { + sum+=1; + } else { + sum+=1; + } + if (c == '\0') { + break; + } + i++; + j++; + } + + char *encoded_str = (char *)PR_Malloc(sum); //allocate more than we may need + + if (encoded_str == NULL) + return NULL; + + i = 0; + j = 0; + while (1) { + c = str[j]; + if (c == '/') { + encoded_str[i++] = '%'; + encoded_str[i++] = '2'; + encoded_str[i] = 'F'; + } else if (c == '&') { + encoded_str[i++] = '%'; + encoded_str[i++] = '2'; + encoded_str[i] = '6'; + } else if (c == '=') { + encoded_str[i++] = '%'; + encoded_str[i++] = '3'; + encoded_str[i] = 'D'; + } else if (c == '\r') { + encoded_str[i++] = '%'; + encoded_str[i++] = '0'; + encoded_str[i] = 'D'; + } else if (c == '\n') { + encoded_str[i++] = '%'; + encoded_str[i++] = '0'; + encoded_str[i] = 'A'; + } else if (c == '+') { + encoded_str[i++] = '%'; + encoded_str[i++] = '2'; + encoded_str[i] = 'B'; + } else if (c == ' ') { + encoded_str[i] = '+'; + } else { + encoded_str[i] = str[j]; + } + if (encoded_str[i] == '\0') { + break; + } + i++; + j++; + } + encoded_str[i] = '\0'; + + // DONT print, some of the sensitive information get printed. + /* + RA::Debug(LL_PER_PDU, "CertEnroll::urlEncode", + "URL-encoded encoded_str =%s",encoded_str); + */ + + return encoded_str; +} +/** + * this urlEncode function takes a char string + */ +TPS_PUBLIC char * Util::URLEncode(const char *str) +{ + int sum = 0; + if (str == NULL) + return NULL; + + // URL-encode the base-64 encoded public key. This code copies + // From input buffer str[] to output buffer encoded_str[] + int i = 0; + int j = 0; + char c; + + i = 0; + j = 0; + while (1) { + c = str[j]; + if (c == '/') { + sum+=3; + } else if (c == '=') { + sum+=3; + } else if (c == '\r') { + sum+=3; + } else if (c == '\n') { + sum+=3; + } else if (c == '+') { + sum+=3; + } else if (c == ' ') { + sum+=1; + } else { + sum+=1; + } + if (c == '\0') { + break; + } + i++; + j++; + } + + char *encoded_str = (char *)PR_Malloc(sum); //allocate more than we may need + + if (encoded_str == NULL) + return NULL; + + i = 0; + j = 0; + while (1) { + c = str[j]; + if (c == '/') { + encoded_str[i++] = '%'; + encoded_str[i++] = '2'; + encoded_str[i] = 'F'; + } else if (c == '=') { + encoded_str[i++] = '%'; + encoded_str[i++] = '3'; + encoded_str[i] = 'D'; + } else if (c == '\r') { + encoded_str[i++] = '%'; + encoded_str[i++] = '0'; + encoded_str[i] = 'D'; + } else if (c == '\n') { + encoded_str[i++] = '%'; + encoded_str[i++] = '0'; + encoded_str[i] = 'A'; + } else if (c == '+') { + encoded_str[i++] = '%'; + encoded_str[i++] = '2'; + encoded_str[i] = 'B'; + } else if (c == ' ') { + encoded_str[i] = '+'; + } else { + encoded_str[i] = str[j]; + } + if (encoded_str[i] == '\0') { + break; + } + i++; + j++; + } + encoded_str[i] = '\0'; + + // DONT print, some of the sensitive information get printed. + /* + RA::Debug(LL_PER_PDU, "CertEnroll::urlEncode", + "URL-encoded encoded_str =%s",encoded_str); + */ + + return encoded_str; +} + +/* s Format: 01AFEE */ +TPS_PUBLIC Buffer *Util::Str2Buf (const char *s) +{ + int len = strlen(s) / 2; + BYTE *ret = (BYTE *)PR_Malloc(len); + if (ret == NULL) + return NULL; + + for (int i = 0; i < len; i ++) { + ret[i] = hex2bin(s[i*2]) * 16 + hex2bin(s[i*2+1]); + } + + Buffer *newbuf = new Buffer(ret, len); + if( ret != NULL ) { + PR_Free( ret ); + ret = NULL; + } + return newbuf; +} + +TPS_PUBLIC char *Util::Buffer2String (Buffer &data) +{ + int i; + BYTE *buf = (BYTE*)data; + int len = (int)data.size(); + int sum = 0; + + for (i = 0; i < len; i ++) { + sum+=2; + } + char *ret = (char *)PR_Malloc(sum + 1); // allocate more than we may need + if (ret == NULL) + return NULL; + char *cur = ret; + + for (i = 0; i < len; i ++) { + *cur++ = bin2hex(buf[i] >> 4); + *cur++ = bin2hex(buf[i]); + } + *cur = '\0'; // null-terminated + return ret; +} + +TPS_PUBLIC Buffer *Util::SpecialURLDecode(const char *data) +{ + int i; + Buffer buf; + Buffer *ret = NULL; + int len = strlen(data); + BYTE *tmp = NULL; + int sum = 0; + + if (len == 0) + return NULL; + tmp = (BYTE *)malloc(len); + if (tmp == NULL) + return NULL; + for (i = 0; i < len; i++) { + if (data[i] == '+') { + tmp[sum++] = ' '; + } else if (data[i] == '#') { + tmp[sum++] = (hex2bin(data[i+1]) << 4) + hex2bin(data[i+2]); + i+=2; + } else { + tmp[sum++] = (BYTE)data[i]; + } + } + + ret = new Buffer(tmp, sum); + if( tmp != NULL ) { + free( tmp ); + tmp = NULL; + } + return ret; +} + +TPS_PUBLIC Buffer *Util::URLDecode(const char *data) +{ + int i; + Buffer buf; + Buffer *ret = NULL; + int len = strlen(data); + BYTE *tmp = NULL; + int sum = 0; + + if (len == 0) + return NULL; + tmp = (BYTE *)PR_Malloc(len); + for (i = 0; i < len; i++) { + if (data[i] == '+') { + tmp[sum++] = ' '; + } else if (data[i] == '%') { + tmp[sum++] = (hex2bin(data[i+1]) << 4) + hex2bin(data[i+2]); + i+=2; + } else { + tmp[sum++] = (BYTE)data[i]; + } + } + + ret = new Buffer(tmp, sum); + if( tmp != NULL ) { + PR_Free( tmp ); + tmp = NULL; + } + return ret; +} + + +TPS_PUBLIC PRStatus Util::GetRandomChallenge(Buffer &random) +{ + PRStatus rv = PR_FAILURE; + SECStatus status; + + status = PK11_GenerateRandom(random, random.size()); + if (status != SECSuccess) { + goto loser; + } + rv = PR_SUCCESS; +loser: + return rv; +} /* GetRandomChallenge */ + +#define DES2_WORKAROUND + +TPS_PUBLIC PK11SymKey *Util::DiversifyKey(PK11SymKey *masterKey, Buffer &data, PK11SlotInfo *slot) +{ + PK11SymKey *key = NULL; + PRStatus status = PR_FAILURE ; + PK11Context *context = NULL; +#ifdef DES2_WORKAROUND + unsigned char keyData[24]; +#else + unsigned char keyData[16]; +#endif + SECItem keyItem = { siBuffer, keyData, sizeof keyData }; + SECStatus s; + int i; + int len; + static SECItem noParams = { siBuffer, 0, 0 }; + + /* XXX + - masterKey could be just a double-length + DES Key (16 bytes). + - we may need to add the first 8 bytes to + the end to make the key 24 bytes long (DES3 Key) + */ + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, + masterKey, + &noParams); + if (!context) goto done; + + /* Part 1 */ + s = PK11_CipherOp(context, &keyData[0], &len, 8, &((BYTE*)data)[0], 8); + if (s != SECSuccess) goto done; + + /* Part 2 */ + s = PK11_CipherOp(context, &keyData[8], &len, 8, &((BYTE*)data)[8], 8); + if (s != SECSuccess) goto done; + +#ifdef DES2_WORKAROUND + /* Part 3 */ + for(i = 0;i < 8;i++) + { + keyData[i+16] = keyData[i]; + } +#endif + + key = PK11_ImportSymKeyWithFlags( + slot, + CKM_DES3_ECB, + PK11_OriginGenerated, + CKA_ENCRYPT, + &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); + + status = PR_SUCCESS; + +done: + + return key; +} + +TPS_PUBLIC PRStatus Util::ComputeKeyCheck(const Buffer& newKey, Buffer& output) +{ + PK11SymKey *key = NULL; + PRStatus status = PR_FAILURE ; + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + PK11Context *context = NULL; + SECStatus s = SECFailure; + int len; + static SECItem noParams = { siBuffer, 0, 0 }; +#ifdef DES2_WORKAROUND + unsigned char keyData[24]; +#else + unsigned char keyData[16]; +#endif + SECItem keyItem = {siBuffer, keyData, sizeof(keyData) }; + unsigned char value[8]; + // convert 16-byte to 24-byte triple-DES key + memcpy(keyData, newKey, 16); +#ifdef DES2_WORKAROUND + memcpy(keyData+16, newKey, 8); +#endif + + memset(value, 0, sizeof value); + + key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, + PK11_OriginGenerated, CKA_ENCRYPT, &keyItem, + CKF_ENCRYPT, PR_FALSE, 0); + if( ! key ) { + goto done; + } + + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, + &noParams); + if (!context) { + goto done; + } + s = PK11_CipherOp(context, &value[0], &len, 8, &value[0], 8); + if (s != SECSuccess) { + goto done; + } + + output.resize(3); + output.replace(0, value, 3); + + status = PR_SUCCESS; +done: + memset(keyData, 0, sizeof keyData); + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + if( slot != NULL ) { + PK11_FreeSlot( slot ); + slot = NULL; + } + if( key != NULL ) { + PK11_FreeSymKey( key ); + key = NULL; + } + + return status; +} + +TPS_PUBLIC PRStatus Util::ComputeCryptogram(PK11SymKey *key, + const Buffer &card_challenge, const Buffer &host_challenge, + Buffer &output) +{ + Buffer icv(8, (BYTE)0); + Buffer input = card_challenge + host_challenge; + + return ComputeMAC(key, input, icv, output); +} /* ComputeCryptogram */ + + +TPS_PUBLIC PRStatus Util::ComputeMAC(PK11SymKey *key, Buffer &x_input, + const Buffer &icv, Buffer &output) +{ + PRStatus rv = PR_SUCCESS; + PK11Context *context = NULL; +// NetkeyICV temp; + unsigned char result[8]; + int i; + SECStatus s; + int len; +#ifdef USE_DESMAC + CK_ULONG macLen = sizeof result; + SECItem params = { siBuffer, (unsigned char *)&macLen, sizeof macLen }; +#endif + static SECItem noParams = { siBuffer, 0, 0 }; + static unsigned char macPad[] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + BYTE *input = (BYTE *) x_input; + int inputLen = x_input.size(); + +#ifdef USE_DESMAC + context = PK11_CreateContextBySymKey(CKM_DES3_MAC_GENERAL, CKA_SIGN, + key, ¶ms); + if (!context) { rv = PR_FAILURE; goto done; } + + s = PK11_DigestBegin(context); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + + s = PK11_DigestOp(context, icv, 8); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + + while(inputLen >= 8) + { + s = PK11_DigestOp(context, input, 8); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + + input += 8; + inputLen -= 8; + } + + for (i = 0;i < inputLen;i++) + { + result[i] = input[i]; + } + + input = macPad; + for(;i < 8;i++) + { + result[i] = *input++; + } + + s = PK11_DigestOp(context, result, sizeof result); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + + s = PK11_DigestFinal(context, output, (unsigned int *)&len, sizeof output); + if (1 != SECSuccess) { rv = PR_FAILURE; goto done; } + +#else + + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams); + if (!context) { rv = PR_FAILURE; goto done; } + + memcpy(result, icv, sizeof result); + + /* Process whole blocks */ + while(inputLen >= 8) + { + for(i = 0;i < 8;i++) + { + result[i] ^= input[i]; + } + + s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + if (len != sizeof result) /* assert? */ + { + //PR_SetError(PR_UNKNOWN_ERROR, 0); + rv = PR_FAILURE; + goto done; + } + + input += 8; + inputLen -= 8; + } + + /* + * Fold in remaining data (if any) + * Set i to number of bytes processed + */ + for(i = 0;i < inputLen;i++) + { + result[i] ^= input[i]; + } + + /* + * Fill remainder of last block. There + * will be at least one byte handled here. + */ + input = macPad; + while(i < 8) + { + result[i] ^= *input++; + i++; + } + + s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result); + if (s != SECSuccess) { rv = PR_FAILURE; goto done; } + if (len != sizeof result) + { + //PR_SetError(PR_UNKNOWN_ERROR, 0); + rv = PR_FAILURE; + goto done; + } + + output.replace(0, result, sizeof result); +#endif + +done: + if( context != NULL ) + { + PK11_Finalize( context ); + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + memset(result, 0, sizeof result); + + return rv; +} /* ComputeMAC */ + +TPS_PUBLIC PK11SymKey *Util::DeriveKey(const Buffer& permKey, + const Buffer& hostChallenge, + const Buffer& cardChallenge) +{ + PK11SymKey *key = NULL, *master = NULL; + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + PK11Context *context = NULL; + unsigned char derivationData[16]; +#ifdef DES2_WORKAROUND + unsigned char keyData[24]; +#else + unsigned char keyData[16]; +#endif + int i; + SECStatus s; + int len; + SECItem keyItem = { siBuffer, keyData, sizeof keyData }; + static SECItem noParams = { siBuffer, 0, 0 }; + BYTE masterKeyData[24]; + SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; + + // convert 16-byte to 24-byte triple-DES key + memcpy(masterKeyData, permKey, 16); + memcpy(masterKeyData+16, permKey, 8); + + master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, + PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, + CKF_ENCRYPT, PR_FALSE, 0); + if( ! master ) goto done; + + for(i = 0;i < 4;i++) + { + derivationData[i] = cardChallenge[i+4]; + derivationData[i+4] = hostChallenge[i]; + derivationData[i+8] = cardChallenge[i]; + derivationData[i+12] = hostChallenge[i+4]; + } + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, + &noParams); + if (!context) goto done; + + /* Part 1 */ + s = PK11_CipherOp(context, &keyData[0], &len, 8, &derivationData[0], 8); + if (s != SECSuccess) goto done; + + /* Part 2 */ + s = PK11_CipherOp(context, &keyData[8], &len, 8, &derivationData[8], 8); + if (s != SECSuccess) goto done; + +#ifdef DES2_WORKAROUND + /* Part 3 */ + for(i = 0;i < 8;i++) + { + keyData[i+16] = keyData[i]; + } +#endif + + key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated, + CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0); + +done: + memset(keyData, 0, sizeof keyData); + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + if( slot != NULL ) { + PK11_FreeSlot( slot ); + slot = NULL; + } + if( master != NULL ) { + PK11_FreeSymKey( master ); + master = NULL; + } + + return key; +} + +/** + * + * 01 + * 81 10 B4 BA A8 9A 8C D0 29 2B 45 21 0E (AUTH KEY) + * 1B C8 4B 1C 31 + * 03 8B AF 47 + * 81 10 B4 BA A8 9A 8C D0 29 2B 45 21 0E (MAC KEY) + * 1B C8 4B 1C 31 + * 03 8B AF 47 + * 81 10 B4 BA A8 9A 8C D0 29 2B 45 21 0E (KEK KEY) + * 1B C8 4B 1C 31 + * 03 8B AF 47 + * + */ +TPS_PUBLIC PRStatus Util::CreateKeySetData(Buffer &newMasterVer, Buffer &old_kek_key, Buffer &new_auth_key, Buffer &new_mac_key, Buffer &new_kek_key, Buffer &output) +{ + PRStatus rv = PR_FAILURE; + + Buffer result; + + Buffer encrypted_auth_key(16); + Util::EncryptData(old_kek_key, new_auth_key, encrypted_auth_key); + Buffer kc_auth_key(3); + Util::ComputeKeyCheck(new_auth_key, kc_auth_key); + Buffer encrypted_mac_key(16); + Util::EncryptData(old_kek_key, new_mac_key, encrypted_mac_key); + Buffer kc_mac_key(3); + Util::ComputeKeyCheck(new_mac_key, kc_mac_key); + Buffer encrypted_kek_key(16); + Util::EncryptData(old_kek_key, new_auth_key, encrypted_kek_key); + Buffer kc_kek_key(3); + Util::ComputeKeyCheck(new_kek_key, kc_kek_key); + + result = newMasterVer + + Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)0x10) + + encrypted_auth_key + + Buffer(1, (BYTE)0x03) + + kc_auth_key + + Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)0x10) + + encrypted_mac_key + + Buffer(1, (BYTE)0x03) + + kc_mac_key + + Buffer(1, (BYTE)0x81) + + Buffer(1, (BYTE)0x10) + + encrypted_kek_key + + Buffer(1, (BYTE)0x03) + + kc_kek_key; + + output = result; + + rv = PR_SUCCESS; + return rv; +} + + +/* + * for Secure Messaging in Secure Channel + */ +TPS_PUBLIC PRStatus Util::EncryptData(PK11SymKey *encSessionKey, + Buffer &input, Buffer &output) +{ + PRStatus rv = PR_FAILURE; + SECStatus s = SECFailure; + //static SECItem noParams = { siBuffer, 0, 0 }; + static unsigned char d[8] = { 0,0,0,0,0,0,0,0 }; + static SECItem ivParams = { siBuffer, d, 8 }; + PK11Context *context = NULL; + unsigned char result[8]; + int len; + int i; + + /* this is ECB mode + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, encSessionKey, + &noParams); + */ + // use CBC mode + context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_ENCRYPT, encSessionKey, + &ivParams); + if (!context) { + goto done; + } + + for(i = 0;i < (int)input.size();i += 8) { + s = PK11_CipherOp(context, result, &len, 8, + (unsigned char *)(((BYTE*)input)+i), 8); + + if (s != SECSuccess) { + goto done; + } + output.replace(i, result, 8); + } + + rv = PR_SUCCESS; +// RA::Debug("Util::EncryptData", "success"); +done: + + //#define VRFY_ENC_SESSION_KEY + // fix this to use CBC mode later +#ifdef VRFY_ENC_SESSION_KEY + Buffer enc_key_buffer = Buffer((BYTE *) PK11_GetKeyData(encSessionKey)->data, PK11_GetKeyData(encSessionKey)->len); + RA::DebugBuffer("Util::EncryptData", "Verifying Encrypted Data", + &output); + Buffer out1 = Buffer(16, (BYTE)0); + PRStatus status = Util::DecryptData(enc_key_buffer, output, out1); + RA::DebugBuffer("Util::EncryptData", "Decrypted Data", + &out1); +#endif + + + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + + return rv; +} + + +TPS_PUBLIC PRStatus Util::EncryptData(Buffer &kek_key, Buffer &input, Buffer &output) +{ + PRStatus rv = PR_FAILURE; + + PK11SymKey *master = NULL; + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + PK11Context *context = NULL; + int i; + SECStatus s = SECFailure; + int len; + static SECItem noParams = { siBuffer, 0, 0 }; +#ifdef DES2_WORKAROUND + unsigned char masterKeyData[24]; +#else + unsigned char masterKeyData[16]; +#endif + SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; + unsigned char result[8]; + + // convert 16-byte to 24-byte triple-DES key + memcpy(masterKeyData, (BYTE*)kek_key, 16); +#ifdef DES2_WORKAROUND + memcpy(masterKeyData+16, (BYTE*)kek_key, 8); +#endif + + master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, + PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem, + CKF_ENCRYPT, PR_FALSE, 0); + if( ! master ) { + goto done; + } + + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master, + &noParams); + if (!context) { + goto done; + } + + for(i = 0;i < (int)input.size();i += 8) { + s = PK11_CipherOp(context, result, &len, 8, + (unsigned char *)(((BYTE*)input)+i), 8); + + if (s != SECSuccess) { + goto done; + } + output.replace(i, result, 8); + } + + rv = PR_SUCCESS; + +done: + + memset(masterKeyData, 0, sizeof masterKeyData); + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + if( slot != NULL ) { + PK11_FreeSlot( slot ); + slot = NULL; + } + if( master != NULL ) { + PK11_FreeSymKey( master ); + master = NULL; + } + + return rv; +} + +TPS_PUBLIC PRStatus Util::DecryptData(Buffer &kek_key, Buffer &input, Buffer &output) +{ + PRStatus rv = PR_FAILURE; + + PK11SymKey *master = NULL; + PK11SlotInfo *slot = PK11_GetInternalKeySlot(); + PK11Context *context = NULL; + int i; + SECStatus s = SECFailure; + int len; + static SECItem noParams = { siBuffer, 0, 0 }; +#ifdef DES2_WORKAROUND + unsigned char masterKeyData[24]; +#else + unsigned char masterKeyData[16]; +#endif + SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) }; + unsigned char result[8]; + + // convert 16-byte to 24-byte triple-DES key + memcpy(masterKeyData, (BYTE*)kek_key, 16); +#ifdef DES2_WORKAROUND + memcpy(masterKeyData+16, (BYTE*)kek_key, 8); +#endif + + master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, + PK11_OriginGenerated, CKA_DECRYPT, &masterKeyItem, + CKF_DECRYPT, PR_FALSE, 0); + if( ! master ) { + goto done; + } + + context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_DECRYPT, master, + &noParams); + if (!context) { + goto done; + } + + for(i = 0;i < (int)input.size();i += 8) { + s = PK11_CipherOp(context, result, &len, 8, + (unsigned char *)(((BYTE *)input)+i), 8); + + if (s != SECSuccess) { + goto done; + } + output.replace(i, result, 8); + } + + rv = PR_SUCCESS; + +done: + + memset(masterKeyData, 0, sizeof masterKeyData); + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + if( slot != NULL ) { + PK11_FreeSlot( slot ); + slot = NULL; + } + if( master != NULL ) { + PK11_FreeSymKey( master ); + master = NULL; + } + + return rv; +} + +// this one takes PK11SymKey instead +TPS_PUBLIC PRStatus Util::DecryptData(PK11SymKey* enc_key, Buffer &input, Buffer &output) +{ + PRStatus rv = PR_FAILURE; + + PK11Context *context = NULL; + int i; + SECStatus s = SECFailure; + int len; + // static SECItem noParams = { siBuffer, 0, 0 }; + static unsigned char d[8] = { 0,0,0,0,0,0,0,0 }; + static SECItem ivParams = { siBuffer, d, 8 }; + unsigned char result[8]; + + if( ! enc_key ) { + goto done; + } + + context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_DECRYPT, enc_key, + &ivParams); + if (!context) { + goto done; + } + + for(i = 0;i < (int)input.size();i += 8) { + s = PK11_CipherOp(context, result, &len, 8, + (unsigned char *)(((BYTE *)input)+i), 8); + + if (s != SECSuccess) { + goto done; + } + output.replace(i, result, 8); + } + + rv = PR_SUCCESS; + +done: + + if( context != NULL ) { + PK11_DestroyContext( context, PR_TRUE ); + context = NULL; + } + + return rv; +} + |